From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 11 ++-- dlls/winegstreamer/gst_private.h | 1 + dlls/winegstreamer/h264_decoder.c | 23 ++++++++- dlls/winegstreamer/main.c | 13 +++++ dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 7 +++ dlls/winegstreamer/wg_parser.c | 1 + dlls/winegstreamer/wg_transform.c | 84 +++++++++++++++++++++++++++++++ 8 files changed, 133 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 00be50c8494..80a4cf155bc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7818,7 +7818,7 @@ static void test_h264_decoder(void) todo_wine ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
- if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { hr = IMFTransform_ProcessInput(transform, 0, sample, 0); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); @@ -7826,16 +7826,14 @@ static void test_h264_decoder(void) ok(ret <= 1, "Release returned %lu\n", ret); sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine + todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr); }
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(!!output.pSample, "got pSample %p\n", output.pSample); - todo_wine ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus); ok(!output.pEvents, "got pEvents %p\n", output.pEvents); - todo_wine ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status); hr = IMFSample_GetTotalLength(output.pSample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); @@ -7858,17 +7856,16 @@ static void test_h264_decoder(void) memset(&output, 0, sizeof(output)); output.pSample = create_sample(NULL, actual_width * actual_height * 2); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(!!output.pSample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); ok(!output.pEvents, "got pEvents %p\n", output.pEvents); ok(status == 0, "got status %#lx\n", status); - if (hr != S_OK) goto skip_i420_tests;
hr = IMFSample_GetSampleTime(output.pSample, &time); ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); + todo_wine_if(time == 1334666) /* when VA-API plugin is used */ ok(time - 333666 <= 2, "got time %I64d\n", time);
duration = 0xdeadbeef; @@ -7904,7 +7901,6 @@ static void test_h264_decoder(void)
check_sample(output.pSample, i420_frame_data, output_file);
-skip_i420_tests: ret = IMFSample_Release(output.pSample); ok(ret == 0, "Release returned %lu\n", ret);
@@ -7915,6 +7911,7 @@ skip_i420_tests: memset(&output, 0, sizeof(output)); output.pSample = create_sample(NULL, actual_width * actual_height * 2); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); + todo_wine_if(hr == S_OK) /* when VA-API plugin is used */ ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(!!output.pSample, "got pSample %p\n", output.pSample); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 8348d2e8360..7b8f05dc09c 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -102,6 +102,7 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, struct wg_transform *wg_transform_create(const struct wg_format *input_format, const struct wg_format *output_format); void wg_transform_destroy(struct wg_transform *transform); +bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_format *format);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 012a7060f29..afae14fb8e7 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -467,7 +467,28 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF IMFMediaType_Release(decoder->output_type); IMFMediaType_AddRef((decoder->output_type = type));
- if (FAILED(hr = try_create_wg_transform(decoder))) + if (decoder->wg_transform) + { + struct wg_format output_format; + mf_media_type_to_wg_format(decoder->output_type, &output_format); + + /* Don't force any specific size, H264 streams already have the metadata for it + * and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later. + */ + output_format.u.video.width = 0; + output_format.u.video.height = 0; + output_format.u.video.fps_d = 0; + output_format.u.video.fps_n = 0; + + if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN + || !wg_transform_set_output_format(decoder->wg_transform, &output_format)) + { + IMFMediaType_Release(decoder->output_type); + decoder->output_type = NULL; + return MF_E_INVALIDMEDIATYPE; + } + } + else if (FAILED(hr = try_create_wg_transform(decoder))) { IMFMediaType_Release(decoder->output_type); decoder->output_type = NULL; diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index fc7b9d73285..20dcdccc606 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -348,6 +348,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample return params.result; }
+bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_format *format) +{ + struct wg_transform_set_output_format_params params = + { + .transform = transform, + .format = format, + }; + + TRACE("transform %p, format %p.\n", transform, format); + + return !__wine_unix_call(unix_handle, unix_wg_transform_set_output_format, ¶ms); +} + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { if (reason == DLL_PROCESS_ATTACH) diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index e9f472986ae..617204e97c7 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -34,6 +34,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN; +extern NTSTATUS wg_transform_set_output_format(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 860a8ab2a52..e2eef2a4932 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -263,6 +263,12 @@ struct wg_transform_read_data_params HRESULT result; };
+struct wg_transform_set_output_format_params +{ + struct wg_transform *transform; + const struct wg_format *format; +}; + enum unix_funcs { unix_wg_parser_create, @@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_create, unix_wg_transform_destroy, + unix_wg_transform_set_output_format,
unix_wg_transform_push_data, unix_wg_transform_read_data, diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 7d55897aa0a..f0487fd1ffa 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1625,6 +1625,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create), X(wg_transform_destroy), + X(wg_transform_set_output_format),
X(wg_transform_push_data), X(wg_transform_read_data), diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 070263698fb..e703e93b07e 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -51,6 +51,7 @@ struct wg_transform GstPad *my_src, *my_sink; GstPad *their_sink, *their_src; GstSegment segment; + GstQuery *drain_query;
guint input_max_length; GstAtomicQueue *input_queue; @@ -175,6 +176,31 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery g_object_unref(pool); return true; } + + case GST_QUERY_CAPS: + { + GstCaps *caps, *filter, *temp; + gchar *str; + + gst_query_parse_caps(query, &filter); + caps = gst_caps_ref(transform->output_caps); + + if (filter) + { + temp = gst_caps_intersect(caps, filter); + gst_caps_unref(caps); + caps = temp; + } + + str = gst_caps_to_string(caps); + GST_INFO("Returning caps %s", str); + g_free(str); + + gst_query_set_caps_result(query, caps); + gst_caps_unref(caps); + return true; + } + default: GST_WARNING("Ignoring "%s" query.", gst_query_type_get_name(query->type)); break; @@ -236,6 +262,7 @@ NTSTATUS wg_transform_destroy(void *args) g_object_unref(transform->container); g_object_unref(transform->my_sink); g_object_unref(transform->my_src); + gst_query_unref(transform->drain_query); gst_caps_unref(transform->output_caps); gst_atomic_queue_unref(transform->output_queue); free(transform); @@ -344,6 +371,8 @@ NTSTATUS wg_transform_create(void *args) goto out; if (!(transform->output_queue = gst_atomic_queue_new(8))) goto out; + if (!(transform->drain_query = gst_query_new_drain())) + goto out; if (!(transform->allocator = wg_allocator_create(transform_request_sample, transform))) goto out; transform->input_max_length = 1; @@ -505,6 +534,8 @@ out: gst_caps_unref(src_caps); if (transform->allocator) wg_allocator_destroy(transform->allocator); + if (transform->drain_query) + gst_query_unref(transform->drain_query); if (transform->output_queue) gst_atomic_queue_unref(transform->output_queue); if (transform->input_queue) @@ -519,6 +550,59 @@ out: return status; }
+NTSTATUS wg_transform_set_output_format(void *args) +{ + struct wg_transform_set_output_format_params *params = args; + struct wg_transform *transform = params->transform; + const struct wg_format *format = params->format; + GstSample *sample; + GstCaps *caps; + gchar *str; + + if (!(caps = wg_format_to_caps(format))) + { + GST_ERROR("Failed to convert format %p to caps.", format); + return STATUS_UNSUCCESSFUL; + } + + if (gst_caps_is_always_compatible(transform->output_caps, caps)) + { + gst_caps_unref(caps); + return STATUS_SUCCESS; + } + + if (!gst_pad_peer_query(transform->my_src, transform->drain_query)) + { + GST_ERROR("Failed to drain transform %p.", transform); + return STATUS_UNSUCCESSFUL; + } + + gst_caps_unref(transform->output_caps); + transform->output_caps = caps; + + if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure())) + { + GST_ERROR("Failed to reconfigure transform %p.", transform); + return STATUS_UNSUCCESSFUL; + } + + str = gst_caps_to_string(caps); + GST_INFO("Configured new caps %s.", str); + g_free(str); + + /* Ideally and to be fully compatible with native transform, the queued + * output buffers will need to be converted to the new output format and + * kept queued. + */ + if (transform->output_sample) + gst_sample_unref(transform->output_sample); + while ((sample = gst_atomic_queue_pop(transform->output_queue))) + gst_sample_unref(sample); + transform->output_sample = NULL; + + return STATUS_SUCCESS; +} + static void wg_sample_free_notify(void *arg) { struct wg_sample *sample = arg;
From: Rémi Bernon rbernon@codeweavers.com
Updating the internal stream format frame size accordingly.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 141 +++++++++--------------------- dlls/winegstreamer/h264_decoder.c | 7 ++ 2 files changed, 48 insertions(+), 100 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 80a4cf155bc..1d4f29e9361 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7157,144 +7157,98 @@ static void test_h264_decoder(void) ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES), }, }; - static const media_type_desc default_outputs[] = + static const DWORD input_width = 120, input_height = 248; + const media_type_desc default_outputs[] = { { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width), ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width), ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width), ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width), ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2), ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, }; - static const media_type_desc default_outputs_extra[] = - { - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - }, - }; - static const media_type_desc default_outputs_win7[] = - { - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920), - }, - }; - static const struct attribute_desc input_type_desc[] = + const struct attribute_desc input_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), {0}, }; - static const struct attribute_desc minimal_output_type_desc[] = + const struct attribute_desc minimal_output_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), {0}, }; - static const struct attribute_desc output_type_desc[] = - { - ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), - ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), - ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1), - ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1080 * 3 / 2), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - {0}, - }; - static const struct attribute_desc output_type_desc_win7[] = + const struct attribute_desc output_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), + ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height), ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1088 * 3 / 2), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2), ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), {0}, }; @@ -7307,15 +7261,6 @@ static void test_h264_decoder(void) ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2), {0}, }; - static const struct attribute_desc new_output_type_desc_win7[] = - { - ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), - ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), - ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), - ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1), - ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2), - {0}, - }; static const MFVideoArea actual_aperture = {.Area={82,84}}; static const DWORD actual_width = 96, actual_height = 96; const media_type_desc actual_outputs[] = @@ -7407,7 +7352,6 @@ static void test_h264_decoder(void) IMFMediaType *media_type; LONGLONG time, duration; IMFTransform *transform; - BOOL is_win7 = FALSE; ULONG i, ret, flags; HANDLE output_file; IMFSample *sample; @@ -7502,6 +7446,9 @@ static void test_h264_decoder(void) init_media_type(media_type, input_type_desc, 2); hr = IMFTransform_SetInputType(transform, 0, media_type, 0); ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); + init_media_type(media_type, input_type_desc, -1); + hr = IMFTransform_SetInputType(transform, 0, media_type, 0); + ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); ok(ret == 1, "Release returned %lu\n", ret);
@@ -7511,8 +7458,7 @@ static void test_h264_decoder(void) ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags); todo_wine - ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */, - "got cbSize %#lx\n", output_info.cbSize); + ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
/* output types can now be enumerated (though they are actually the same for all input types) */ @@ -7523,9 +7469,6 @@ static void test_h264_decoder(void) winetest_push_context("out %lu", i); ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr); check_media_type(media_type, default_outputs[i], -1); - hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL); - is_win7 = broken(FAILED(hr)); - check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); @@ -7553,8 +7496,8 @@ static void test_h264_decoder(void) init_media_type(media_type, minimal_output_type_desc, i + 1); } hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); - ok(hr == (is_win7 ? MF_E_INVALIDMEDIATYPE : S_OK), "SetOutputType returned %#lx.\n", hr); - init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1); + ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); + init_media_type(media_type, output_type_desc, -1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); @@ -7562,7 +7505,7 @@ static void test_h264_decoder(void)
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr); - check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1); + check_media_type(media_type, output_type_desc, -1); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret);
@@ -7574,7 +7517,6 @@ static void test_h264_decoder(void) winetest_push_context("out %lu", i); ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr); check_media_type(media_type, default_outputs[i], -1); - check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1); ret = IMFMediaType_Release(media_type); ok(ret == 0, "Release returned %lu\n", ret); winetest_pop_context(); @@ -7598,8 +7540,7 @@ static void test_h264_decoder(void) ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags); todo_wine - ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */, - "got cbSize %#lx\n", output_info.cbSize); + ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
input_count = output_count = 0xdeadbeef; @@ -7710,7 +7651,7 @@ static void test_h264_decoder(void) /* current output type is still the one we selected */ hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr); - check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1); + check_media_type(media_type, output_type_desc, -1); hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL); ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr); ret = IMFMediaType_Release(media_type); @@ -7794,10 +7735,10 @@ static void test_h264_decoder(void) /* we can change it, but only with the correct frame size */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); - init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1); + init_media_type(media_type, output_type_desc, -1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr); - init_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1); + init_media_type(media_type, new_output_type_desc, -1); hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); ret = IMFMediaType_Release(media_type); @@ -7805,7 +7746,7 @@ static void test_h264_decoder(void)
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr); - check_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1); + check_media_type(media_type, new_output_type_desc, -1); hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL); ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr); ret = IMFMediaType_Release(media_type); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index afae14fb8e7..471ad49d8e6 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -401,6 +401,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM { struct h264_decoder *decoder = impl_from_IMFTransform(iface); GUID major, subtype; + UINT64 frame_size; HRESULT hr; ULONG i;
@@ -429,6 +430,12 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM IMFMediaType_Release(decoder->input_type); IMFMediaType_AddRef((decoder->input_type = type));
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) + { + decoder->wg_format.u.video.width = frame_size >> 32; + decoder->wg_format.u.video.height = (UINT32)frame_size; + } + return S_OK; }
From: Rémi Bernon rbernon@codeweavers.com
Instead of maximum output sample size returned from GetOutputStreamInfo.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 2 +- dlls/winegstreamer/h264_decoder.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 1d4f29e9361..d09cc467dc7 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7671,7 +7671,7 @@ static void test_h264_decoder(void)
status = 0; memset(&output, 0, sizeof(output)); - output.pSample = create_sample(NULL, actual_width * actual_height * 2); + output.pSample = create_sample(NULL, actual_width * actual_height * 3 / 2); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 471ad49d8e6..43b8f83a20c 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -581,10 +581,11 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct h264_decoder *decoder = impl_from_IMFTransform(iface); - MFT_OUTPUT_STREAM_INFO info; struct wg_sample *wg_sample; struct wg_format wg_format; + UINT32 sample_size; UINT64 frame_rate; + GUID subtype; HRESULT hr;
TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -592,9 +593,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, if (count != 1) return E_INVALIDARG;
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) - return hr; - if (!decoder->wg_transform) return MF_E_TRANSFORM_TYPE_NOT_SET;
@@ -602,10 +600,16 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, samples[0].dwStatus = 0; if (!samples[0].pSample) return E_INVALIDARG;
+ if (FAILED(hr = IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &subtype))) + return hr; + if (FAILED(hr = MFCalculateImageSize(&subtype, decoder->wg_format.u.video.width, + decoder->wg_format.u.video.height, &sample_size))) + return hr; + if (FAILED(hr = wg_sample_create_mf(samples[0].pSample, &wg_sample))) return hr;
- if (wg_sample->max_size < info.cbSize) + if (wg_sample->max_size < sample_size) { wg_sample_release(wg_sample); return MF_E_BUFFERTOOSMALL;
On Fri Jul 8 09:23:33 2022 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=118553 Your paranoid android. === w864 (32 bit report) === mf: 04b0:mf: unhandled exception c0000005 at 0042ACE3 === w1064v1507 (32 bit report) === mf: 0da8:mf: unhandled exception c0000005 at 0042ACE3 === w1064v1809 (32 bit report) === mf: 1da0:mf: unhandled exception c0000005 at 0042ACE3 === w1064 (32 bit report) === mf: 1c6c:mf: unhandled exception c0000005 at 0042ACE3 === w1064_tsign (32 bit report) === mf: 0ea4:mf: unhandled exception c0000005 at 0042ACE3 === w10pro64 (32 bit report) === mf: 1e00:mf: unhandled exception c0000005 at 0042ACE3
Hmm, I'll have a look at these in case we're doing some buffer overflow somewhere, but I'm otherwise tempted to only change the test on 64bit. The test change matches what the games are doing.