-- v3: winegstreamer: Use an atomic queue for wg_transform input buffers. winegstreamer: Check H264 ProcessOutput sample against actual image size. winegstreamer: Use H264 input media type frame size when specified. winegstreamer: Implement H264 SetOutputType by reconfiguring the pipeline. winegstreamer: Release wg_transform output sample when too small. mf/tests: Add todo_wine for newer FFmpeg versions.
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/tests/mf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 2f3ee3151da..5f26b1a6238 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -5911,7 +5911,7 @@ static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_ if (expect - value + 512 > 1024) break; }
- todo_wine_if(todo) + todo_wine_if(todo && i < length / 2) ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
if (output_file) WriteFile(output_file, buffer, length, &length, NULL); @@ -6544,6 +6544,9 @@ static void test_wma_decoder(void) hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
winetest_pop_context(); + + /* some FFmpeg version request more input to complete decoding */ + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break; } todo_wine ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117495
Your paranoid android.
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39698 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39860 bytes)
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/wg_transform.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index e05432f6ac7..b0048fad644 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -314,10 +314,15 @@ static struct wg_sample *transform_request_sample(gsize size, void *context)
GST_LOG("size %#zx, context %p", size, transform);
- sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL); - if (!sample || sample->max_size < size) + if (!(sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL))) return NULL;
+ if (sample->max_size < size) + { + InterlockedDecrement(&sample->refcount); + return NULL; + } + return sample; }
On 6/23/22 12:12, Rémi Bernon wrote:
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
dlls/winegstreamer/wg_transform.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index e05432f6ac7..b0048fad644 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -314,10 +314,15 @@ static struct wg_sample *transform_request_sample(gsize size, void *context)
GST_LOG("size %#zx, context %p", size, transform);
- sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL);
- if (!sample || sample->max_size < size)
if (!(sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL))) return NULL;
if (sample->max_size < size)
{
InterlockedDecrement(&sample->refcount);
return NULL;
}
return sample;
}
I'll sign off on this because it's an improvement over the current code, but on reflection I think this pattern is not very idiomatic. More idiomatic would be to protect the whole thing with a lock, and not set the pointer to NULL in this function (but instead add an extra reference).
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 | 70 +++++++++++++++++++++++++++++++ 8 files changed, 119 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5f26b1a6238..afe85ddbf3c 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7333,7 +7333,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); @@ -7341,16 +7341,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); @@ -7373,17 +7371,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; @@ -7419,7 +7416,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);
@@ -7430,6 +7426,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..14a52df5921 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_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..1a9dcbd561c 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_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..fb2e8865089 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_format(struct wg_transform *transform, struct wg_format *format) +{ + struct wg_transform_set_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_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..3a6b162c500 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_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..ed02f025b05 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_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_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..a4aa945a708 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_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 b0048fad644..b90fde70519 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -173,6 +173,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; @@ -525,6 +550,51 @@ out: return status; }
+NTSTATUS wg_transform_set_format(void *args) +{ + struct wg_transform_set_format_params *params = args; + struct wg_transform *transform = params->transform; + GstSample *sample; + GstEvent *event; + GstCaps *caps; + gchar *str; + + if (!(caps = wg_format_to_caps(params->format))) + { + GST_ERROR("Failed to convert format to caps."); + return STATUS_UNSUCCESSFUL; + } + + if (gst_caps_is_always_compatible(transform->output_caps, caps)) + { + gst_caps_unref(caps); + return STATUS_SUCCESS; + } + + gst_caps_unref(transform->output_caps); + transform->output_caps = caps; + + if (!gst_pad_set_caps(transform->my_sink, caps) + || !(event = gst_event_new_reconfigure()) + || !gst_pad_push_event(transform->my_sink, event)) + { + GST_ERROR("Failed to reconfigure transform."); + return STATUS_UNSUCCESSFUL; + } + + str = gst_caps_to_string(caps); + GST_INFO("Configured new caps %s.", str); + g_free(str); + + 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;
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117497
Your paranoid android.
=== w864 (32 bit report) ===
mf: mf.c:4610: Test failed: Unexpected hr 0x800401f0.
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39724 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39738 bytes)
On 6/23/22 12:12, Rémi Bernon wrote:
@@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_create, unix_wg_transform_destroy,
unix_wg_transform_set_format,
unix_wg_transform_push_data, unix_wg_transform_read_data,
Perhaps set_output_format? Not that we're likely to need a set_input_format counterpart...
+NTSTATUS wg_transform_set_format(void *args) +{
- struct wg_transform_set_format_params *params = args;
- struct wg_transform *transform = params->transform;
- GstSample *sample;
- GstEvent *event;
- GstCaps *caps;
- gchar *str;
- if (!(caps = wg_format_to_caps(params->format)))
- {
GST_ERROR("Failed to convert format to caps.");
return STATUS_UNSUCCESSFUL;
- }
- if (gst_caps_is_always_compatible(transform->output_caps, caps))
- {
gst_caps_unref(caps);
return STATUS_SUCCESS;
- }
- gst_caps_unref(transform->output_caps);
- transform->output_caps = caps;
This isn't thread-safe; a simultaneous GST_EVENT_CAPS can modify the output caps.
- if (!gst_pad_set_caps(transform->my_sink, caps)
The only effect of gst_pad_set_caps() is to send a CAPS event to the sink, but you've already set transform->output_caps above.
Note also that the event won't be serialized, which begs the question—should it be? I suspect the answer is, "well, we actually need buffers already sent to be re-decoded in the new format, which GStreamer doesn't support". Which would be a helpful thing to write in a comment if so.
Since we do flush output samples below, I suspect we should explicitly try to flush out samples which haven't been received yet before doing anything else in this function, which neatly solves all of the thread safety problems as well. I think the correct way to do that is with flush-start + flush-stop; a DRAIN query might work but I'm not sure if it's guaranteed to force decoders to stop waiting for more data before sending what they have.
|| !(event = gst_event_new_reconfigure())
|| !gst_pad_push_event(transform->my_sink, event))
- {
GST_ERROR("Failed to reconfigure transform.");
return STATUS_UNSUCCESSFUL;
- }
- str = gst_caps_to_string(caps);
- GST_INFO("Configured new caps %s.", str);
- g_free(str);
- 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 | 87 +++++++++++++++++-------------- dlls/winegstreamer/h264_decoder.c | 7 +++ 2 files changed, 55 insertions(+), 39 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index afe85ddbf3c..7b598ba7dac 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6674,14 +6674,17 @@ 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; + static const DWORD align_input_width = (input_width + 15) & ~15; + static const DWORD align_input_height = (input_height + 15) & ~15; + 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), @@ -6691,7 +6694,7 @@ static void test_h264_decoder(void) 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), @@ -6701,7 +6704,7 @@ static void test_h264_decoder(void) 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), @@ -6711,7 +6714,7 @@ static void test_h264_decoder(void) 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), @@ -6721,97 +6724,98 @@ static void test_h264_decoder(void) 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), }, }; - static const media_type_desc default_outputs_extra[] = + const media_type_desc default_outputs_extra[] = { { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), + 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), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), + 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), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), + 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), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400), + 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), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200), + 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), }, }; - static const media_type_desc default_outputs_win7[] = + 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, align_input_width, align_input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), + ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), + ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440), + ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), }, { - ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920), + ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 2), }, }; - 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[] = + 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_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 * 1080 * 3 / 2), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 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_win7[] = { 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, align_input_width, align_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 * align_input_height * 3 / 2), ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), {0}, }; @@ -7017,6 +7021,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);
@@ -7026,7 +7033,8 @@ 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 */, + ok(output_info.cbSize == input_width * input_height * 2 + || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
@@ -7113,7 +7121,8 @@ 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 */, + ok(output_info.cbSize == input_width * input_height * 2 + || broken(output_info.cbSize == align_input_width * align_input_height * 2) /* Win7 */, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 1a9dcbd561c..2ece7dee5b1 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; }
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117498
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
mf: mf.c:7051: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7079: Test failed: SetOutputType returned 0. mf.c:7082: Test failed: SetOutputType returned 0xc00d36b4. mf.c:7100: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7226: Test failed: out 0: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 1: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 2: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 3: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 4: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001
=== w7u_adm (32 bit report) ===
mf: mf.c:7051: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7079: Test failed: SetOutputType returned 0. mf.c:7082: Test failed: SetOutputType returned 0xc00d36b4. mf.c:7100: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7226: Test failed: out 0: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 1: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 2: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 3: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 4: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001
=== w7u_el (32 bit report) ===
mf: mf.c:7051: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7051: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7051: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7079: Test failed: SetOutputType returned 0. mf.c:7082: Test failed: SetOutputType returned 0xc00d36b4. mf.c:7100: Test failed: out 0: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 0: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 1: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 1: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 2: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 2: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 3: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 3: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 44640 mf.c:7100: Test failed: out 4: "MF_MT_FRAME_SIZE" mismatch, type 21, value 120:248 mf.c:7100: Test failed: out 4: "MF_MT_SAMPLE_SIZE" mismatch, type 19, value 59520 mf.c:7226: Test failed: out 0: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 1: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 2: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 3: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001 mf.c:7226: Test failed: out 4: "MF_MT_FRAME_RATE" mismatch, type 21, value 30000:1001
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39732 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39709 bytes)
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 | 114 ++++++------------------------ dlls/winegstreamer/h264_decoder.c | 14 ++-- 2 files changed, 32 insertions(+), 96 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7b598ba7dac..5108d2b2523 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6675,8 +6675,6 @@ static void test_h264_decoder(void) }, }; static const DWORD input_width = 120, input_height = 248; - static const DWORD align_input_width = (input_width + 15) & ~15; - static const DWORD align_input_height = (input_height + 15) & ~15; const media_type_desc default_outputs[] = { { @@ -6688,6 +6686,9 @@ static void test_h264_decoder(void) 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), @@ -6698,6 +6699,9 @@ static void test_h264_decoder(void) 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), @@ -6708,6 +6712,9 @@ static void test_h264_decoder(void) 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), @@ -6718,6 +6725,9 @@ static void test_h264_decoder(void) 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), @@ -6728,57 +6738,9 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), - }, - }; - const media_type_desc default_outputs_extra[] = - { - { - 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), - }, - { - 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), - }, - { - 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), - }, - { - 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), - }, - { 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), - }, - }; - const media_type_desc default_outputs_win7[] = - { - { - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 3 / 2), - }, - { - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_input_height), - ATTR_UINT32(MF_MT_SAMPLE_SIZE, align_input_width * align_input_height * 2), + /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */ }, }; const struct attribute_desc input_type_desc[] = @@ -6807,18 +6769,6 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), {0}, }; - const struct attribute_desc output_type_desc_win7[] = - { - ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), - ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), - ATTR_RATIO(MF_MT_FRAME_SIZE, align_input_width, align_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 * align_input_height * 3 / 2), - ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), - {0}, - }; static const struct attribute_desc new_output_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -6828,15 +6778,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[] = @@ -6928,7 +6869,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; @@ -7033,9 +6973,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 == input_width * input_height * 2 - || broken(output_info.cbSize == align_input_width * align_input_height * 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) */ @@ -7046,9 +6984,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(); @@ -7076,8 +7011,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); @@ -7085,7 +7020,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);
@@ -7097,7 +7032,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(); @@ -7121,9 +7055,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 == input_width * input_height * 2 - || broken(output_info.cbSize == align_input_width * align_input_height * 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; @@ -7234,7 +7166,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); @@ -7254,7 +7186,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); @@ -7318,10 +7250,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); @@ -7329,7 +7261,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 2ece7dee5b1..561a3c1578c 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;
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 tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117499
Your paranoid android.
=== w8 (32 bit report) ===
mf: mf.c:4610: Test failed: Unexpected hr 0x800401f0.
=== w1064v1507 (64 bit report) ===
mf: 0d4c:mf: unhandled exception c0000005 at 00007FFFE1D1A901
=== debian11 (32 bit report) ===
Report validation errors: mf:mf prints too much data (39752 bytes)
=== debian11 (32 bit WoW report) ===
Report validation errors: mf:mf prints too much data (39710 bytes)
From: Rémi Bernon rbernon@codeweavers.com
And push them one by one until an output buffer is generated, to avoid generating multiple output buffers without a backing wg_sample.
This makes zero-copy more efficient for games which queue multiple input buffers before checking output, such as Yakuza 4.
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/winegstreamer/wg_transform.c | 40 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 21 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index b90fde70519..73bec6d35e4 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -51,10 +51,10 @@ struct wg_transform GstPad *my_src, *my_sink; GstPad *their_sink, *their_src; GstSegment segment; - GstBufferList *input; guint input_max_length; guint output_plane_align; struct wg_sample *output_wg_sample; + GstAtomicQueue *input_queue; GstAtomicQueue *output_queue; GstSample *output_sample; bool output_caps_changed; @@ -240,9 +240,11 @@ NTSTATUS wg_transform_destroy(void *args) { struct wg_transform *transform = args; GstSample *sample; + GstBuffer *buffer;
- if (transform->input) - gst_buffer_list_unref(transform->input); + while ((buffer = gst_atomic_queue_pop(transform->input_queue))) + gst_buffer_unref(buffer); + gst_atomic_queue_unref(transform->input_queue);
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -371,7 +373,7 @@ NTSTATUS wg_transform_create(void *args) return STATUS_NO_MEMORY; if (!(transform->container = gst_bin_new("wg_transform"))) goto out; - if (!(transform->input = gst_buffer_list_new())) + if (!(transform->input_queue = gst_atomic_queue_new(8))) goto out; if (!(transform->output_queue = gst_atomic_queue_new(8))) goto out; @@ -538,8 +540,8 @@ out: wg_allocator_destroy(transform->allocator); if (transform->output_queue) gst_atomic_queue_unref(transform->output_queue); - if (transform->input) - gst_buffer_list_unref(transform->input); + if (transform->input_queue) + gst_atomic_queue_unref(transform->input_queue); if (transform->container) { gst_element_set_state(transform->container, GST_STATE_NULL); @@ -610,7 +612,7 @@ NTSTATUS wg_transform_push_data(void *args) GstBuffer *buffer; guint length;
- length = gst_buffer_list_length(transform->input); + length = gst_atomic_queue_length(transform->input_queue); if (length >= transform->input_max_length) { GST_INFO("Refusing %u bytes, %u buffers already queued", sample->size, length); @@ -636,7 +638,7 @@ NTSTATUS wg_transform_push_data(void *args) GST_BUFFER_DURATION(buffer) = sample->duration * 100; if (!(sample->flags & WG_SAMPLE_FLAG_SYNC_POINT)) GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT); - gst_buffer_list_insert(transform->input, -1, buffer); + gst_atomic_queue_push(transform->input_queue, buffer);
params->result = S_OK; return STATUS_SUCCESS; @@ -791,9 +793,8 @@ NTSTATUS wg_transform_read_data(void *args) struct wg_transform *transform = params->transform; struct wg_sample *sample = params->sample; struct wg_format *format = params->format; + GstBuffer *output_buffer, *input_buffer; GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *output_buffer; - GstBufferList *input; GstCaps *output_caps; bool discard_data; NTSTATUS status; @@ -802,17 +803,14 @@ NTSTATUS wg_transform_read_data(void *args) InterlockedIncrement(&sample->refcount); InterlockedExchangePointer((void **)&transform->output_wg_sample, sample);
- if (!gst_buffer_list_length(transform->input)) - GST_DEBUG("Not input buffer queued"); - else if ((input = gst_buffer_list_new())) + while (!transform->output_sample && ret == GST_FLOW_OK) { - ret = gst_pad_push_list(transform->my_src, transform->input); - transform->input = input; - } - else - { - GST_ERROR("Failed to allocate new input queue"); - ret = GST_FLOW_ERROR; + if ((input_buffer = gst_atomic_queue_pop(transform->input_queue))) + ret = gst_pad_push(transform->my_src, input_buffer); + transform->output_sample = gst_atomic_queue_pop(transform->output_queue); + + if (!input_buffer) + break; }
/* Remove the sample so transform_request_sample cannot use it */ @@ -826,7 +824,7 @@ NTSTATUS wg_transform_read_data(void *args) return STATUS_UNSUCCESSFUL; }
- if (!transform->output_sample && !(transform->output_sample = gst_atomic_queue_pop(transform->output_queue))) + if (!transform->output_sample) { sample->size = 0; params->result = MF_E_TRANSFORM_NEED_MORE_INPUT;
On 6/23/22 12:12, Rémi Bernon wrote:
@@ -802,17 +803,14 @@ NTSTATUS wg_transform_read_data(void *args) InterlockedIncrement(&sample->refcount); InterlockedExchangePointer((void **)&transform->output_wg_sample, sample);
- if (!gst_buffer_list_length(transform->input))
GST_DEBUG("Not input buffer queued");
- else if ((input = gst_buffer_list_new()))
- while (!transform->output_sample && ret == GST_FLOW_OK) {
ret = gst_pad_push_list(transform->my_src, transform->input);
transform->input = input;
- }
- else
- {
GST_ERROR("Failed to allocate new input queue");
ret = GST_FLOW_ERROR;
if ((input_buffer = gst_atomic_queue_pop(transform->input_queue)))
ret = gst_pad_push(transform->my_src, input_buffer);
transform->output_sample = gst_atomic_queue_pop(transform->output_queue);
if (!input_buffer)
break; }
This is correct anyway, but the "ret == GST_FLOW_OK" feels wrong, as does continuing to process output samples even after we've hit an error condition. Would you mind moving the error check and break into the loop?
v3: Fix Win7 test failures in PATCH 5.
Sorry, the failures were actually introduced in PATCH 4, I'll move the fixes and update the MR.