* Generic Forward Error Correction (FEC) decoder for Uneven Level
* Protection (ULP) as described in RFC 5109.
*
+ * It differs from the RFC in one important way, it multiplexes the
+ * FEC packets in the same sequence number as media packets. This is to be
+ * compatible with libwebrtc as using in Google Chrome and with Microsoft
+ * Lync / Skype for Business.
+ *
* This element will work in combination with an upstream #GstRtpStorage
* 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
- * <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>.
+ * If no storage is provided using the #GstRtpUlpFecDec:storage
+ * property, it will try to get it from an element upstream.
*
* Additionally, the payload types of the protection packets *must* be
* provided to this element via its #GstRtpUlpFecDec:pt property.
* When using #GstRtpBin, this element should be inserted through the
* #GstRtpBin::request-fec-decoder signal.
*
+ * <refsect2>
+ * <title>Example pipeline</title>
+ * |[
+ * gst-launch-1.0 udpsrc port=8888 caps="application/x-rtp, payload=96, clock-rate=90000" ! rtpstorage size-time=220000000 ! rtpssrcdemux ! application/x-rtp, payload=96, clock-rate=90000, media=video, encoding-name=H264 ! rtpjitterbuffer do-lost=1 latency=200 ! rtpulpfecdec pt=122 ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink
+ * ]| This example will receive a stream with FEC and try to reconstruct the packets.
+ *
+ * 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>.
+ *
+ * </refsect2>
+ *
* See also: #GstRtpUlpFecEnc, #GstRtpBin, #GstRtpStorage
* Since: 1.14
*/
GST_LOG_RTP_PACKET (self, "rtp header (incoming)", &info->rtp);
if (lost_seq == gst_rtp_buffer_get_seq (&info->rtp)) {
- GST_DEBUG_OBJECT (self, "Received lost packet from from the storage");
+ GST_DEBUG_OBJECT (self, "Received lost packet from the storage");
g_list_free (self->info_media);
self->info_media = NULL;
self->lost_packet_from_storage = TRUE;
sent_buffer = gst_buffer_copy_deep (recovered_buffer);
+ if (self->lost_packet_from_storage)
+ gst_buffer_unref (recovered_buffer);
+
gst_rtp_buffer_map (sent_buffer, GST_MAP_WRITE, &rtp);
gst_rtp_buffer_set_seq (&rtp, self->next_seqnum++);
gst_rtp_buffer_unmap (&rtp);
break;
}
- rtp_storage_put_recovered_packet (self->storage,
- recovered_buffer, recovered_pt, self->caps_ssrc, recovered_seq);
+ if (!self->lost_packet_from_storage) {
+ rtp_storage_put_recovered_packet (self->storage,
+ recovered_buffer, recovered_pt, self->caps_ssrc, recovered_seq);
+ } else {
+ gst_buffer_unref (recovered_buffer);
+ }
}
gst_rtp_ulpfec_dec_stop (self);
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,