rtphdrext: allow updating depayloader src caps

Add overridable method that updates depayloader's src caps based on
the data from RTP header.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1011>
This commit is contained in:
Jakub Adam 2021-02-04 17:08:04 +01:00
parent 899c69abad
commit c222f322c0
3 changed files with 135 additions and 0 deletions

View file

@ -60,6 +60,8 @@ struct _GstRTPBaseDepayloadPrivate
gboolean negotiated;
GstCaps *last_caps;
gboolean needs_src_caps_update;
GstEvent *segment_event;
guint32 segment_seqnum; /* Note: this is a GstEvent seqnum */
@ -1241,6 +1243,10 @@ read_rtp_header_extensions (GstRTPBaseDepayload * depayload,
goto out;
}
if (gst_rtp_header_extension_wants_update_non_rtp_src_caps (ext)) {
depayload->priv->needs_src_caps_update = TRUE;
}
gst_object_unref (ext);
}
GST_OBJECT_UNLOCK (depayload);
@ -1307,6 +1313,46 @@ gst_rtp_base_depayload_prepare_push (GstRTPBaseDepayload * filter,
set_headers (buf, 0, filter);
}
/* header extensions may want to update src caps */
if (G_UNLIKELY (filter->priv->needs_src_caps_update)) {
GstCaps *src_caps = gst_pad_get_current_caps (filter->srcpad);
if (src_caps) {
GstCaps *new_caps;
gboolean update_ok = TRUE;
gint i;
new_caps = gst_caps_copy (src_caps);
for (i = 0; i < filter->priv->header_exts->len; i++) {
GstRTPHeaderExtension *ext;
ext = g_ptr_array_index (filter->priv->header_exts, i);
update_ok =
gst_rtp_header_extension_update_non_rtp_src_caps (ext, new_caps);
if (!update_ok) {
GST_ELEMENT_ERROR (filter, STREAM, DECODE,
("RTP header extension (%s) could not update src caps",
GST_OBJECT_NAME (ext)), (NULL));
break;
}
}
if (G_UNLIKELY (update_ok && !gst_caps_is_equal (src_caps, new_caps))) {
gst_pad_set_caps (filter->srcpad, new_caps);
}
gst_caps_unref (src_caps);
gst_caps_unref (new_caps);
if (!update_ok) {
return GST_FLOW_ERROR;
}
}
filter->priv->needs_src_caps_update = FALSE;
}
/* if this is the first buffer send a NEWSEGMENT */
if (G_UNLIKELY (filter->priv->segment_event)) {
gst_pad_push_event (filter->srcpad, filter->priv->segment_event);

View file

@ -394,6 +394,49 @@ gst_rtp_header_extension_set_attributes_from_caps (GstRTPHeaderExtension * ext,
return klass->set_attributes_from_caps (ext, caps);
}
/**
* gst_rtp_header_extension_wants_update_non_rtp_src_caps:
* @ext: a #GstRTPHeaderExtension
*
* Call this function after gst_rtp_header_extension_read() to check if
* the depayloader's src caps need updating with data received in the last RTP
* packet.
*
* Returns: Whether @ext wants to update depayloader's src caps.
*
* Since: 1.20
*/
gboolean
gst_rtp_header_extension_wants_update_non_rtp_src_caps (GstRTPHeaderExtension *
ext)
{
g_return_val_if_fail (GST_IS_RTP_HEADER_EXTENSION (ext), FALSE);
return ext->wants_update_non_rtp_src_caps;
}
/**
* gst_rtp_header_extension_set_wants_update_non_rtp_src_caps:
* @ext: a #GstRTPHeaderExtension
* @state: TRUE if caps update is needed
*
* Call this function in a subclass from #GstRTPHeaderExtensionClass::read to
* tell the depayloader whether the data just parsed from RTP packet require
* updating its src (non-RTP) caps. If @state is TRUE, #GstRTPBaseDepayload will
* eventually invoke gst_rtp_header_extension_update_non_rtp_src_caps() to
* have the caps update applied. Applying the update also flips the internal
* "wants update" flag back to FALSE.
*
* Since: 1.20
*/
void gst_rtp_header_extension_set_wants_update_non_rtp_src_caps
(GstRTPHeaderExtension * ext, gboolean state)
{
g_return_if_fail (GST_IS_RTP_HEADER_EXTENSION (ext));
ext->wants_update_non_rtp_src_caps = state;
}
/**
* gst_rtp_header_extension_set_non_rtp_sink_caps:
* @ext: a #GstRTPHeaderExtension
@ -424,6 +467,39 @@ gst_rtp_header_extension_set_non_rtp_sink_caps (GstRTPHeaderExtension * ext,
return TRUE;
}
/**
* gst_rtp_header_extension_update_non_rtp_src_caps:
* @ext: a #GstRTPHeaderExtension
* @caps: src #GstCaps to modify
*
* Updates depayloader src caps based on the information received in RTP header.
* @caps must be writable as this function may modify them.
*
* Returns: whether @caps were modified successfully
*
* Since: 1.20
*/
gboolean
gst_rtp_header_extension_update_non_rtp_src_caps (GstRTPHeaderExtension * ext,
GstCaps * caps)
{
GstRTPHeaderExtensionClass *klass;
g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
g_return_val_if_fail (GST_IS_RTP_HEADER_EXTENSION (ext), FALSE);
g_return_val_if_fail (ext->ext_id <= MAX_RTP_EXT_ID, FALSE);
klass = GST_RTP_HEADER_EXTENSION_GET_CLASS (ext);
ext->wants_update_non_rtp_src_caps = FALSE;
if (klass->update_non_rtp_src_caps) {
return klass->update_non_rtp_src_caps (ext, caps);
}
return TRUE;
}
/**
* gst_rtp_header_extension_set_caps_from_attributes:
* @ext: a #GstRTPHeaderExtension

View file

@ -117,6 +117,7 @@ struct _GstRTPHeaderExtension
GstElement parent;
guint ext_id;
gboolean wants_update_non_rtp_src_caps;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
@ -140,6 +141,8 @@ struct _GstRTPHeaderExtension
* information, optionally adding some meta onto the output buffer.
* @set_non_rtp_sink_caps: read any information from sink caps that the header
* extension needs for its function.
* @update_non_rtp_src_caps: update depayloader non-RTP (depayloaded) caps with
* the information parsed from RTP header.
* @set_attributes_from_caps: read the caps information to set the necessary
* attributes that may be signaled e.g. with an SDP.
* @set_caps_from_attributes: write the necessary caps field/s for the configured
@ -173,6 +176,8 @@ struct _GstRTPHeaderExtensionClass
GstBuffer * buffer);
gboolean (*set_non_rtp_sink_caps) (GstRTPHeaderExtension * ext,
const GstCaps * caps);
gboolean (*update_non_rtp_src_caps) (GstRTPHeaderExtension * ext,
GstCaps * caps);
gboolean (*set_attributes_from_caps) (GstRTPHeaderExtension * ext,
const GstCaps * caps);
gboolean (*set_caps_from_attributes) (GstRTPHeaderExtension * ext,
@ -224,6 +229,14 @@ GST_RTP_API
gboolean gst_rtp_header_extension_set_non_rtp_sink_caps (GstRTPHeaderExtension * ext,
const GstCaps * caps);
GST_RTP_API
gboolean gst_rtp_header_extension_wants_update_non_rtp_src_caps (GstRTPHeaderExtension * ext);
GST_RTP_API
void gst_rtp_header_extension_set_wants_update_non_rtp_src_caps (GstRTPHeaderExtension * ext,
gboolean state);
GST_RTP_API
gboolean gst_rtp_header_extension_update_non_rtp_src_caps (GstRTPHeaderExtension * ext,
GstCaps * caps);
GST_RTP_API
gboolean gst_rtp_header_extension_set_caps_from_attributes (GstRTPHeaderExtension * ext,
GstCaps * caps);
GST_RTP_API