gst-libs/gst/rtp/gstbasertpdepayload.*: Catch packet-lost events from the jitterbuffe...
authorWim Taymans <wim.taymans@gmail.com>
Fri, 2 May 2008 12:11:07 +0000 (12:11 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 2 May 2008 12:11:07 +0000 (12:11 +0000)
Original commit message from CVS:
* gst-libs/gst/rtp/gstbasertpdepayload.c:
(gst_base_rtp_depayload_class_init),
(gst_base_rtp_depayload_handle_sink_event), (create_segment_event),
(gst_base_rtp_depayload_packet_lost),
(gst_base_rtp_depayload_set_gst_timestamp):
* gst-libs/gst/rtp/gstbasertpdepayload.h:
Catch packet-lost events from the jitterbuffer and convert them into a
vmethod call (lost-packet) so that depayloaders can do something smart.
Also add a default packet-lost function that sends out a segment update
to the decoders.

ChangeLog
gst-libs/gst/rtp/gstbasertpdepayload.c
gst-libs/gst/rtp/gstbasertpdepayload.h

index 95921b3..c234d56 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-05-02  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * gst-libs/gst/rtp/gstbasertpdepayload.c:
+       (gst_base_rtp_depayload_class_init),
+       (gst_base_rtp_depayload_handle_sink_event), (create_segment_event),
+       (gst_base_rtp_depayload_packet_lost),
+       (gst_base_rtp_depayload_set_gst_timestamp):
+       * gst-libs/gst/rtp/gstbasertpdepayload.h:
+       Catch packet-lost events from the jitterbuffer and convert them into a
+       vmethod call (lost-packet) so that depayloaders can do something smart.
+       Also add a default packet-lost function that sends out a segment update
+       to the decoders.
+
 2008-05-02  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/playback/test4.c:
index 90f7aac..41cfb85 100644 (file)
@@ -70,7 +70,8 @@ enum
 enum
 {
   PROP_0,
-  PROP_QUEUE_DELAY
+  PROP_QUEUE_DELAY,
+  PROP_LAST
 };
 
 static void gst_base_rtp_depayload_finalize (GObject * object);
@@ -90,6 +91,8 @@ static GstStateChangeReturn gst_base_rtp_depayload_change_state (GstElement *
 
 static void gst_base_rtp_depayload_set_gst_timestamp
     (GstBaseRTPDepayload * filter, guint32 rtptime, GstBuffer * buf);
+static gboolean gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload *
+    filter, GstEvent * event);
 
 GST_BOILERPLATE (GstBaseRTPDepayload, gst_base_rtp_depayload, GstElement,
     GST_TYPE_ELEMENT);
@@ -134,6 +137,7 @@ gst_base_rtp_depayload_class_init (GstBaseRTPDepayloadClass * klass)
   gstelement_class->change_state = gst_base_rtp_depayload_change_state;
 
   klass->set_gst_timestamp = gst_base_rtp_depayload_set_gst_timestamp;
+  klass->packet_lost = gst_base_rtp_depayload_packet_lost;
 
   GST_DEBUG_CATEGORY_INIT (basertpdepayload_debug, "basertpdepayload", 0,
       "Base class for RTP Depayloaders");
@@ -316,6 +320,29 @@ gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event)
       gst_event_unref (event);
       break;
     }
+    case GST_EVENT_CUSTOM_DOWNSTREAM:
+    {
+      GstBaseRTPDepayloadClass *bclass;
+
+      bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter);
+
+      if (gst_event_has_name (event, "GstRTPPacketLost")) {
+        /* we get this event from the jitterbuffer when it considers a packet as
+         * being lost. We send it to our packet_lost vmethod. The default
+         * implementation will make time progress by pushing out a NEWSEGMENT
+         * update event. Subclasses can override and to one of the following:
+         *  - Adjust timestamp/duration to something more accurate before
+         *    calling the parent (default) packet_lost method.
+         *  - do some more advanced error concealing on the already received
+         *    (fragmented) packets.
+         *  - ignore the packet lost.
+         */
+        if (bclass->packet_lost)
+          res = bclass->packet_lost (filter, event);
+      }
+      gst_event_unref (event);
+      break;
+    }
     default:
       /* pass other events forward */
       res = gst_pad_push_event (filter->srcpad, event);
@@ -402,6 +429,60 @@ gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * out_buf)
   return gst_base_rtp_depayload_push_full (filter, FALSE, 0, out_buf);
 }
 
+static GstEvent *
+create_segment_event (GstBaseRTPDepayload * filter, gboolean update,
+    GstClockTime position)
+{
+  GstEvent *event;
+  GstClockTime stop;
+  GstBaseRTPDepayloadPrivate *priv;
+
+  priv = filter->priv;
+
+  if (priv->npt_stop != -1)
+    stop = priv->npt_stop - priv->npt_start;
+  else
+    stop = -1;
+
+  event = gst_event_new_new_segment_full (update, priv->play_speed,
+      priv->play_scale, GST_FORMAT_TIME, position, stop,
+      position + priv->npt_start);
+
+  return event;
+}
+
+/* convert the PacketLost event form a jitterbuffer to a segment update.
+ * subclasses can override this.  */
+static gboolean
+gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload * filter,
+    GstEvent * event)
+{
+  GstBaseRTPDepayloadPrivate *priv;
+  GstClockTime timestamp, duration, position;
+  GstEvent *sevent;
+  const GstStructure *s;
+
+  priv = filter->priv;
+
+  s = gst_event_get_structure (event);
+
+  /* first start by parsing the timestamp and duration */
+  timestamp = -1;
+  duration = -1;
+
+  gst_structure_get_clock_time (s, "timestamp", &timestamp);
+  gst_structure_get_clock_time (s, "duration", &duration);
+
+  position = timestamp;
+  if (duration != -1)
+    position += duration;
+
+  /* update the current segment with the elapsed time */
+  sevent = create_segment_event (filter, TRUE, position);
+
+  return gst_pad_push_event (filter->srcpad, sevent);
+}
+
 static void
 gst_base_rtp_depayload_set_gst_timestamp (GstBaseRTPDepayload * filter,
     guint32 rtptime, GstBuffer * buf)
@@ -424,18 +505,8 @@ gst_base_rtp_depayload_set_gst_timestamp (GstBaseRTPDepayload * filter,
   /* if this is the first buffer send a NEWSEGMENT */
   if (filter->need_newsegment) {
     GstEvent *event;
-    GstClockTime stop, position;
-
-    if (priv->npt_stop != -1)
-      stop = priv->npt_stop - priv->npt_start;
-    else
-      stop = -1;
-
-    position = priv->npt_start;
 
-    event =
-        gst_event_new_new_segment_full (FALSE, priv->play_speed,
-        priv->play_scale, GST_FORMAT_TIME, 0, stop, position);
+    event = create_segment_event (filter, FALSE, 0);
 
     gst_pad_push_event (filter->srcpad, event);
 
index a22f37c..34ecd16 100644 (file)
@@ -113,8 +113,13 @@ struct _GstBaseRTPDepayloadClass
    * this function is used by the child class before gst_pad_pushing */
   void (*set_gst_timestamp) (GstBaseRTPDepayload *filter, guint32 timestamp, GstBuffer *buf);
 
+  /* non-pure function used to to signal the depayloader about packet loss. the
+   * timestamp and duration are the estimated values of the lost packet.
+   * The default implementation of this message pushes a segment update. */
+  gboolean (*packet_lost) (GstBaseRTPDepayload *filter, GstEvent *event);
+
   /*< private >*/
-  gpointer _gst_reserved[GST_PADDING];
+  gpointer _gst_reserved[GST_PADDING-1];
 };
 
 GType gst_base_rtp_depayload_get_type (void);