From: Rémi Bernon rbernon@codeweavers.com
Adding an info structure to the sample when the caps have changed, removing if once it has been reported to the caller.
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 | 4 ---- dlls/winegstreamer/h264_decoder.c | 7 +++++++ dlls/winegstreamer/quartz_transform.c | 2 ++ dlls/winegstreamer/wg_transform.c | 23 ++++++++++++++++++++++- dlls/winegstreamer/wma_decoder.c | 8 ++++++++ 5 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7170bad85a0..291c9d0a175 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7147,20 +7147,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 912a5bdf0b1..ea80956b038 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -569,6 +569,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 447f331d474..44f4cd44ff4 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -350,6 +350,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 b6cc51aecb7..9edcd72754f 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; @@ -504,6 +517,14 @@ 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 71369add244..57931a700eb 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -587,6 +587,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; }