[PATCH 4/5] winegstreamer: Support dynamic wg_transform output format change.

Rémi Bernon wine at gitlab.winehq.org
Thu May 12 03:15:10 CDT 2022


From: Rémi Bernon <rbernon at 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 at codeweavers.com>
---
 dlls/winegstreamer/gst_private.h      |  3 ++-
 dlls/winegstreamer/h264_decoder.c     |  9 ++++++++-
 dlls/winegstreamer/main.c             |  6 ++++--
 dlls/winegstreamer/quartz_transform.c |  2 +-
 dlls/winegstreamer/unixlib.h          |  1 +
 dlls/winegstreamer/wg_transform.c     | 14 ++++++++++++++
 dlls/winegstreamer/wma_decoder.c      |  2 +-
 7 files changed, 31 insertions(+), 6 deletions(-)

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 58960cd632a..68f4ba7562d 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 format;
     struct wg_transform *wg_transform;
 };
 
@@ -564,7 +565,13 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
     if (wg_sample->max_size < info.cbSize)
         hr = MF_E_BUFFERTOOSMALL;
     else
-        hr = wg_transform_read_data(decoder->wg_transform, wg_sample);
+        hr = wg_transform_read_data(decoder->wg_transform, wg_sample, &decoder->format);
+
+    if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
+    {
+        samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
+        *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
+    }
 
     mf_destroy_wg_sample(wg_sample);
     return hr;
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, &params)))
         return HRESULT_FROM_NT(status);
diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c
index 447f331d474..3b43f182ecb 100644
--- a/dlls/winegstreamer/quartz_transform.c
+++ b/dlls/winegstreamer/quartz_transform.c
@@ -342,7 +342,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 87baa80e840..66f8da0a940 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -483,8 +483,10 @@ NTSTATUS wg_transform_read_data(void *args)
     struct wg_sample *sample = params->sample;
     GstBufferList *input = transform->input;
     GstBuffer *output_buffer;
+    struct wg_format format;
     GstFlowReturn ret;
     NTSTATUS status;
+    GstCaps *caps;
 
     if (!gst_buffer_list_length(transform->input))
         GST_DEBUG("Not input buffer queued");
@@ -508,6 +510,18 @@ NTSTATUS wg_transform_read_data(void *args)
     }
     output_buffer = gst_sample_get_buffer(transform->output_sample);
 
+    if (params->format && (caps = gst_sample_get_caps(transform->output_sample)))
+    {
+        wg_format_from_caps(&format, caps);
+        if (!wg_format_compare(&format, params->format))
+        {
+            *params->format = format;
+            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)))
     {
         sample->size = 0;
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 71369add244..2bad84df0de 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -580,7 +580,7 @@ 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)))
+    else 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



More information about the wine-devel mailing list