diff --git a/subprojects/gst-plugins-bad/gst/autoconvert/gstautoconvert.c b/subprojects/gst-plugins-bad/gst/autoconvert/gstautoconvert.c index d21c35b353..ca06b228e3 100644 --- a/subprojects/gst-plugins-bad/gst/autoconvert/gstautoconvert.c +++ b/subprojects/gst-plugins-bad/gst/autoconvert/gstautoconvert.c @@ -94,8 +94,6 @@ static GstPad *gst_auto_convert_get_internal_srcpad (GstAutoConvert * static GstIterator *gst_auto_convert_iterate_internal_links (GstPad * pad, GstObject * parent); -static gboolean gst_auto_convert_sink_setcaps (GstAutoConvert * autoconvert, - GstCaps * caps); static GstCaps *gst_auto_convert_getcaps (GstAutoConvert * autoconvert, GstCaps * filter, GstPadDirection dir); static GstFlowReturn gst_auto_convert_sink_chain (GstPad * pad, @@ -624,7 +622,7 @@ gst_auto_convert_get_or_make_element_from_factory (GstAutoConvert * autoconvert, /* * This function checks if there is one and only one pad template on the * factory that can accept the given caps. If there is one and only one, - * it returns TRUE, otherwise, its FALSE + * it returns TRUE, FALSE otherwise */ static gboolean @@ -852,49 +850,62 @@ gst_auto_convert_iterate_internal_links (GstPad * pad, GstObject * parent) */ static gboolean -gst_auto_convert_sink_setcaps (GstAutoConvert * autoconvert, GstCaps * caps) +gst_auto_convert_sink_setcaps (GstAutoConvert * autoconvert, GstCaps * caps, + gboolean check_downstream) { GList *elem; GstCaps *other_caps = NULL; GList *factories; - GstCaps *current_caps; + GstCaps *current_caps = NULL; gboolean res = FALSE; - GstElement *current_subelement; + GstElement *current_subelement = NULL; g_return_val_if_fail (autoconvert != NULL, FALSE); - current_caps = gst_pad_get_current_caps (autoconvert->sinkpad); - if (current_caps) { - if (gst_caps_is_equal_fixed (caps, current_caps)) { - gst_caps_unref (current_caps); - return TRUE; - } - gst_caps_unref (current_caps); + if (!check_downstream) { + current_caps = gst_pad_get_current_caps (autoconvert->sinkpad); + + if (current_caps && gst_caps_is_equal_fixed (caps, current_caps)) + goto get_out; } + if (check_downstream) + other_caps = gst_pad_peer_query_caps (autoconvert->srcpad, NULL); current_subelement = gst_auto_convert_get_subelement (autoconvert); if (current_subelement) { if (gst_pad_peer_query_accept_caps (autoconvert->current_internal_srcpad, caps)) { - /* If we can set the new caps on the current element, - * then we just get out - */ - GST_DEBUG_OBJECT (autoconvert, "Could set %s:%s to %" GST_PTR_FORMAT, - GST_DEBUG_PAD_NAME (autoconvert->current_internal_srcpad), caps); - goto get_out; - } else { - /* If the current element doesn't work, - * then we remove the current element before finding a new one. - */ - GST_AUTOCONVERT_LOCK (autoconvert); - g_clear_object (&autoconvert->current_subelement); - g_clear_object (&autoconvert->current_internal_sinkpad); - g_clear_object (&autoconvert->current_internal_srcpad); - GST_AUTOCONVERT_UNLOCK (autoconvert); + + res = TRUE; + if (other_caps) { + GstElementFactory *factory = + gst_element_get_factory (current_subelement); + + if (!factory_can_intersect (autoconvert, factory, GST_PAD_SRC, + other_caps)) { + GST_LOG_OBJECT (autoconvert, + "Factory %s does not accept src caps %" GST_PTR_FORMAT, + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), + other_caps); + res = FALSE; + } + } + + if (res) { + /* If we can set the new caps on the current element, + * then we just get out + */ + GST_DEBUG_OBJECT (autoconvert, "Could set %s:%s to %" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (autoconvert->current_internal_srcpad), caps); + goto get_out; + } } } - other_caps = gst_pad_peer_query_caps (autoconvert->srcpad, NULL); + if (!check_downstream) + other_caps = gst_pad_peer_query_caps (autoconvert->srcpad, NULL); + /* We already queries downstream caps otherwise */ + factories = gst_auto_convert_get_or_load_factories (autoconvert); for (elem = factories; elem; elem = g_list_next (elem)) { @@ -940,6 +951,7 @@ gst_auto_convert_sink_setcaps (GstAutoConvert * autoconvert, GstCaps * caps) get_out: gst_clear_object (¤t_subelement); gst_clear_caps (&other_caps); + gst_clear_caps (¤t_caps); if (!res) GST_WARNING_OBJECT (autoconvert, @@ -1064,6 +1076,22 @@ gst_auto_convert_sink_chain (GstPad * pad, GstObject * parent, GstFlowReturn ret = GST_FLOW_NOT_NEGOTIATED; GstAutoConvert *autoconvert = GST_AUTO_CONVERT (parent); + if (gst_pad_check_reconfigure (autoconvert->srcpad)) { + GstCaps *sinkcaps = gst_pad_get_current_caps (pad); + + GST_INFO_OBJECT (parent, "Needs reconfigure."); + /* if we need to reconfigure we pretend new caps arrived. This + * will reconfigure the transform with the new output format. */ + if (sinkcaps + && !gst_auto_convert_sink_setcaps (autoconvert, sinkcaps, TRUE)) { + gst_clear_caps (&sinkcaps); + GST_ERROR_OBJECT (autoconvert, "Could not reconfigure."); + + return GST_FLOW_NOT_NEGOTIATED; + } + gst_clear_caps (&sinkcaps); + } + if (autoconvert->current_internal_srcpad) { ret = gst_pad_push (autoconvert->current_internal_srcpad, buffer); if (ret != GST_FLOW_OK) @@ -1112,7 +1140,7 @@ gst_auto_convert_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) GstCaps *caps; gst_event_parse_caps (event, &caps); - ret = gst_auto_convert_sink_setcaps (autoconvert, caps); + ret = gst_auto_convert_sink_setcaps (autoconvert, caps, FALSE); if (!ret) { gst_event_unref (event); return ret; diff --git a/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate.validatetest b/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate.validatetest new file mode 100644 index 0000000000..2077d2d4e0 --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate.validatetest @@ -0,0 +1,22 @@ +meta, + args = { + "gltestsrc ! gldownload ! autovideoconvert name=convert ! capsfilter name=capsfilter caps=\"video/x-raw(memory:GLMemory)\" ! fakevideosink name=sink", + }, + configs = { + "$(validateflow), pad=convert:src, record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream},buffer={meta}\"", + } + +crank-clock, repeat=2 +wait, on-clock=true +foreach, + caps = < + "video/x-raw", + "video/x-raw(memory:GLMemory)", + "video/x-raw", + >, + actions = { + [set-properties, capsfilter::caps="$(caps)"], + [crank-clock, repeat=2], + [wait, on-clock=true], + } +stop \ No newline at end of file diff --git a/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate/flow-expectations/log-convert-src-expected b/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate/flow-expectations/log-convert-src-expected new file mode 100644 index 0000000000..df1f9918a5 --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/validate/autovideoconvert/renegotiate/flow-expectations/log-convert-src-expected @@ -0,0 +1,15 @@ +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE; +event caps: video/x-raw(memory:GLMemory), format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320; +event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000 +buffer: pts=0:00:00.000000000, dur=0:00:00.033333333, flags=discont +buffer: pts=0:00:00.033333333, dur=0:00:00.033333333 +buffer: pts=0:00:00.066666666, dur=0:00:00.033333334 +event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320; +buffer: pts=0:00:00.100000000, dur=0:00:00.033333333 +buffer: pts=0:00:00.133333333, dur=0:00:00.033333333 +event caps: video/x-raw(memory:GLMemory), format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320; +buffer: pts=0:00:00.166666666, dur=0:00:00.033333334 +buffer: pts=0:00:00.200000000, dur=0:00:00.033333333 +event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320; +buffer: pts=0:00:00.233333333, dur=0:00:00.033333333 +buffer: pts=0:00:00.266666666, dur=0:00:00.033333334 diff --git a/subprojects/gst-plugins-bad/tests/validate/meson.build b/subprojects/gst-plugins-bad/tests/validate/meson.build index 2be348030b..c09772a657 100644 --- a/subprojects/gst-plugins-bad/tests/validate/meson.build +++ b/subprojects/gst-plugins-bad/tests/validate/meson.build @@ -12,6 +12,7 @@ tests = [ {'path': 'vtenc/vtenc_h264_b_frames', 'skip': not applemedia_found_deps}, {'path': 'vtenc/vtenc_h265', 'skip': not applemedia_found_deps}, {'path': 'vtenc/vtenc_h265_b_frames', 'skip': not applemedia_found_deps}, + {'path': 'autovideoconvert/renegotiate'}, ] env = environment()