autoconvert: Handle reconfiguring on the srcpad

Only upstream renegotiation was properly handled, we needed to answer
that when downstream forces a renegotiation we take into account the
new downstream restrictions.

And add tests for it

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/899>
This commit is contained in:
Thibault Saunier 2021-05-25 20:44:46 -04:00 committed by GStreamer Marge Bot
parent 69db5b77d1
commit e153c558c7
4 changed files with 96 additions and 30 deletions

View file

@ -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 (&current_subelement);
gst_clear_caps (&other_caps);
gst_clear_caps (&current_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;

View file

@ -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

View file

@ -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

View file

@ -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()