[PATCH v3 3/6] winegstreamer: Implement H264 SetOutputType by reconfiguring the pipeline.
Rémi Bernon
wine at gitlab.winehq.org
Thu Jun 23 12:12:40 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/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;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
More information about the wine-devel
mailing list