diff --git a/gst-libs/gst/rtp/gstrtpbasedepayload.c b/gst-libs/gst/rtp/gstrtpbasedepayload.c index 68b576068a..edb12a20d7 100644 --- a/gst-libs/gst/rtp/gstrtpbasedepayload.c +++ b/gst-libs/gst/rtp/gstrtpbasedepayload.c @@ -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); diff --git a/gst-libs/gst/rtp/gstrtphdrext.c b/gst-libs/gst/rtp/gstrtphdrext.c index 1988e4469d..e324359a1f 100644 --- a/gst-libs/gst/rtp/gstrtphdrext.c +++ b/gst-libs/gst/rtp/gstrtphdrext.c @@ -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 diff --git a/gst-libs/gst/rtp/gstrtphdrext.h b/gst-libs/gst/rtp/gstrtphdrext.h index 1f0e9b1ca0..cdfefd4959 100644 --- a/gst-libs/gst/rtp/gstrtphdrext.h +++ b/gst-libs/gst/rtp/gstrtphdrext.h @@ -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