[PATCH v5 0/8] MR61: winegstreamer: Dynamic transform stream format change support.
Compared to last attempt, I moved the format pointer to a dedicated `wg_transform_read_data` parameter instead of a property of the sample. Most of the transforms use `NULL` there as they don't expect or support format change. H264 decoder passes a transform format member where it tracks the current stream format. -- v5: winegstreamer: Expose output media type attributes from the stream format. winegstreamer: Support wg_transform output format change events. winegstreamer: Track caps changes and keep them with the output buffers. winegstreamer: Only filter video caps attributes when format uses 0. winegstreamer: Avoid leaking buffer list in wg_transform_read_data. winegstreamer: Return early if output buffer is too small. winegstreamer: Set wg_transform output sample size on gst_buffer_map failure. winegstreamer: Append a videoconvert element to wg_transform video output. https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)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(a)codeweavers.com> --- dlls/winegstreamer/wg_transform.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 21392a82509..ae6e948318a 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -268,6 +268,11 @@ NTSTATUS wg_transform_create(void *args) break; case WG_MAJOR_TYPE_VIDEO: + if (!(element = create_element("videoconvert", "base")) + || !transform_append_element(transform, element, &first, &last)) + goto out; + /* Let GStreamer choose a default number of threads. */ + gst_util_set_object_arg(G_OBJECT(element), "n-threads", "0"); break; case WG_MAJOR_TYPE_MPEG1_AUDIO: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
This merge request was approved by Alexandre Julliard. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)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(a)codeweavers.com> --- dlls/winegstreamer/wg_transform.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index ae6e948318a..9699d7e0a31 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -392,6 +392,7 @@ static NTSTATUS read_transform_output_data(GstBuffer *buffer, struct wg_sample * if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) { GST_ERROR("Failed to map buffer %p", buffer); + sample->size = 0; return STATUS_UNSUCCESSFUL; } @@ -464,10 +465,7 @@ NTSTATUS wg_transform_read_data(void *args) } if ((status = read_transform_output_data(transform->output_buffer, sample))) - { - sample->size = 0; return status; - } if (!(sample->flags & WG_SAMPLE_FLAG_INCOMPLETE)) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)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(a)codeweavers.com> --- dlls/winegstreamer/h264_decoder.c | 8 +++++--- dlls/winegstreamer/wma_decoder.c | 16 +++++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index de823741ba9..b7174d097ad 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -556,10 +556,12 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return hr; if (wg_sample->max_size < info.cbSize) - hr = MF_E_BUFFERTOOSMALL; - else - hr = wg_transform_read_data(decoder->wg_transform, wg_sample); + { + mf_destroy_wg_sample(wg_sample); + return MF_E_BUFFERTOOSMALL; + } + hr = wg_transform_read_data(decoder->wg_transform, wg_sample); mf_destroy_wg_sample(wg_sample); return hr; } diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 71369add244..70563649c9c 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -539,10 +539,12 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS /* WMA transform uses fixed size input samples and ignores samples with invalid sizes */ if (wg_sample->size % info.cbSize) - hr = S_OK; - else - hr = wg_transform_push_data(decoder->wg_transform, wg_sample); + { + mf_destroy_wg_sample(wg_sample); + return S_OK; + } + hr = wg_transform_push_data(decoder->wg_transform, wg_sample); mf_destroy_wg_sample(wg_sample); return hr; } @@ -579,8 +581,12 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, wg_sample->size = 0; if (wg_sample->max_size < info.cbSize) - hr = MF_E_BUFFERTOOSMALL; - else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample))) + { + mf_destroy_wg_sample(wg_sample); + return MF_E_BUFFERTOOSMALL; + } + + if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample))) { if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE) samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)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(a)codeweavers.com> --- dlls/winegstreamer/wg_transform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 9699d7e0a31..d75593daedd 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -448,6 +448,7 @@ NTSTATUS wg_transform_read_data(void *args) else if (!(transform->input = gst_buffer_list_new())) { GST_ERROR("Failed to allocate new input queue"); + gst_buffer_list_unref(input); return STATUS_NO_MEMORY; } else if ((ret = gst_pad_push_list(transform->my_src, input))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)codeweavers.com> In wg_transform we only want to remove width/height/framerate if the transform supports format change, and we want to keep the caps fixed otherwise so we can use gst_caps_is_always_compatible to monitor caps changes. 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(a)codeweavers.com> --- dlls/mf/tests/mf.c | 2 +- dlls/winegstreamer/h264_decoder.c | 8 ++++++++ dlls/winegstreamer/wg_format.c | 9 ++++++--- dlls/winegstreamer/wg_parser.c | 6 ++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index e873712085b..9de7308f9ff 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7200,7 +7200,7 @@ static void test_h264_decoder(void) "got status %#lx\n", status); hr = IMFSample_GetTotalLength(output.pSample, &length); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); - todo_wine_if(length == 1920 * 1080 * 3 / 2) + todo_wine ok(length == 0, "got length %lu\n", length); ret = IMFSample_Release(output.pSample); ok(ret == 0, "Release returned %lu\n", ret); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index b7174d097ad..66d53a3a5ce 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -75,6 +75,14 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder) if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE; + /* 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 (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format))) return E_FAIL; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 5b3a5617ff1..4cebeac9182 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -394,11 +394,14 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format) gst_video_info_set_format(&info, video_format, format->u.video.width, abs(format->u.video.height)); if ((caps = gst_video_info_to_caps(&info))) { - /* Clear some fields that shouldn't prevent us from connecting. */ for (i = 0; i < gst_caps_get_size(caps); ++i) { - gst_structure_remove_fields(gst_caps_get_structure(caps, i), - "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL); + if (!format->u.video.width) + gst_structure_remove_fields(gst_caps_get_structure(caps, i), "width", NULL); + if (!format->u.video.height) + gst_structure_remove_fields(gst_caps_get_structure(caps, i), "height", NULL); + if (!format->u.video.fps_d && !format->u.video.fps_n) + gst_structure_remove_fields(gst_caps_get_structure(caps, i), "framerate", NULL); } } return caps; diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 48b88a4b11c..7d55897aa0a 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -598,6 +598,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) { GstCaps *caps, *filter, *temp; gchar *str; + gsize i; gst_query_parse_caps(query, &filter); @@ -608,6 +609,11 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) if (!caps) return FALSE; + /* Clear some fields that shouldn't prevent us from connecting. */ + for (i = 0; i < gst_caps_get_size(caps); ++i) + gst_structure_remove_fields(gst_caps_get_structure(caps, i), + "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL); + str = gst_caps_to_string(caps); GST_LOG("Stream caps are \"%s\".", str); g_free(str); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
Hi, While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=115537 Your paranoid android. === debian11 (build log) === 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0108:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0108:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins === debian11 (build log) === 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins
From: Rémi Bernon <rbernon(a)codeweavers.com> Using a GstSample queue instead of GstBuffer queue to combine both. 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(a)codeweavers.com> --- dlls/winegstreamer/wg_transform.c | 76 +++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index d75593daedd..f8211001be9 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -51,40 +51,77 @@ struct wg_transform GstBufferList *input; guint input_max_length; GstAtomicQueue *output_queue; - GstBuffer *output_buffer; + GstSample *output_sample; + GstCaps *output_caps; }; static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) { struct wg_transform *transform = gst_pad_get_element_private(pad); + GstSample *sample; GST_LOG("transform %p, buffer %p.", transform, buffer); - gst_atomic_queue_push(transform->output_queue, buffer); + if (!(sample = gst_sample_new(buffer, transform->output_caps, NULL, NULL))) + { + GST_ERROR("Failed to allocate transform %p output sample.", transform); + gst_buffer_unref(buffer); + return GST_FLOW_ERROR; + } + gst_atomic_queue_push(transform->output_queue, sample); + gst_buffer_unref(buffer); return GST_FLOW_OK; } +static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) +{ + struct wg_transform *transform = gst_pad_get_element_private(pad); + + GST_LOG("transform %p, type \"%s\".", transform, GST_EVENT_TYPE_NAME(event)); + + switch (event->type) + { + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps(event, &caps); + + gst_caps_unref(transform->output_caps); + transform->output_caps = gst_caps_ref(caps); + break; + } + default: + GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event)); + break; + } + + gst_event_unref(event); + return TRUE; +} + NTSTATUS wg_transform_destroy(void *args) { struct wg_transform *transform = args; - GstBuffer *buffer; + GstSample *sample; if (transform->input) gst_buffer_list_unref(transform->input); gst_element_set_state(transform->container, GST_STATE_NULL); - if (transform->output_buffer) - gst_buffer_unref(transform->output_buffer); - while ((buffer = gst_atomic_queue_pop(transform->output_queue))) - gst_buffer_unref(buffer); + if (transform->output_sample) + gst_sample_unref(transform->output_sample); + while ((sample = gst_atomic_queue_pop(transform->output_queue))) + gst_sample_unref(sample); g_object_unref(transform->their_sink); g_object_unref(transform->their_src); g_object_unref(transform->container); g_object_unref(transform->my_sink); g_object_unref(transform->my_src); + gst_caps_unref(transform->output_caps); gst_atomic_queue_unref(transform->output_queue); free(transform); @@ -162,10 +199,10 @@ static bool transform_append_element(struct wg_transform *transform, GstElement NTSTATUS wg_transform_create(void *args) { struct wg_transform_create_params *params = args; - GstCaps *raw_caps = NULL, *src_caps = NULL, *sink_caps = NULL; struct wg_format output_format = *params->output_format; struct wg_format input_format = *params->input_format; GstElement *first = NULL, *last = NULL, *element; + GstCaps *raw_caps = NULL, *src_caps = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; GstPadTemplate *template = NULL; struct wg_transform *transform; @@ -194,9 +231,9 @@ NTSTATUS wg_transform_create(void *args) if (!transform->my_src) goto out; - if (!(sink_caps = wg_format_to_caps(&output_format))) + if (!(transform->output_caps = wg_format_to_caps(&output_format))) goto out; - if (!(template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps))) + if (!(template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, transform->output_caps))) goto out; transform->my_sink = gst_pad_new_from_template(template, "sink"); g_object_unref(template); @@ -204,13 +241,14 @@ NTSTATUS wg_transform_create(void *args) goto out; gst_pad_set_element_private(transform->my_sink, transform); + gst_pad_set_event_function(transform->my_sink, transform_sink_event_cb); gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb); /* Since we append conversion elements, we don't want to filter decoders * based on the actual output caps now. Matching decoders with the * raw output media type should be enough. */ - media_type = gst_structure_get_name(gst_caps_get_structure(sink_caps, 0)); + media_type = gst_structure_get_name(gst_caps_get_structure(transform->output_caps, 0)); if (!(raw_caps = gst_caps_new_empty_simple(media_type))) goto out; @@ -316,7 +354,6 @@ NTSTATUS wg_transform_create(void *args) || !gst_pad_push_event(transform->my_src, event)) goto out; - gst_caps_unref(sink_caps); gst_caps_unref(src_caps); GST_INFO("Created winegstreamer transform %p.", transform); @@ -330,8 +367,8 @@ out: gst_object_unref(transform->their_src); if (transform->my_sink) gst_object_unref(transform->my_sink); - if (sink_caps) - gst_caps_unref(sink_caps); + if (transform->output_caps) + gst_caps_unref(transform->output_caps); if (transform->my_src) gst_object_unref(transform->my_src); if (src_caps) @@ -440,6 +477,7 @@ NTSTATUS wg_transform_read_data(void *args) struct wg_transform *transform = params->transform; struct wg_sample *sample = params->sample; GstBufferList *input = transform->input; + GstBuffer *output_buffer; GstFlowReturn ret; NTSTATUS status; @@ -457,7 +495,7 @@ NTSTATUS wg_transform_read_data(void *args) return STATUS_UNSUCCESSFUL; } - if (!transform->output_buffer && !(transform->output_buffer = gst_atomic_queue_pop(transform->output_queue))) + if (!transform->output_sample && !(transform->output_sample = gst_atomic_queue_pop(transform->output_queue))) { sample->size = 0; params->result = MF_E_TRANSFORM_NEED_MORE_INPUT; @@ -465,13 +503,15 @@ NTSTATUS wg_transform_read_data(void *args) return STATUS_SUCCESS; } - if ((status = read_transform_output_data(transform->output_buffer, sample))) + output_buffer = gst_sample_get_buffer(transform->output_sample); + + if ((status = read_transform_output_data(output_buffer, sample))) return status; if (!(sample->flags & WG_SAMPLE_FLAG_INCOMPLETE)) { - gst_buffer_unref(transform->output_buffer); - transform->output_buffer = NULL; + gst_sample_unref(transform->output_sample); + transform->output_sample = NULL; } params->result = S_OK; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
From: Rémi Bernon <rbernon(a)codeweavers.com> Adding an info structure to the sample when the caps have changed, removing if once it has been reported to the caller, and optionally returning the new stream format. 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(a)codeweavers.com> --- dlls/mf/tests/mf.c | 4 ---- dlls/winegstreamer/h264_decoder.c | 7 +++++++ dlls/winegstreamer/quartz_transform.c | 2 ++ dlls/winegstreamer/wg_transform.c | 24 +++++++++++++++++++++++- dlls/winegstreamer/wma_decoder.c | 8 ++++++++ 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 9de7308f9ff..419faa61e2b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7187,20 +7187,16 @@ static void test_h264_decoder(void) ok(i == 2, "got %lu iterations\n", i); todo_wine ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len); - todo_wine 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); - todo_wine ok(length == 0, "got length %lu\n", length); ret = IMFSample_Release(output.pSample); ok(ret == 0, "Release returned %lu\n", ret); diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index 66d53a3a5ce..b3452269f04 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -571,6 +571,13 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, hr = wg_transform_read_data(decoder->wg_transform, wg_sample); mf_destroy_wg_sample(wg_sample); + + if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + { + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + } + return hr; } diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index 7986997abef..e093e2c201e 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -358,6 +358,8 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa } if (FAILED(hr)) { + if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + FIXME("Unexpected stream format change!\n"); IMediaSample_Release(output_sample); return hr; } diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index f8211001be9..06b26a04310 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -52,17 +52,27 @@ struct wg_transform guint input_max_length; GstAtomicQueue *output_queue; GstSample *output_sample; + bool output_caps_changed; GstCaps *output_caps; }; static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) { struct wg_transform *transform = gst_pad_get_element_private(pad); + GstStructure *info = NULL; GstSample *sample; GST_LOG("transform %p, buffer %p.", transform, buffer); - if (!(sample = gst_sample_new(buffer, transform->output_caps, NULL, NULL))) + if (transform->output_caps_changed && !(info = gst_structure_new_empty("format-changed"))) + { + GST_ERROR("Failed to allocate transform %p output sample info.", transform); + gst_buffer_unref(buffer); + return GST_FLOW_ERROR; + } + transform->output_caps_changed = false; + + if (!(sample = gst_sample_new(buffer, transform->output_caps, NULL, info))) { GST_ERROR("Failed to allocate transform %p output sample.", transform); gst_buffer_unref(buffer); @@ -88,6 +98,9 @@ static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent gst_event_parse_caps(event, &caps); + transform->output_caps_changed = transform->output_caps_changed + || !gst_caps_is_always_compatible(transform->output_caps, caps); + gst_caps_unref(transform->output_caps); transform->output_caps = gst_caps_ref(caps); break; @@ -505,6 +518,15 @@ NTSTATUS wg_transform_read_data(void *args) output_buffer = gst_sample_get_buffer(transform->output_sample); + if (gst_sample_get_info(transform->output_sample)) + { + gst_sample_set_info(transform->output_sample, NULL); + + params->result = MF_E_TRANSFORM_STREAM_CHANGE; + GST_INFO("Format changed detected, returning no output"); + return STATUS_SUCCESS; + } + if ((status = read_transform_output_data(output_buffer, sample))) return status; diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 70563649c9c..ca53816f134 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -593,6 +593,14 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, } mf_destroy_wg_sample(wg_sample); + + if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + { + FIXME("Unexpected stream format change!\n"); + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; + } + return hr; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
Hi, While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=115539 Your paranoid android. === debian11 (build log) === 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins === debian11 (build log) === 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins
From: Rémi Bernon <rbernon(a)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(a)codeweavers.com> --- dlls/mf/tests/mf.c | 17 ++++---- dlls/winegstreamer/gst_private.h | 3 +- dlls/winegstreamer/h264_decoder.c | 57 +++++++++++++++------------ dlls/winegstreamer/main.c | 6 ++- dlls/winegstreamer/quartz_transform.c | 2 +- dlls/winegstreamer/unixlib.h | 1 + dlls/winegstreamer/wg_transform.c | 6 +++ dlls/winegstreamer/wma_decoder.c | 2 +- 8 files changed, 54 insertions(+), 40 deletions(-) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 419faa61e2b..3fe819ba23d 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6841,7 +6841,7 @@ static void test_h264_decoder(void) 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, 60000, 1000, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE), ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE), @@ -6855,7 +6855,7 @@ static void test_h264_decoder(void) 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, 60000, 1000, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE), ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE), @@ -6869,7 +6869,7 @@ static void test_h264_decoder(void) 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, 60000, 1000, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE), ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE), @@ -6883,7 +6883,7 @@ static void test_h264_decoder(void) 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, 60000, 1000, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE), ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE), @@ -6897,7 +6897,7 @@ static void test_h264_decoder(void) 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, 60000, 1000, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE), ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2, .todo_value = TRUE), ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2, .todo_value = TRUE), @@ -7206,7 +7206,6 @@ static void test_h264_decoder(void) hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); 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 == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment); @@ -7248,14 +7247,12 @@ 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_nv12_tests; hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value); ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr); @@ -7272,9 +7269,7 @@ static void test_h264_decoder(void) time = 0xdeadbeef; hr = IMFSample_GetSampleTime(output.pSample, &time); - todo_wine ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); - todo_wine ok(time == 0, "got time %I64d\n", time); /* doesn't matter what frame rate we've selected, duration is defined by the stream */ @@ -7289,7 +7284,9 @@ static void test_h264_decoder(void) ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr); hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length); ok(hr == S_OK, "Lock returned %#lx\n", hr); + todo_wine ok(length == nv12_frame_len, "got length %lu\n", length); + if (length != nv12_frame_len) goto skip_nv12_tests; for (i = 0; i < actual_aperture.Area.cy; ++i) { diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 2a4b16079c1..159143d7e54 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -97,7 +97,8 @@ 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); HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample); -HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample); +HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample, + 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 b3452269f04..f97b6cf18c2 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -50,6 +50,7 @@ struct h264_decoder IMFMediaType *input_type; IMFMediaType *output_type; + struct wg_format wg_format; struct wg_transform *wg_transform; }; @@ -89,8 +90,10 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder) return S_OK; } -static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type) +static HRESULT fill_output_media_type(struct h264_decoder *decoder, IMFMediaType *media_type) { + IMFMediaType *default_type = decoder->output_type; + struct wg_format *wg_format = &decoder->wg_format; UINT32 value, width, height; UINT64 ratio; GUID subtype; @@ -101,8 +104,7 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &ratio))) { - if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_SIZE, &ratio))) - ratio = (UINT64)1920 << 32 | 1080; + ratio = (UINT64)wg_format->u.video.width << 32 | wg_format->u.video.height; if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ratio))) return hr; } @@ -111,24 +113,21 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FRAME_RATE, NULL))) { - if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_RATE, &ratio))) - ratio = (UINT64)30000 << 32 | 1001; + ratio = (UINT64)wg_format->u.video.fps_n << 32 | wg_format->u.video.fps_d; if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ratio))) return hr; } if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_PIXEL_ASPECT_RATIO, NULL))) { - if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_PIXEL_ASPECT_RATIO, &ratio))) - ratio = (UINT64)1 << 32 | 1; + ratio = (UINT64)1 << 32 | 1; /* FIXME: read it from format */ if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, ratio))) return hr; } if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_SAMPLE_SIZE, NULL))) { - if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_SAMPLE_SIZE, &value))) && - FAILED(hr = MFCalculateImageSize(&subtype, width, height, &value))) + if (FAILED(hr = MFCalculateImageSize(&subtype, width, height, &value))) return hr; if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, value))) return hr; @@ -136,8 +135,7 @@ static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *de if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_DEFAULT_STRIDE, NULL))) { - if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_DEFAULT_STRIDE, &value))) && - FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG *)&value))) + if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG *)&value))) return hr; if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_DEFAULT_STRIDE, value))) return hr; @@ -272,23 +270,15 @@ static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) { struct h264_decoder *decoder = impl_from_IMFTransform(iface); - UINT32 sample_size; - UINT64 frame_size; + UINT32 actual_width, actual_height; TRACE("iface %p, id %#lx, info %p.\n", iface, id, info); - if (!decoder->output_type) - sample_size = 1920 * 1088 * 2; - else if (FAILED(IMFMediaType_GetUINT32(decoder->output_type, &MF_MT_SAMPLE_SIZE, &sample_size))) - { - if (FAILED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_SIZE, &frame_size))) - sample_size = 1920 * 1088 * 2; - else - sample_size = (frame_size >> 32) * (UINT32)frame_size * 2; - } + actual_width = (decoder->wg_format.u.video.width + 15) & ~15; + actual_height = (decoder->wg_format.u.video.height + 15) & ~15; info->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; - info->cbSize = sample_size; + info->cbSize = actual_width * actual_height * 2; info->cbAlignment = 0; return S_OK; @@ -378,7 +368,7 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type))) goto done; - hr = fill_output_media_type(media_type, NULL); + hr = fill_output_media_type(decoder, media_type); done: if (SUCCEEDED(hr)) @@ -543,6 +533,8 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, struct h264_decoder *decoder = impl_from_IMFTransform(iface); MFT_OUTPUT_STREAM_INFO info; struct wg_sample *wg_sample; + struct wg_format wg_format; + UINT64 frame_rate; HRESULT hr; TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status); @@ -569,11 +561,21 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_BUFFERTOOSMALL; } - hr = wg_transform_read_data(decoder->wg_transform, wg_sample); + hr = wg_transform_read_data(decoder->wg_transform, wg_sample, + &wg_format); mf_destroy_wg_sample(wg_sample); if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { + decoder->wg_format = wg_format; + + /* keep the frame rate that was requested, GStreamer doesn't provide any */ + if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_RATE, &frame_rate))) + { + decoder->wg_format.u.video.fps_n = frame_rate >> 32; + decoder->wg_format.u.video.fps_d = (UINT32)frame_rate; + } + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; } @@ -641,6 +643,11 @@ HRESULT h264_decoder_create(REFIID riid, void **ret) decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; + decoder->wg_format.u.video.format = WG_VIDEO_FORMAT_UNKNOWN; + decoder->wg_format.u.video.width = 1920; + decoder->wg_format.u.video.height = 1080; + decoder->wg_format.u.video.fps_n = 30000; + decoder->wg_format.u.video.fps_d = 1001; *ret = &decoder->IMFTransform_iface; TRACE("Created decoder %p\n", *ret); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index c3adbb82d61..5075b3118cd 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -329,16 +329,18 @@ HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample return params.result; } -HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample) +HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample, + struct wg_format *format) { struct wg_transform_read_data_params params = { .transform = transform, .sample = sample, + .format = format, }; NTSTATUS status; - TRACE("transform %p, sample %p.\n", transform, sample); + TRACE("transform %p, sample %p, format %p.\n", transform, sample, format); if ((status = __wine_unix_call(unix_handle, unix_wg_transform_read_data, ¶ms))) return HRESULT_FROM_NT(status); diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index e093e2c201e..326b8691a42 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -350,7 +350,7 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa return hr; } - hr = wg_transform_read_data(filter->transform, &output_wg_sample); + hr = wg_transform_read_data(filter->transform, &output_wg_sample, NULL); if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { IMediaSample_Release(output_sample); diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 5911278530d..e8cdfaf7217 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -257,6 +257,7 @@ struct wg_transform_read_data_params { struct wg_transform *transform; struct wg_sample *sample; + struct wg_format *format; HRESULT result; }; diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 06b26a04310..946268ee353 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -489,8 +489,10 @@ NTSTATUS wg_transform_read_data(void *args) struct wg_transform_read_data_params *params = args; struct wg_transform *transform = params->transform; struct wg_sample *sample = params->sample; + struct wg_format *format = params->format; GstBufferList *input = transform->input; GstBuffer *output_buffer; + GstCaps *output_caps; GstFlowReturn ret; NTSTATUS status; @@ -517,11 +519,15 @@ NTSTATUS wg_transform_read_data(void *args) } output_buffer = gst_sample_get_buffer(transform->output_sample); + output_caps = gst_sample_get_caps(transform->output_sample); if (gst_sample_get_info(transform->output_sample)) { gst_sample_set_info(transform->output_sample, NULL); + if (format) + wg_format_from_caps(format, output_caps); + params->result = MF_E_TRANSFORM_STREAM_CHANGE; GST_INFO("Format changed detected, returning no output"); return STATUS_SUCCESS; diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index ca53816f134..106d32adce9 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -586,7 +586,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_BUFFERTOOSMALL; } - if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample))) + if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample, NULL))) { if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE) samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/61
Hi, While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=115540 Your paranoid android. === debian11 (build log) === 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins 0104:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0104:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins === debian11 (build log) === 0100:err:winediag:wma_decoder_create GStreamer doesn't support WMA decoding, please install appropriate plugins 0100:err:winediag:h264_decoder_create GStreamer doesn't support H.264 decoding, please install appropriate plugins
participants (3)
-
Alexandre Julliard (@julliard) -
Marvin -
Rémi Bernon