rtpmanager: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / gstrtprtxsend.c
index 4329d84..bfa5db8 100644 (file)
 
 /**
  * SECTION:element-rtprtxsend
+ * @title: rtprtxsend
  *
  * See #GstRtpRtxReceive for examples
- * 
+ *
  * The purpose of the sender RTX object is to keep a history of RTP packets up
  * to a configurable limit (max-size-time or max-size-packets). It will listen
  * for upstream custom retransmission events (GstRTPRetransmissionRequest) that
@@ -61,7 +62,8 @@ enum
   PROP_MAX_SIZE_TIME,
   PROP_MAX_SIZE_PACKETS,
   PROP_NUM_RTX_REQUESTS,
-  PROP_NUM_RTX_PACKETS
+  PROP_NUM_RTX_PACKETS,
+  PROP_CLOCK_RATE_MAP,
 };
 
 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
@@ -73,7 +75,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("application/x-rtp, " "clock-rate = (int) [1, MAX]")
+    GST_STATIC_CAPS ("application/x-rtp")
     );
 
 static gboolean gst_rtp_rtx_send_queue_check_full (GstDataQueue * queue,
@@ -191,6 +193,11 @@ gst_rtp_rtx_send_class_init (GstRtpRtxSendClass * klass)
           " Number of retransmission packets sent", 0, G_MAXUINT,
           0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_CLOCK_RATE_MAP,
+      g_param_spec_boxed ("clock-rate-map", "Clock Rate Map",
+          "Map of payload types to their clock rates",
+          GST_TYPE_STRUCTURE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
   gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
 
@@ -227,6 +234,9 @@ gst_rtp_rtx_send_finalize (GObject * object)
   g_hash_table_unref (rtx->rtx_pt_map);
   if (rtx->rtx_pt_map_structure)
     gst_structure_free (rtx->rtx_pt_map_structure);
+  g_hash_table_unref (rtx->clock_rate_map);
+  if (rtx->clock_rate_map_structure)
+    gst_structure_free (rtx->clock_rate_map_structure);
   g_object_unref (rtx->queue);
 
   G_OBJECT_CLASS (gst_rtp_rtx_send_parent_class)->finalize (object);
@@ -267,6 +277,7 @@ gst_rtp_rtx_send_init (GstRtpRtxSend * rtx)
       NULL, (GDestroyNotify) ssrc_rtx_data_free);
   rtx->rtx_ssrcs = g_hash_table_new (g_direct_hash, g_direct_equal);
   rtx->rtx_pt_map = g_hash_table_new (g_direct_hash, g_direct_equal);
+  rtx->clock_rate_map = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   rtx->max_size_time = DEFAULT_MAX_SIZE_TIME;
   rtx->max_size_packets = DEFAULT_MAX_SIZE_PACKETS;
@@ -400,7 +411,10 @@ gst_rtp_rtx_buffer_new (GstRtpRtxSend * rtx, GstBuffer * buffer)
 
   /* copy extension if any */
   if (rtp.size[1]) {
-    mem = gst_memory_copy (rtp.map[1].memory, 0, rtp.size[1]);
+    mem = gst_allocator_alloc (NULL, rtp.size[1], NULL);
+    gst_memory_map (mem, &map, GST_MAP_WRITE);
+    memcpy (map.data, rtp.data[1], rtp.size[1]);
+    gst_memory_unmap (mem, &map);
     gst_buffer_append_memory (new_buffer, mem);
   }
 
@@ -491,6 +505,26 @@ gst_rtp_rtx_send_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
             GST_LOG_OBJECT (rtx, "found %u", item->seqnum);
             rtx_buf = gst_rtp_rtx_buffer_new (rtx, item->buffer);
           }
+#ifndef GST_DISABLE_DEBUG
+          else {
+            BufferQueueItem *item = NULL;
+
+            iter = g_sequence_get_begin_iter (data->queue);
+            if (!g_sequence_iter_is_end (iter))
+              item = g_sequence_get (iter);
+
+            if (item && seqnum < item->seqnum) {
+              GST_DEBUG_OBJECT (rtx, "requested seqnum %u has already been "
+                  "removed from the rtx queue; the first available is %u",
+                  seqnum, item->seqnum);
+            } else {
+              GST_WARNING_OBJECT (rtx, "requested seqnum %u has not been "
+                  "transmitted yet in the original stream; either the remote end "
+                  "is not configured correctly, or the source is too slow",
+                  seqnum);
+            }
+          }
+#endif
         }
         GST_OBJECT_UNLOCK (rtx);
 
@@ -511,7 +545,7 @@ gst_rtp_rtx_send_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 
         GST_OBJECT_LOCK (rtx);
 
-        /* choose another ssrc for our retransmited stream */
+        /* choose another ssrc for our retransmitted stream */
         if (g_hash_table_contains (rtx->rtx_ssrcs, GUINT_TO_POINTER (ssrc))) {
           guint master_ssrc;
           SSRCRtxData *data;
@@ -601,6 +635,9 @@ gst_rtp_rtx_send_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       if (!gst_structure_get_int (s, "payload", &payload))
         payload = -1;
 
+      if (payload == -1 || ssrc == G_MAXUINT)
+        break;
+
       if (payload == -1)
         GST_WARNING_OBJECT (rtx, "No payload in caps");
 
@@ -699,6 +736,12 @@ process_buffer (GstRtpRtxSend * rtx, GstBuffer * buffer)
   if (g_hash_table_contains (rtx->rtx_pt_map, GUINT_TO_POINTER (payload_type))) {
     data = gst_rtp_rtx_send_get_ssrc_data (rtx, ssrc);
 
+    if (data->clock_rate == 0 && rtx->clock_rate_map_structure) {
+      data->clock_rate =
+          GPOINTER_TO_INT (g_hash_table_lookup (rtx->clock_rate_map,
+              GUINT_TO_POINTER (payload_type)));
+    }
+
     /* add current rtp buffer to queue history */
     item = g_slice_new0 (BufferQueueItem);
     item->seqnum = seqnum;
@@ -847,6 +890,11 @@ gst_rtp_rtx_send_get_property (GObject * object,
       g_value_set_uint (value, rtx->num_rtx_packets);
       GST_OBJECT_UNLOCK (rtx);
       break;
+    case PROP_CLOCK_RATE_MAP:
+      GST_OBJECT_LOCK (rtx);
+      g_value_set_boxed (value, rtx->clock_rate_map_structure);
+      GST_OBJECT_UNLOCK (rtx);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -903,6 +951,16 @@ gst_rtp_rtx_send_set_property (GObject * object,
       rtx->max_size_packets = g_value_get_uint (value);
       GST_OBJECT_UNLOCK (rtx);
       break;
+    case PROP_CLOCK_RATE_MAP:
+      GST_OBJECT_LOCK (rtx);
+      if (rtx->clock_rate_map_structure)
+        gst_structure_free (rtx->clock_rate_map_structure);
+      rtx->clock_rate_map_structure = g_value_dup_boxed (value);
+      g_hash_table_remove_all (rtx->clock_rate_map);
+      gst_structure_foreach (rtx->clock_rate_map_structure,
+          structure_to_hash_table, rtx->clock_rate_map);
+      GST_OBJECT_UNLOCK (rtx);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;