rtpulpfec*: Improve documentation
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpulpfecdec.c
index da29371..cb6372c 100644 (file)
  * 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
  */
@@ -134,7 +147,7 @@ gst_rtp_ulpfec_dec_start (GstRtpUlpFecDec * self, GstBufferList * buflist,
       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;
@@ -421,6 +434,9 @@ gst_rtp_ulpfec_dec_handle_packet_loss (GstRtpUlpFecDec * self, guint16 seqnum,
 
         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);
@@ -431,8 +447,12 @@ gst_rtp_ulpfec_dec_handle_packet_loss (GstRtpUlpFecDec * self, guint16 seqnum,
         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);
@@ -465,7 +485,26 @@ gst_rtp_ulpfec_dec_handle_sink_event (GstPad * pad, GstObject * parent,
     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,