From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index db2a5037476..525a4a0426d 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -324,6 +324,8 @@ NTSTATUS wg_transform_create(void *args) if (!transform->my_src) goto out;
+ GST_INFO("transform %p input caps %"GST_PTR_FORMAT, transform, src_caps); + gst_pad_set_element_private(transform->my_src, transform); gst_pad_set_query_function(transform->my_src, transform_src_query_cb);
@@ -336,6 +338,8 @@ NTSTATUS wg_transform_create(void *args) if (!transform->my_sink) goto out;
+ GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, transform->output_caps); + gst_pad_set_element_private(transform->my_sink, transform); gst_pad_set_event_function(transform->my_sink, transform_sink_event_cb); gst_pad_set_query_function(transform->my_sink, transform_sink_query_cb); @@ -505,6 +509,8 @@ NTSTATUS wg_transform_set_output_format(void *args) } transform->output_format = *format;
+ GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, caps); + if (gst_caps_is_always_compatible(transform->output_caps, caps)) { gst_caps_unref(caps); @@ -795,6 +801,8 @@ NTSTATUS wg_transform_read_data(void *args) { GST_MINI_OBJECT_FLAG_UNSET(transform->output_sample, GST_SAMPLE_FLAG_WG_CAPS_CHANGED);
+ GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, output_caps); + if (format) { gsize plane_align = transform->attrs.output_plane_align;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 114 ++++++++++++++++-------------- 1 file changed, 59 insertions(+), 55 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 525a4a0426d..7ab798244b8 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -125,74 +125,78 @@ static gboolean transform_src_query_cb(GstPad *pad, GstObject *parent, GstQuery } }
-static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) +static gboolean transform_sink_query_allocation(struct wg_transform *transform, GstQuery *query) { - struct wg_transform *transform = gst_pad_get_element_private(pad); + gsize plane_align = transform->attrs.output_plane_align; + GstStructure *config, *params; + GstVideoAlignment align; + gboolean needs_pool; + GstBufferPool *pool; + GstVideoInfo info; + GstCaps *caps;
- GST_LOG("transform %p, type "%s".", transform, gst_query_type_get_name(query->type)); + gst_query_parse_allocation(query, &caps, &needs_pool); + if (stream_type_from_caps(caps) != GST_STREAM_TYPE_VIDEO || !needs_pool) + return false;
- switch (query->type) - { - case GST_QUERY_ALLOCATION: - { - gsize plane_align = transform->attrs.output_plane_align; - GstStructure *config, *params; - GstVideoAlignment align; - gboolean needs_pool; - GstBufferPool *pool; - GstVideoInfo info; - GstCaps *caps; + if (!gst_video_info_from_caps(&info, caps) + || !(pool = gst_video_buffer_pool_new())) + return false;
- gst_query_parse_allocation(query, &caps, &needs_pool); - if (stream_type_from_caps(caps) != GST_STREAM_TYPE_VIDEO || !needs_pool) - break; + align_video_info_planes(plane_align, &info, &align);
- if (!gst_video_info_from_caps(&info, caps) - || !(pool = gst_video_buffer_pool_new())) - break; + if ((params = gst_structure_new("video-meta", + "padding-top", G_TYPE_UINT, align.padding_top, + "padding-bottom", G_TYPE_UINT, align.padding_bottom, + "padding-left", G_TYPE_UINT, align.padding_left, + "padding-right", G_TYPE_UINT, align.padding_right, + NULL))) + { + gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, params); + gst_structure_free(params); + } + + if (!(config = gst_buffer_pool_get_config(pool))) + GST_ERROR("Failed to get pool %p config.", pool); + else + { + gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); + gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); + gst_buffer_pool_config_set_video_alignment(config, &align);
- align_video_info_planes(plane_align, &info, &align); + gst_buffer_pool_config_set_params(config, caps, + info.size, 0, 0); + gst_buffer_pool_config_set_allocator(config, transform->allocator, NULL); + if (!gst_buffer_pool_set_config(pool, config)) + GST_ERROR("Failed to set pool %p config.", pool); + }
- if ((params = gst_structure_new("video-meta", - "padding-top", G_TYPE_UINT, align.padding_top, - "padding-bottom", G_TYPE_UINT, align.padding_bottom, - "padding-left", G_TYPE_UINT, align.padding_left, - "padding-right", G_TYPE_UINT, align.padding_right, - NULL))) - { - gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, params); - gst_structure_free(params); - } + /* Prevent pool reconfiguration, we don't want another alignment. */ + if (!gst_buffer_pool_set_active(pool, true)) + GST_ERROR("Pool %p failed to activate.", pool);
- if (!(config = gst_buffer_pool_get_config(pool))) - GST_ERROR("Failed to get pool %p config.", pool); - else - { - gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); - gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT); - gst_buffer_pool_config_set_video_alignment(config, &align); - - gst_buffer_pool_config_set_params(config, caps, - info.size, 0, 0); - gst_buffer_pool_config_set_allocator(config, transform->allocator, NULL); - if (!gst_buffer_pool_set_config(pool, config)) - GST_ERROR("Failed to set pool %p config.", pool); - } + gst_query_add_allocation_pool(query, pool, info.size, 0, 0); + gst_query_add_allocation_param(query, transform->allocator, NULL);
- /* Prevent pool reconfiguration, we don't want another alignment. */ - if (!gst_buffer_pool_set_active(pool, true)) - GST_ERROR("Pool %p failed to activate.", pool); + GST_INFO("Proposing pool %p, buffer size %#zx, allocator %p, for query %p.", + pool, info.size, transform->allocator, query);
- gst_query_add_allocation_pool(query, pool, info.size, 0, 0); - gst_query_add_allocation_param(query, transform->allocator, NULL); + g_object_unref(pool); + return true; +}
- GST_INFO("Proposing pool %p, buffer size %#zx, allocator %p, for query %p.", - pool, info.size, transform->allocator, query); +static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) +{ + struct wg_transform *transform = gst_pad_get_element_private(pad);
- g_object_unref(pool); - return true; - } + GST_LOG("transform %p, type "%s".", transform, gst_query_type_get_name(query->type));
+ switch (query->type) + { + case GST_QUERY_ALLOCATION: + if (transform_sink_query_allocation(transform, query)) + return true; + break; case GST_QUERY_CAPS: { GstCaps *caps, *filter, *temp;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 48 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 7ab798244b8..dd80560016f 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -185,6 +185,30 @@ static gboolean transform_sink_query_allocation(struct wg_transform *transform, return true; }
+static gboolean transform_sink_query_caps(struct wg_transform *transform, GstQuery *query) +{ + GstCaps *caps, *filter, *temp; + + GST_LOG("transform %p, query %"GST_PTR_FORMAT, transform, query); + + gst_query_parse_caps(query, &filter); + if (!(caps = wg_format_to_caps(&transform->output_format))) + return false; + + if (filter) + { + temp = gst_caps_intersect(caps, filter); + gst_caps_unref(caps); + caps = temp; + } + + GST_INFO("Returning caps %" GST_PTR_FORMAT, caps); + + gst_query_set_caps_result(query, caps); + gst_caps_unref(caps); + return true; +} + static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) { struct wg_transform *transform = gst_pad_get_element_private(pad); @@ -198,27 +222,9 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery return true; break; case GST_QUERY_CAPS: - { - GstCaps *caps, *filter, *temp; - - gst_query_parse_caps(query, &filter); - if (!(caps = wg_format_to_caps(&transform->output_format))) - break; - - if (filter) - { - temp = gst_caps_intersect(caps, filter); - gst_caps_unref(caps); - caps = temp; - } - - GST_INFO("Returning caps %" GST_PTR_FORMAT, caps); - - gst_query_set_caps_result(query, caps); - gst_caps_unref(caps); - return true; - } - + if (transform_sink_query_caps(transform, query)) + return true; + break; default: GST_WARNING("Ignoring "%s" query.", gst_query_type_get_name(query->type)); break;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index dd80560016f..0c796bddf57 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -233,6 +233,19 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery return gst_pad_query_default(pad, parent, query); }
+static void transform_sink_event_caps(struct wg_transform *transform, GstEvent *event) +{ + GstCaps *caps; + + 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); +} + static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) { struct wg_transform *transform = gst_pad_get_element_private(pad); @@ -241,22 +254,12 @@ static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent
switch (event->type) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - 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; - } - default: - GST_WARNING("Ignoring "%s" event.", GST_EVENT_TYPE_NAME(event)); - break; + case GST_EVENT_CAPS: + transform_sink_event_caps(transform, event); + break; + default: + GST_WARNING("Ignoring "%s" event.", GST_EVENT_TYPE_NAME(event)); + break; }
gst_event_unref(event);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 53 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 0c796bddf57..56523c7606a 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -87,7 +87,7 @@ static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, Gst struct wg_transform *transform = gst_pad_get_element_private(pad); GstSample *sample;
- GST_LOG("transform %p, buffer %p.", transform, buffer); + GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, buffer);
if (!(sample = gst_sample_new(buffer, transform->output_caps, NULL, NULL))) { @@ -107,7 +107,7 @@ static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, Gst
static gboolean transform_src_query_latency(struct wg_transform *transform, GstQuery *query) { - GST_LOG("transform %p, query %p", transform, query); + GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, query); gst_query_set_latency(query, transform->attrs.low_latency, 0, 0); return true; } @@ -121,6 +121,7 @@ static gboolean transform_src_query_cb(GstPad *pad, GstObject *parent, GstQuery case GST_QUERY_LATENCY: return transform_src_query_latency(transform, query); default: + GST_TRACE("transform %p, ignoring %"GST_PTR_FORMAT, transform, query); return gst_pad_query_default(pad, parent, query); } } @@ -135,6 +136,8 @@ static gboolean transform_sink_query_allocation(struct wg_transform *transform, GstVideoInfo info; GstCaps *caps;
+ GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, query); + gst_query_parse_allocation(query, &caps, &needs_pool); if (stream_type_from_caps(caps) != GST_STREAM_TYPE_VIDEO || !needs_pool) return false; @@ -157,7 +160,7 @@ static gboolean transform_sink_query_allocation(struct wg_transform *transform, }
if (!(config = gst_buffer_pool_get_config(pool))) - GST_ERROR("Failed to get pool %p config.", pool); + GST_ERROR("Failed to get %"GST_PTR_FORMAT" config.", pool); else { gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); @@ -168,17 +171,17 @@ static gboolean transform_sink_query_allocation(struct wg_transform *transform, info.size, 0, 0); gst_buffer_pool_config_set_allocator(config, transform->allocator, NULL); if (!gst_buffer_pool_set_config(pool, config)) - GST_ERROR("Failed to set pool %p config.", pool); + GST_ERROR("Failed to set %"GST_PTR_FORMAT" config.", pool); }
/* Prevent pool reconfiguration, we don't want another alignment. */ if (!gst_buffer_pool_set_active(pool, true)) - GST_ERROR("Pool %p failed to activate.", pool); + GST_ERROR("%"GST_PTR_FORMAT" failed to activate.", pool);
gst_query_add_allocation_pool(query, pool, info.size, 0, 0); gst_query_add_allocation_param(query, transform->allocator, NULL);
- GST_INFO("Proposing pool %p, buffer size %#zx, allocator %p, for query %p.", + GST_INFO("Proposing %"GST_PTR_FORMAT", buffer size %#zx, %"GST_PTR_FORMAT", for %"GST_PTR_FORMAT, pool, info.size, transform->allocator, query);
g_object_unref(pool); @@ -189,7 +192,7 @@ static gboolean transform_sink_query_caps(struct wg_transform *transform, GstQue { GstCaps *caps, *filter, *temp;
- GST_LOG("transform %p, query %"GST_PTR_FORMAT, transform, query); + GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, query);
gst_query_parse_caps(query, &filter); if (!(caps = wg_format_to_caps(&transform->output_format))) @@ -213,23 +216,21 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery { struct wg_transform *transform = gst_pad_get_element_private(pad);
- GST_LOG("transform %p, type "%s".", transform, gst_query_type_get_name(query->type)); - switch (query->type) { - case GST_QUERY_ALLOCATION: - if (transform_sink_query_allocation(transform, query)) - return true; - break; - case GST_QUERY_CAPS: - if (transform_sink_query_caps(transform, query)) - return true; - break; - default: - GST_WARNING("Ignoring "%s" query.", gst_query_type_get_name(query->type)); - break; + case GST_QUERY_ALLOCATION: + if (transform_sink_query_allocation(transform, query)) + return true; + break; + case GST_QUERY_CAPS: + if (transform_sink_query_caps(transform, query)) + return true; + break; + default: + break; }
+ GST_TRACE("transform %p, ignoring %"GST_PTR_FORMAT, transform, query); return gst_pad_query_default(pad, parent, query); }
@@ -237,6 +238,8 @@ static void transform_sink_event_caps(struct wg_transform *transform, GstEvent * { GstCaps *caps;
+ GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, event); + gst_event_parse_caps(event, &caps);
transform->output_caps_changed = transform->output_caps_changed @@ -250,15 +253,13 @@ static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent { 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: transform_sink_event_caps(transform, event); break; default: - GST_WARNING("Ignoring "%s" event.", GST_EVENT_TYPE_NAME(event)); + GST_TRACE("transform %p, ignoring %"GST_PTR_FORMAT, transform, event); break; }
@@ -601,7 +602,7 @@ NTSTATUS wg_transform_push_data(void *args) else { InterlockedIncrement(&sample->refcount); - GST_INFO("Wrapped %u/%u bytes from sample %p to buffer %p", sample->size, sample->max_size, sample, buffer); + GST_INFO("Wrapped %u/%u bytes from sample %p to %"GST_PTR_FORMAT, sample->size, sample->max_size, sample, buffer); }
if (sample->flags & WG_SAMPLE_FLAG_HAS_PTS) @@ -708,7 +709,7 @@ static NTSTATUS read_transform_output_data(GstBuffer *buffer, GstCaps *caps, gsi
if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) { - GST_ERROR("Failed to map buffer %p", buffer); + GST_ERROR("Failed to map buffer %"GST_PTR_FORMAT, buffer); sample->size = 0; return STATUS_UNSUCCESSFUL; } @@ -725,7 +726,7 @@ static NTSTATUS read_transform_output_data(GstBuffer *buffer, GstCaps *caps, gsi
if (status) { - GST_ERROR("Failed to copy buffer %p", buffer); + GST_ERROR("Failed to copy buffer %"GST_PTR_FORMAT, buffer); sample->size = 0; return status; }
From: Rémi Bernon rbernon@codeweavers.com
Decoders might output some fps information and encoders might input fps, but otherwise is unnecessary and may prevent compatible caps matching. --- dlls/winegstreamer/h264_decoder.c | 4 --- dlls/winegstreamer/video_decoder.c | 6 ----- dlls/winegstreamer/wg_transform.c | 39 +++++++++++++++++++++++++----- dlls/winegstreamer/wmv_decoder.c | 4 --- 4 files changed, 33 insertions(+), 20 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index a187c744549..ec1dd593b18 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -111,8 +111,6 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder) */ 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 (SUCCEEDED(IMFAttributes_GetUINT32(decoder->attributes, &MF_LOW_LATENCY, &low_latency))) attrs.low_latency = !!low_latency; @@ -552,8 +550,6 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF */ 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_output_format(decoder->wg_transform, &output_format)) diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 2faab78faf2..f24c25e03f2 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -84,9 +84,6 @@ static HRESULT try_create_wg_transform(struct video_decoder *decoder) if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) return MF_E_INVALIDMEDIATYPE;
- 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, &attrs))) { ERR("Failed to create transform with input major_type %u.\n", input_format.major_type); @@ -311,9 +308,6 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF { mf_media_type_to_wg_format(decoder->output_type, &output_format);
- 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_output_format(decoder->wg_transform, &output_format)) { diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 56523c7606a..320ee76438e 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -188,6 +188,16 @@ static gboolean transform_sink_query_allocation(struct wg_transform *transform, return true; }
+static GstCaps *transform_format_to_caps(struct wg_transform *transform, const struct wg_format *format) +{ + struct wg_format copy = *format; + + if (format->major_type == WG_MAJOR_TYPE_VIDEO) + copy.u.video.fps_n = copy.u.video.fps_d = 0; + + return wg_format_to_caps(©); +} + static gboolean transform_sink_query_caps(struct wg_transform *transform, GstQuery *query) { GstCaps *caps, *filter, *temp; @@ -195,7 +205,7 @@ static gboolean transform_sink_query_caps(struct wg_transform *transform, GstQue GST_LOG("transform %p, %"GST_PTR_FORMAT, transform, query);
gst_query_parse_caps(query, &filter); - if (!(caps = wg_format_to_caps(&transform->output_format))) + if (!(caps = transform_format_to_caps(transform, &transform->output_format))) return false;
if (filter) @@ -234,6 +244,23 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery return gst_pad_query_default(pad, parent, query); }
+static gboolean transform_output_caps_is_compatible(struct wg_transform *transform, GstCaps *caps) +{ + GstCaps *copy = gst_caps_copy(caps); + gboolean ret; + gsize i; + + for (i = 0; i < gst_caps_get_size(copy); ++i) + { + GstStructure *structure = gst_caps_get_structure(copy, i); + gst_structure_remove_fields(structure, "framerate", NULL); + } + + ret = gst_caps_is_always_compatible(transform->output_caps, copy); + gst_caps_unref(copy); + return ret; +} + static void transform_sink_event_caps(struct wg_transform *transform, GstEvent *event) { GstCaps *caps; @@ -243,7 +270,7 @@ static void transform_sink_event_caps(struct wg_transform *transform, GstEvent * gst_event_parse_caps(event, &caps);
transform->output_caps_changed = transform->output_caps_changed - || !gst_caps_is_always_compatible(transform->output_caps, caps); + || !transform_output_caps_is_compatible(transform, caps);
gst_caps_unref(transform->output_caps); transform->output_caps = gst_caps_ref(caps); @@ -329,7 +356,7 @@ NTSTATUS wg_transform_create(void *args) transform->attrs = *params->attrs; transform->output_format = output_format;
- if (!(src_caps = wg_format_to_caps(&input_format))) + if (!(src_caps = transform_format_to_caps(transform, &input_format))) goto out; if (!(template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps))) goto out; @@ -343,7 +370,7 @@ NTSTATUS wg_transform_create(void *args) gst_pad_set_element_private(transform->my_src, transform); gst_pad_set_query_function(transform->my_src, transform_src_query_cb);
- if (!(transform->output_caps = wg_format_to_caps(&output_format))) + if (!(transform->output_caps = transform_format_to_caps(transform, &output_format))) goto out; if (!(template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, transform->output_caps))) goto out; @@ -516,7 +543,7 @@ NTSTATUS wg_transform_set_output_format(void *args) GstSample *sample; GstCaps *caps;
- if (!(caps = wg_format_to_caps(format))) + if (!(caps = transform_format_to_caps(transform, format))) { GST_ERROR("Failed to convert format %p to caps.", format); return STATUS_UNSUCCESSFUL; @@ -525,7 +552,7 @@ NTSTATUS wg_transform_set_output_format(void *args)
GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, caps);
- if (gst_caps_is_always_compatible(transform->output_caps, caps)) + if (transform_output_caps_is_compatible(transform, caps)) { gst_caps_unref(caps); return STATUS_SUCCESS; diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index 89da25074c6..d13b5a065ed 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -520,8 +520,6 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) return DMO_E_TYPE_NOT_ACCEPTED; assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO_WMV); - wg_format.u.video_wmv.fps_n = 0; - wg_format.u.video_wmv.fps_d = 0;
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK; @@ -579,8 +577,6 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) return DMO_E_TYPE_NOT_ACCEPTED; assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO); - wg_format.u.video.fps_n = 0; - wg_format.u.video.fps_d = 0;
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/h264_decoder.c | 13 +------------ dlls/winegstreamer/unixlib.h | 1 + dlls/winegstreamer/wg_transform.c | 4 ++++ 3 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c index ec1dd593b18..bf691a2e25c 100644 --- a/dlls/winegstreamer/h264_decoder.c +++ b/dlls/winegstreamer/h264_decoder.c @@ -89,6 +89,7 @@ static HRESULT try_create_wg_transform(struct h264_decoder *decoder) { .output_plane_align = 15, .input_queue_length = 15, + .allow_size_change = TRUE, }; struct wg_format input_format; struct wg_format output_format; @@ -106,12 +107,6 @@ 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; - if (SUCCEEDED(IMFAttributes_GetUINT32(decoder->attributes, &MF_LOW_LATENCY, &low_latency))) attrs.low_latency = !!low_latency;
@@ -545,12 +540,6 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF 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; - if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN || !wg_transform_set_output_format(decoder->wg_transform, &output_format)) { diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 516fc19b4e3..4ec9fce515e 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -336,6 +336,7 @@ struct wg_transform_attrs { UINT32 output_plane_align; UINT32 input_queue_length; + BOOL allow_size_change; BOOL low_latency; };
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 320ee76438e..516b28e82e2 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -193,7 +193,11 @@ static GstCaps *transform_format_to_caps(struct wg_transform *transform, const s struct wg_format copy = *format;
if (format->major_type == WG_MAJOR_TYPE_VIDEO) + { + if (transform->attrs.allow_size_change) + copy.u.video.width = copy.u.video.height = 0; copy.u.video.fps_n = copy.u.video.fps_d = 0; + }
return wg_format_to_caps(©); }
I don't hate this, but I'm having a hard time seeing it as an improvement. Is there some future code that builds on this, or perhaps just a different perspective I'm missing?
I have more changes to the transforms that rely on this though I don't see what difference it makes. This is IMO some trivial refactoring to simplify the code by factoring common logic across clients into a single place, for some of the changes, and improve debugging experience by making traces more useful, for the other parts and I don't understand why we have to argue about if they are worth having.
On Fri Feb 2 05:25:46 2024 +0000, Rémi Bernon wrote:
I have more changes to the transforms that rely on this though I don't see what difference it makes. This is IMO some trivial refactoring to simplify the code by factoring common logic across clients into a single place, for some of the changes, and improve debugging experience by making traces more useful, for the other parts and I don't understand why we have to argue about if they are worth having.
(Then of course, I'm happy to make changes if there's anything specific...)
I have more changes to the transforms that rely on this though I don't see what difference it makes. This is IMO some trivial refactoring to simplify the code by factoring common logic across clients into a single place, for some of the changes, and improve debugging experience by making traces more useful, for the other parts and I don't understand why we have to argue about if they are worth having.
Ah sorry, I misspoke, 1-5 are definitely an improvement, it's only 6 and moreso 7 I feel lukewarm about. It's not really factoring out that much (and 7 isn't factoring out anything), and it doesn't seem like it's factoring it out into a place that really makes sense (why would this inhere to the transform?)
But if it's useful for some future patches I'm willing to accept it.
6 is mainly to solve the caps matching failure in the place where it belongs.
No transform care about mismatched fps as of today and there is no reason we need to call gstreamer for something that would pass through buffers but change fps, this can be done on the client side.
There's plenty of cases where clients can set mismatched fps in their media types, and as far as the tests go this is never a reason for a failure.
Regarding 7, it is going to be needed to fix some frame size / padding issues when clients set it on input but miss it on output, or set a new output type with a missing aperture but overall matching frame size. The decoders we have currently workaround this by clearing the frame size before set_output_format, and this is incorrect.
6 is mainly to solve the caps matching failure in the place where it belongs.
No transform care about mismatched fps as of today and there is no reason we need to call gstreamer for something that would pass through buffers but change fps, this can be done on the client side.
I'm not saying that something being common to all users is a bad reason to share code, it's just not necessarily a great reason either. It's not hard to see this as something specific to one frontend. It's not something that inheres about matching GStreamer caps, it's just working around bugs in Media Foundation games.
Regarding 7, it is going to be needed to fix some frame size / padding issues when clients set it on input but miss it on output, or set a new output type with a missing aperture but overall matching frame size. The decoders we have currently workaround this by clearing the frame size before set_output_format, and this is incorrect.
...Incorrect why, though? It's doing the exact same thing as this code is doing, just on another level.
This merge request was approved by Zebediah Figura.