mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
codectimestamper: Implement QUERY_CAPS support
This is required to ensure that downstream restrcitions are also propagated upstream. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4341>
This commit is contained in:
parent
dbc6afd874
commit
5797fa09af
5 changed files with 102 additions and 5 deletions
|
@ -76,13 +76,16 @@ static GstFlowReturn gst_codec_timestamper_chain (GstPad * pad,
|
||||||
GstObject * parent, GstBuffer * buffer);
|
GstObject * parent, GstBuffer * buffer);
|
||||||
static gboolean gst_codec_timestamper_sink_event (GstPad * pad,
|
static gboolean gst_codec_timestamper_sink_event (GstPad * pad,
|
||||||
GstObject * parent, GstEvent * event);
|
GstObject * parent, GstEvent * event);
|
||||||
|
static gboolean gst_codec_timestamper_sink_query (GstPad * pad,
|
||||||
|
GstObject * parent, GstQuery * query);
|
||||||
static gboolean gst_codec_timestamper_src_query (GstPad * pad,
|
static gboolean gst_codec_timestamper_src_query (GstPad * pad,
|
||||||
GstObject * parent, GstQuery * query);
|
GstObject * parent, GstQuery * query);
|
||||||
static GstStateChangeReturn
|
static GstCaps *gst_timestamper_get_caps (GstCodecTimestamper * self,
|
||||||
gst_codec_timestamper_change_state (GstElement * element,
|
GstCaps * filter);
|
||||||
GstStateChange transition);
|
static GstStateChangeReturn gst_codec_timestamper_change_state (GstElement *
|
||||||
static void
|
element, GstStateChange transition);
|
||||||
gst_codec_timestamper_clear_frame (GstCodecTimestamperFrame * frame);
|
static void gst_codec_timestamper_clear_frame (GstCodecTimestamperFrame *
|
||||||
|
frame);
|
||||||
static void gst_codec_timestamper_reset (GstCodecTimestamper * self);
|
static void gst_codec_timestamper_reset (GstCodecTimestamper * self);
|
||||||
static void gst_codec_timestamper_drain (GstCodecTimestamper * self);
|
static void gst_codec_timestamper_drain (GstCodecTimestamper * self);
|
||||||
|
|
||||||
|
@ -142,6 +145,9 @@ gst_codec_timestamper_class_init (GstCodecTimestamperClass * klass)
|
||||||
element_class->change_state =
|
element_class->change_state =
|
||||||
GST_DEBUG_FUNCPTR (gst_codec_timestamper_change_state);
|
GST_DEBUG_FUNCPTR (gst_codec_timestamper_change_state);
|
||||||
|
|
||||||
|
/* Default implementation is correct for both H264 and H265 */
|
||||||
|
klass->get_sink_caps = gst_timestamper_get_caps;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_codec_timestamper_debug, "codectimestamper", 0,
|
GST_DEBUG_CATEGORY_INIT (gst_codec_timestamper_debug, "codectimestamper", 0,
|
||||||
"codectimestamper");
|
"codectimestamper");
|
||||||
|
|
||||||
|
@ -169,6 +175,9 @@ gst_codec_timestamper_init (GstCodecTimestamper * self,
|
||||||
GST_DEBUG_FUNCPTR (gst_codec_timestamper_chain));
|
GST_DEBUG_FUNCPTR (gst_codec_timestamper_chain));
|
||||||
gst_pad_set_event_function (self->sinkpad,
|
gst_pad_set_event_function (self->sinkpad,
|
||||||
GST_DEBUG_FUNCPTR (gst_codec_timestamper_sink_event));
|
GST_DEBUG_FUNCPTR (gst_codec_timestamper_sink_event));
|
||||||
|
gst_pad_set_query_function (self->sinkpad,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_codec_timestamper_sink_query));
|
||||||
|
|
||||||
GST_PAD_SET_PROXY_SCHEDULING (self->sinkpad);
|
GST_PAD_SET_PROXY_SCHEDULING (self->sinkpad);
|
||||||
GST_PAD_SET_ACCEPT_INTERSECT (self->sinkpad);
|
GST_PAD_SET_ACCEPT_INTERSECT (self->sinkpad);
|
||||||
GST_PAD_SET_ACCEPT_TEMPLATE (self->sinkpad);
|
GST_PAD_SET_ACCEPT_TEMPLATE (self->sinkpad);
|
||||||
|
@ -582,6 +591,76 @@ gst_codec_timestamper_chain (GstPad * pad, GstObject * parent,
|
||||||
return gst_codec_timestamper_process_output_frame (self);
|
return gst_codec_timestamper_process_output_frame (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_timestamper_get_caps (GstCodecTimestamper * self, GstCaps * filter)
|
||||||
|
{
|
||||||
|
GstCaps *peercaps, *templ;
|
||||||
|
GstCaps *res, *tmp, *pcopy;
|
||||||
|
|
||||||
|
templ = gst_pad_get_pad_template_caps (self->sinkpad);
|
||||||
|
if (filter) {
|
||||||
|
GstCaps *fcopy = gst_caps_copy (filter);
|
||||||
|
|
||||||
|
peercaps = gst_pad_peer_query_caps (self->srcpad, fcopy);
|
||||||
|
gst_caps_unref (fcopy);
|
||||||
|
} else {
|
||||||
|
peercaps = gst_pad_peer_query_caps (self->srcpad, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pcopy = gst_caps_copy (peercaps);
|
||||||
|
|
||||||
|
res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (pcopy);
|
||||||
|
gst_caps_unref (templ);
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
GstCaps *tmp = gst_caps_intersect_full (res, filter,
|
||||||
|
GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (res);
|
||||||
|
res = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try if we can put the downstream caps first */
|
||||||
|
pcopy = gst_caps_copy (peercaps);
|
||||||
|
tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (pcopy);
|
||||||
|
if (!gst_caps_is_empty (tmp))
|
||||||
|
res = gst_caps_merge (tmp, res);
|
||||||
|
else
|
||||||
|
gst_caps_unref (tmp);
|
||||||
|
|
||||||
|
gst_caps_unref (peercaps);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_codec_timestamper_sink_query (GstPad * pad, GstObject * parent,
|
||||||
|
GstQuery * query)
|
||||||
|
{
|
||||||
|
GstCodecTimestamper *self = GST_CODEC_TIMESTAMPER (parent);
|
||||||
|
|
||||||
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_CAPS:{
|
||||||
|
GstCaps *caps, *filter;
|
||||||
|
GstCodecTimestamperClass *klass = GST_CODEC_TIMESTAMPER_GET_CLASS (self);
|
||||||
|
|
||||||
|
gst_query_parse_caps (query, &filter);
|
||||||
|
g_assert (klass->get_sink_caps);
|
||||||
|
caps = klass->get_sink_caps (self, filter);
|
||||||
|
GST_LOG_OBJECT (self, "sink getcaps returning caps %" GST_PTR_FORMAT,
|
||||||
|
caps);
|
||||||
|
gst_query_set_caps_result (query, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gst_pad_query_default (pad, parent, query);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_codec_timestamper_src_query (GstPad * pad, GstObject * parent,
|
gst_codec_timestamper_src_query (GstPad * pad, GstObject * parent,
|
||||||
GstQuery * query)
|
GstQuery * query)
|
||||||
|
|
|
@ -54,6 +54,9 @@ struct _GstCodecTimestamperClass
|
||||||
gboolean (*set_caps) (GstCodecTimestamper * timestamper,
|
gboolean (*set_caps) (GstCodecTimestamper * timestamper,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
|
||||||
|
GstCaps * (*get_sink_caps) (GstCodecTimestamper * timestamper,
|
||||||
|
GstCaps * filter);
|
||||||
|
|
||||||
GstFlowReturn (*handle_buffer) (GstCodecTimestamper * timestamper,
|
GstFlowReturn (*handle_buffer) (GstCodecTimestamper * timestamper,
|
||||||
GstBuffer * buffer);
|
GstBuffer * buffer);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
meta,
|
||||||
|
args = {
|
||||||
|
"videotestsrc num-buffers=1 ! video/x-raw,width=1920,height=1080,format=I420 ! videoscale ! x264enc tune=zerolatency ! h264timestamper ! video/x-h264,width=50,height=50 ! fakesink name=sink",
|
||||||
|
},
|
||||||
|
configs = {
|
||||||
|
"$(validateflow), pad=sink:sink, buffers-checksum=as-id, caps-properties={width, height}, ignored-event-types={tag}",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1;
|
||||||
|
event caps: video/x-h264, height=(int)50, width=(int)50;
|
||||||
|
event segment: format=TIME, start=1000:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=1000:00:00.000000000
|
||||||
|
buffer: content-id=0, dts=1000:00:00.000000000, pts=1000:00:00.000000000, dur=0:00:00.033333333, flags=discont marker
|
||||||
|
event eos: (no structure)
|
|
@ -6,6 +6,7 @@ endif
|
||||||
tests = [
|
tests = [
|
||||||
{'path': 'opencv/cvtracker'},
|
{'path': 'opencv/cvtracker'},
|
||||||
{'path': 'testsrcbin/caps_spec'},
|
{'path': 'testsrcbin/caps_spec'},
|
||||||
|
{'path': 'codectimestamper/h264_propagate_caps'},
|
||||||
{'path': 'wpe/load_bytes_first', 'skip': not building_wpe},
|
{'path': 'wpe/load_bytes_first', 'skip': not building_wpe},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue