}
}
+static gboolean
+gst_rtp_storage_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
+{
+ GstRtpStorage *self = GST_RTP_STORAGE (parent);
+
+ if (GST_QUERY_TYPE (query) == GST_QUERY_CUSTOM) {
+ GstStructure *s = gst_query_writable_structure (query);
+
+ if (gst_structure_has_name (s, "GstRtpStorage")) {
+ gst_structure_set (s, "storage", G_TYPE_OBJECT, self->storage, NULL);
+ return TRUE;
+ }
+ }
+
+ return gst_pad_query_default (pad, parent, query);
+}
+
static void
gst_rtp_storage_init (GstRtpStorage * self)
{
GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad);
gst_pad_set_chain_function (self->sinkpad, gst_rtp_storage_chain);
+ gst_pad_set_query_function (self->srcpad, gst_rtp_storage_src_query);
+
gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
* element and attempt to recover packets declared lost through custom
* 'GstRTPPacketLost' events, usually emitted by #GstRtpJitterBuffer.
*
- * As such, this element cannot be usefully used from the command line,
- * because a reference to the upstream storage object needs to be
- * provided to it through its #GstRtpUlpFecDec:storage property, example
- * programs are available at
+ * If no storage is provided using the #GstRtpUlpFecDec:storage
+ * property, it will try to get it from an element upstream.
+ *
+ * Example programs are available at
* <https://github.com/sdroege/gstreamer-rs/blob/master/examples/src/bin/rtpfecserver.rs>
* and
* <https://github.com/sdroege/gstreamer-rs/blob/master/examples/src/bin/rtpfecclient.rs>.
s = gst_event_writable_structure (event);
g_assert (self->have_caps_ssrc);
- g_assert (self->storage);
+
+ if (self->storage == NULL) {
+ GstQuery *q = gst_query_new_custom (GST_QUERY_CUSTOM,
+ gst_structure_new_empty ("GstRtpStorage"));
+
+ if (gst_pad_peer_query (self->sinkpad, q)) {
+ const GstStructure *s = gst_query_get_structure (q);
+
+ if (gst_structure_has_field_typed (s, "storage", G_TYPE_OBJECT)) {
+ gst_structure_get (s, "storage", G_TYPE_OBJECT, &self->storage, NULL);
+ }
+ }
+ gst_query_unref (q);
+ }
+
+ if (self->storage == NULL) {
+ GST_ELEMENT_WARNING (self, STREAM, FAILED, ("Internal storage not found"),
+ ("You need to add rtpstorage element upstream from rtpulpfecdec."));
+ return FALSE;
+ }
if (!gst_structure_get (s,
"seqnum", G_TYPE_UINT, &seqnum,