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 | 7 ++----- dlls/winegstreamer/color_convert.c | 30 ++++++++++++++++++++++++++++++ dlls/winegstreamer/video_decoder.c | 2 -- dlls/winegstreamer/wg_transform.c | 23 +++++++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index fb1b0f6c9c6..e46c2d47f1e 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -739,7 +739,6 @@ static void check_mft_get_output_current_type_(IMFTransform *transform, const st ok(hr == S_OK, "Compare returned hr %#lx.\n", hr); todo_wine_if(todo_compare) ok(result, "got result %u.\n", !!result); - IMFMediaType_Release(media_type); IMFMediaType_Release(current_type); } @@ -5978,7 +5977,6 @@ static void test_color_convert(void) ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &output_sample_desc, color_conversion_tests[i].result_bitmap); - todo_wine_if(i == 1) ok(ret <= color_conversion_tests[i].delta, "got %lu%% diff\n", ret); IMFCollection_Release(output_samples);
@@ -6223,7 +6221,7 @@ static void test_video_processor(void) .output_type_desc = output_type_desc, .expect_output_type_desc = output_type_desc, .result_bitmap = L"rgb32frame-vp.bmp", - .delta = 0, + .delta = 2, /* Windows returns 0, Wine needs 2 */ },
{ @@ -6231,7 +6229,7 @@ static void test_video_processor(void) .output_type_desc = output_type_desc_negative_stride, .expect_output_type_desc = output_type_desc_negative_stride, .result_bitmap = L"rgb32frame-vp.bmp", - .delta = 0, + .delta = 2, /* Windows returns 0, Wine needs 2 */ },
{ @@ -6623,7 +6621,6 @@ static void test_video_processor(void)
ret = check_mf_sample_collection(output_samples, &output_sample_desc, video_processor_tests[i].result_bitmap); - todo_wine_if(i == 0 || i == 1) ok(ret <= video_processor_tests[i].delta /* w1064v1507 / w1064v1809 incorrectly rescale */ || broken(ret == 25) || broken(ret == 32), diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 0eaddc687ee..e55a79fb3bc 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -363,6 +363,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM struct color_convert *impl = impl_from_IMFTransform(iface); GUID major, subtype; UINT64 frame_size; + UINT32 stride; HRESULT hr; ULONG i;
@@ -392,6 +393,20 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM IMFMediaType_Release(impl->input_type); impl->input_type = NULL; } + if (FAILED(IMFMediaType_GetUINT32(impl->input_type, &MF_MT_DEFAULT_STRIDE, &stride))) + { + if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, frame_size >> 32, (LONG *)&stride))) + { + IMFMediaType_Release(impl->input_type); + impl->input_type = NULL; + } + if ((INT32)stride < 0) stride = -stride; + if (FAILED(hr = IMFMediaType_SetUINT32(impl->input_type, &MF_MT_DEFAULT_STRIDE, stride))) + { + IMFMediaType_Release(impl->input_type); + impl->input_type = NULL; + } + }
if (impl->output_type && FAILED(hr = try_create_wg_transform(impl))) { @@ -411,6 +426,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF struct color_convert *impl = impl_from_IMFTransform(iface); GUID major, subtype; UINT64 frame_size; + UINT32 stride; HRESULT hr; ULONG i;
@@ -440,6 +456,20 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF IMFMediaType_Release(impl->output_type); impl->output_type = NULL; } + if (FAILED(IMFMediaType_GetUINT32(impl->output_type, &MF_MT_DEFAULT_STRIDE, &stride))) + { + if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, frame_size >> 32, (LONG *)&stride))) + { + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + } + if ((INT32)stride < 0) stride = -stride; + if (FAILED(hr = IMFMediaType_SetUINT32(impl->output_type, &MF_MT_DEFAULT_STRIDE, stride))) + { + IMFMediaType_Release(impl->output_type); + impl->output_type = NULL; + } + }
if (impl->input_type && FAILED(hr = try_create_wg_transform(impl))) { 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/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);