From: Eric Pouech eric.pouech@gmail.com
The app I'm considering opens a video_processor on its own, with a NV12 format on input and a ARGB32 format on output.
Tested on Windows: the samples are flipped vertically. While Wine keeps them untouched.
So added a videoflip in the video processor to be activated when needed. This patch depends on MR!2159.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/mf/tests/transform.c | 16 ++++++---------- dlls/winegstreamer/color_convert.c | 4 ++++ dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/mfplat.c | 26 +++++++++++++++----------- dlls/winegstreamer/video_decoder.c | 2 -- dlls/winegstreamer/video_processor.c | 6 ++++++ dlls/winegstreamer/wg_transform.c | 23 +++++++++++++++++++++++ dlls/winegstreamer/wmv_decoder.c | 3 +++ 8 files changed, 59 insertions(+), 23 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 5717ed0d2ab..828b6bdabd8 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -5356,7 +5356,7 @@ static void test_wmv_decoder(void) ok(i == 1, "got %lu output samples\n", i);
ret = check_mf_sample_collection(output_samples, &output_sample_desc_rgb, L"rgb32frame-vp.bmp"); - ok(ret == 0, "got %lu%% diff\n", ret); + ok(ret <= 5, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples); winetest_pop_context();
@@ -5407,7 +5407,7 @@ static void test_wmv_decoder(void) ok(i == 1, "got %lu output samples\n", i);
ret = check_mf_sample_collection(output_samples, &output_sample_desc_rgb, L"rgb32frame-vp.bmp"); - ok(ret == 0, "got %lu%% diff\n", ret); + ok(ret <= 5, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples); winetest_pop_context();
@@ -5458,7 +5458,7 @@ static void test_wmv_decoder(void) ok(i == 1, "got %lu output samples\n", i);
ret = check_mf_sample_collection(output_samples, &output_sample_desc_rgb, L"rgb32frame-vp.bmp"); - ok(ret == 0, "got %lu%% diff\n", ret); + ok(ret <= 5, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples); winetest_pop_context();
@@ -6149,8 +6149,7 @@ static void test_color_convert(void) ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp"); - todo_wine - ok(ret <= 4 /* small and harmless diff in Wine vs Windows */, "got %lu%% diff\n", ret); + ok(ret <= 6 /* small and harmless diff in Wine vs Windows */, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples);
output_sample = create_sample(NULL, output_info.cbSize); @@ -6812,8 +6811,7 @@ static void test_video_processor(void) ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp"); - todo_wine - ok(ret == 0 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret); + ok(ret <= 2 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples);
output_sample = create_sample(NULL, output_info.cbSize); @@ -6883,8 +6881,7 @@ static void test_video_processor(void) ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp"); - todo_wine - ok(ret == 0 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret); + ok(ret <= 2 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples);
output_sample = create_sample(NULL, output_info.cbSize); @@ -6954,7 +6951,6 @@ static void test_video_processor(void) ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame.bmp"); - todo_wine ok(ret <= 6 || broken(ret <= 32) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples);
diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 0eaddc687ee..0bec0ad4895 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -106,10 +106,14 @@ static HRESULT try_create_wg_transform(struct color_convert *impl) mf_media_type_to_wg_format(impl->input_type, &input_format); if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE; + if (!wg_video_adapt_from_mf_stride(&input_format, impl->input_type)) + input_format.u.video.height = abs(input_format.u.video.height);
mf_media_type_to_wg_format(impl->output_type, &output_format); if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE; + if (!wg_video_adapt_from_mf_stride(&output_format, impl->output_type)) + output_format.u.video.height = abs(output_format.u.video.height);
if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format))) return E_FAIL; diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 04ec84c7936..4393aa162ec 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -152,6 +152,8 @@ unsigned int wg_format_get_stride(const struct wg_format *format);
bool wg_video_format_is_rgb(enum wg_video_format format);
+bool wg_video_adapt_from_mf_stride(struct wg_format *format, IMFMediaType *type); + HRESULT aac_decoder_create(REFIID riid, void **ret); HRESULT h264_decoder_create(REFIID riid, void **ret); HRESULT video_processor_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 9cf98ec9dc4..65ef9b3b46f 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -697,7 +697,7 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *sub { UINT64 frame_rate, frame_size; MFVideoArea aperture; - UINT32 size, stride; + UINT32 size;
if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) { @@ -727,16 +727,6 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *sub }
format->u.video.format = mf_video_format_to_wg(subtype); - - if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_DEFAULT_STRIDE, &stride))) - { - if ((int)stride < 0) - format->u.video.height = -format->u.video.height; - } - else if (wg_video_format_is_rgb(format->u.video.format)) - { - format->u.video.height = -format->u.video.height; - } }
static void mf_media_type_to_wg_format_audio_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format) @@ -901,3 +891,17 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } + +bool wg_video_adapt_from_mf_stride(struct wg_format *format, IMFMediaType *type) +{ + UINT32 stride; + + if (format->major_type == WG_MAJOR_TYPE_VIDEO) + { + if (!SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_DEFAULT_STRIDE, &stride))) + return false; + if ((int)stride < 0) + format->u.video.height = -format->u.video.height; + } + return true; +} diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 66df8173038..0087e12abe3 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -310,8 +310,6 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF { mf_media_type_to_wg_format(decoder->output_type, &output_format);
- output_format.u.video.width = frame_size >> 32; - output_format.u.video.height = (UINT32)frame_size; output_format.u.video.fps_d = 0; output_format.u.video.fps_n = 0;
diff --git a/dlls/winegstreamer/video_processor.c b/dlls/winegstreamer/video_processor.c index 21bc46b0bb3..46103b46f14 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -96,10 +96,16 @@ static HRESULT try_create_wg_transform(struct video_processor *impl) mf_media_type_to_wg_format(impl->input_type, &input_format); if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE; + if (!wg_video_adapt_from_mf_stride(&input_format, impl->input_type) + && wg_video_format_is_rgb(input_format.u.video.format)) + input_format.u.video.height = -input_format.u.video.height;
mf_media_type_to_wg_format(impl->output_type, &output_format); if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE; + if (!wg_video_adapt_from_mf_stride(&output_format, impl->output_type) + && wg_video_format_is_rgb(output_format.u.video.format)) + output_format.u.video.height = -output_format.u.video.height;
if (!(impl->wg_transform = wg_transform_create(&input_format, &output_format))) return E_FAIL; diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index ccdd90361fc..3cd0ae1e728 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -56,6 +56,9 @@ struct wg_transform guint input_max_length; GstAtomicQueue *input_queue;
+ bool input_is_flipped; + GstElement *video_flip; + guint output_plane_align; struct wg_sample *output_wg_sample; GstAtomicQueue *output_queue; @@ -347,6 +350,11 @@ static struct wg_sample *transform_request_sample(gsize size, void *context) return InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL); }
+static bool wg_format_video_is_flipped(const struct wg_format *format) +{ + return format->major_type == WG_MAJOR_TYPE_VIDEO && (format->u.video.height < 0); +} + NTSTATUS wg_transform_create(void *args) { struct wg_transform_create_params *params = args; @@ -470,6 +478,12 @@ NTSTATUS wg_transform_create(void *args)
case WG_MAJOR_TYPE_VIDEO: case WG_MAJOR_TYPE_VIDEO_WMV: + if (!(transform->video_flip = create_element("videoflip", "base")) + || !transform_append_element(transform, transform->video_flip, &first, &last)) + goto out; + transform->input_is_flipped = wg_format_video_is_flipped(&input_format); + if (transform->input_is_flipped != wg_format_video_is_flipped(&output_format)) + gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", "vertical-flip"); if (!(element = create_element("videoconvert", "base")) || !transform_append_element(transform, element, &first, &last)) goto out; @@ -588,6 +602,15 @@ NTSTATUS wg_transform_set_output_format(void *args) gst_caps_unref(transform->output_caps); transform->output_caps = caps;
+ if (transform->video_flip) + { + const char *value; + if (transform->input_is_flipped != wg_format_video_is_flipped(format)) + value = "vertical-flip"; + else + value = "none"; + gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", value); + } if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure())) { GST_ERROR("Failed to reconfigure transform %p.", transform); diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index 82c69776bd6..14867422565 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -584,6 +584,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
+ if (wg_video_format_is_rgb(wg_format.u.video.format)) + wg_format.u.video.height = -wg_format.u.video.height; + decoder->output_subtype = type->subtype; decoder->output_format = wg_format;