gst/realmedia/rdtdepay.*: Parse other values from the incomming caps.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 27 Aug 2008 15:55:05 +0000 (15:55 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 27 Aug 2008 15:55:05 +0000 (15:55 +0000)
Original commit message from CVS:
* gst/realmedia/rdtdepay.c: (gst_rdt_depay_init),
(gst_rdt_depay_setcaps), (gst_rdt_depay_sink_event),
(create_segment_event), (gst_rdt_depay_push),
(gst_rdt_depay_handle_data), (gst_rdt_depay_change_state):
* gst/realmedia/rdtdepay.h:
Parse other values from the incomming caps.
Add event handler to handle flushing and segments.
Create segment events.
* gst/realmedia/rdtjitterbuffer.c: (rdt_jitter_buffer_insert):
Do skew correction based on RDT timestamps.
* gst/realmedia/rdtmanager.c: (activate_session),
(gst_rdt_manager_parse_caps), (gst_rdt_manager_setcaps),
(create_recv_rtp):
Parse caps to get the clockrate needed for the jitterbuffer.
* gst/realmedia/rmdemux.c: (gst_rmdemux_parse_video_packet):
Apply timestamp fixup after correcting for initial timestamp and
internal base timestamp corrections.

ChangeLog
gst/realmedia/rdtdepay.c
gst/realmedia/rdtdepay.h
gst/realmedia/rdtjitterbuffer.c
gst/realmedia/rdtmanager.c
gst/realmedia/rmdemux.c

index 1e93d01..12a0604 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2008-08-27  Wim Taymans  <wim.taymans@collabora.co.uk>
 
+       * gst/realmedia/rdtdepay.c: (gst_rdt_depay_init),
+       (gst_rdt_depay_setcaps), (gst_rdt_depay_sink_event),
+       (create_segment_event), (gst_rdt_depay_push),
+       (gst_rdt_depay_handle_data), (gst_rdt_depay_change_state):
+       * gst/realmedia/rdtdepay.h:
+       Parse other values from the incomming caps.
+       Add event handler to handle flushing and segments.
+       Create segment events.
+
+       * gst/realmedia/rdtjitterbuffer.c: (rdt_jitter_buffer_insert):
+       Do skew correction based on RDT timestamps.
+
+       * gst/realmedia/rdtmanager.c: (activate_session),
+       (gst_rdt_manager_parse_caps), (gst_rdt_manager_setcaps),
+       (create_recv_rtp):
+       Parse caps to get the clockrate needed for the jitterbuffer.
+
+       * gst/realmedia/rmdemux.c: (gst_rmdemux_parse_video_packet):
+       Apply timestamp fixup after correcting for initial timestamp and
+       internal base timestamp corrections.
+
+2008-08-27  Wim Taymans  <wim.taymans@collabora.co.uk>
+
        * gst/realmedia/rdtdepay.c: (gst_rdt_depay_handle_data),
        (gst_rdt_depay_change_state):
        * gst/realmedia/rdtdepay.h:
index 3668da2..552b759 100644 (file)
@@ -84,6 +84,7 @@ static GstStateChangeReturn gst_rdt_depay_change_state (GstElement *
     element, GstStateChange transition);
 
 static gboolean gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps);
+static gboolean gst_rdt_depay_sink_event (GstPad * pad, GstEvent * event);
 static GstFlowReturn gst_rdt_depay_chain (GstPad * pad, GstBuffer * buf);
 
 static void
@@ -127,6 +128,7 @@ gst_rdt_depay_init (GstRDTDepay * rdtdepay, GstRDTDepayClass * klass)
   rdtdepay->sinkpad =
       gst_pad_new_from_static_template (&gst_rdt_depay_sink_template, "sink");
   gst_pad_set_chain_function (rdtdepay->sinkpad, gst_rdt_depay_chain);
+  gst_pad_set_event_function (rdtdepay->sinkpad, gst_rdt_depay_sink_event);
   gst_pad_set_setcaps_function (rdtdepay->sinkpad, gst_rdt_depay_setcaps);
   gst_element_add_pad (GST_ELEMENT_CAST (rdtdepay), rdtdepay->sinkpad);
 
@@ -155,7 +157,7 @@ gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps)
   GstRDTDepay *rdtdepay;
   GstCaps *srccaps;
   gint clock_rate = 1000;       /* default */
-  const GValue *config;
+  const GValue *value;
   GstBuffer *header;
 
   rdtdepay = GST_RDT_DEPAY (GST_PAD_PARENT (pad));
@@ -166,14 +168,44 @@ gst_rdt_depay_setcaps (GstPad * pad, GstCaps * caps)
     gst_structure_get_int (structure, "clock-rate", &clock_rate);
 
   /* config contains the RealMedia header as a buffer. */
-  config = gst_structure_get_value (structure, "config");
-  if (!config)
+  value = gst_structure_get_value (structure, "config");
+  if (!value)
     goto no_header;
 
-  header = gst_value_get_buffer (config);
+  header = gst_value_get_buffer (value);
   if (!header)
     goto no_header;
 
+  /* get other values for newsegment */
+  value = gst_structure_get_value (structure, "npt-start");
+  if (value && G_VALUE_HOLDS_UINT64 (value))
+    rdtdepay->npt_start = g_value_get_uint64 (value);
+  else
+    rdtdepay->npt_start = 0;
+  GST_DEBUG_OBJECT (rdtdepay, "NPT start %" G_GUINT64_FORMAT,
+      rdtdepay->npt_start);
+
+  value = gst_structure_get_value (structure, "npt-stop");
+  if (value && G_VALUE_HOLDS_UINT64 (value))
+    rdtdepay->npt_stop = g_value_get_uint64 (value);
+  else
+    rdtdepay->npt_stop = -1;
+
+  GST_DEBUG_OBJECT (rdtdepay, "NPT stop %" G_GUINT64_FORMAT,
+      rdtdepay->npt_stop);
+
+  value = gst_structure_get_value (structure, "play-speed");
+  if (value && G_VALUE_HOLDS_DOUBLE (value))
+    rdtdepay->play_speed = g_value_get_double (value);
+  else
+    rdtdepay->play_speed = 1.0;
+
+  value = gst_structure_get_value (structure, "play-scale");
+  if (value && G_VALUE_HOLDS_DOUBLE (value))
+    rdtdepay->play_scale = g_value_get_double (value);
+  else
+    rdtdepay->play_scale = 1.0;
+
   /* caps seem good, configure element */
   rdtdepay->clock_rate = clock_rate;
 
@@ -196,11 +228,81 @@ no_header:
   }
 }
 
+static gboolean
+gst_rdt_depay_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstRDTDepay *depay;
+  gboolean res = TRUE;
+
+  depay = GST_RDT_DEPAY (GST_OBJECT_PARENT (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_FLUSH_STOP:
+      res = gst_pad_push_event (depay->srcpad, event);
+
+      gst_segment_init (&depay->segment, GST_FORMAT_UNDEFINED);
+      depay->need_newsegment = TRUE;
+      depay->next_seqnum = -1;
+      break;
+    case GST_EVENT_NEWSEGMENT:
+    {
+      gboolean update;
+      gdouble rate;
+      GstFormat fmt;
+      gint64 start, stop, position;
+
+      gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop,
+          &position);
+
+      gst_segment_set_newsegment (&depay->segment, update, rate, fmt,
+          start, stop, position);
+
+      /* don't pass the event downstream, we generate our own segment
+       * including the NTP time and other things we receive in caps */
+      gst_event_unref (event);
+      break;
+    }
+    default:
+      /* pass other events forward */
+      res = gst_pad_push_event (depay->srcpad, event);
+      break;
+  }
+  return res;
+}
+
+static GstEvent *
+create_segment_event (GstRDTDepay * depay, gboolean update,
+    GstClockTime position)
+{
+  GstEvent *event;
+  GstClockTime stop;
+
+  if (depay->npt_stop != -1)
+    stop = depay->npt_stop - depay->npt_start;
+  else
+    stop = -1;
+
+  event = gst_event_new_new_segment_full (update, depay->play_speed,
+      depay->play_scale, GST_FORMAT_TIME, position, stop,
+      position + depay->npt_start);
+
+  return event;
+}
+
 static GstFlowReturn
 gst_rdt_depay_push (GstRDTDepay * rdtdepay, GstBuffer * buffer)
 {
   GstFlowReturn ret;
 
+  if (rdtdepay->need_newsegment) {
+    GstEvent *event;
+
+    event = create_segment_event (rdtdepay, FALSE, 0);
+    gst_pad_push_event (rdtdepay->srcpad, event);
+
+    rdtdepay->need_newsegment = FALSE;
+  }
+
   gst_buffer_set_caps (buffer, GST_PAD_CAPS (rdtdepay->srcpad));
 
   if (rdtdepay->discont) {
@@ -224,7 +326,6 @@ gst_rdt_depay_handle_data (GstRDTDepay * rdtdepay, GstClockTime outtime,
   guint32 timestamp;
   gint gap;
   guint16 seqnum;
-  gboolean discont;
 
   /* get pointers to the packet data */
   gst_rdt_packet_data_peek_data (packet, &data, &size);
@@ -399,7 +500,9 @@ gst_rdt_depay_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      gst_segment_init (&rdtdepay->segment, GST_FORMAT_UNDEFINED);
       rdtdepay->next_seqnum = -1;
+      rdtdepay->need_newsegment = TRUE;
       break;
     default:
       break;
index 9099a41..7bacae6 100644 (file)
@@ -47,9 +47,16 @@ struct _GstRDTDepay
   GstPad *srcpad;
 
   guint clock_rate;
+  GstClockTime npt_start;
+  GstClockTime npt_stop;
+  gdouble play_speed;
+  gdouble play_scale;
+
   guint32 next_seqnum;
 
   gboolean discont;
+  gboolean need_newsegment;
+  GstSegment segment;
   GstBuffer *header;
 };
 
index 5e622a6..1e34c50 100644 (file)
@@ -360,6 +360,10 @@ rdt_jitter_buffer_insert (RDTJitterBuffer * jbuf, GstBuffer * buf,
   g_return_val_if_fail (more == TRUE, FALSE);
 
   seqnum = gst_rdt_packet_data_get_seq (&packet);
+  /* do skew calculation by measuring the difference between rtptime and the
+   * receive time, this function will retimestamp @buf with the skew corrected
+   * running time. */
+  rtptime = gst_rdt_packet_data_get_timestamp (&packet);
 
   /* loop the list to skip strictly smaller seqnum buffers */
   for (list = jbuf->packets->head; list; list = g_list_next (list)) {
@@ -385,11 +389,7 @@ rdt_jitter_buffer_insert (RDTJitterBuffer * jbuf, GstBuffer * buf,
       break;
   }
 
-  /* do skew calculation by measuring the difference between rtptime and the
-   * receive time, this function will retimestamp @buf with the skew corrected
-   * running time. */
-  //rtptime = gst_rtp_buffer_get_timestamp (buf);
-  rtptime = 0;
+
   if (clock_rate) {
     time = calculate_skew (jbuf, rtptime, time, clock_rate);
     GST_BUFFER_TIMESTAMP (buf) = time;
index 1d4540e..6dd0b41 100644 (file)
@@ -136,6 +136,10 @@ static GstPad *gst_rdt_manager_request_new_pad (GstElement * element,
     GstPadTemplate * templ, const gchar * name);
 static void gst_rdt_manager_release_pad (GstElement * element, GstPad * pad);
 
+static gboolean gst_rdt_manager_parse_caps (GstRDTManager * rdtmanager,
+    GstRDTManagerSession * session, GstCaps * caps);
+static gboolean gst_rdt_manager_setcaps (GstPad * pad, GstCaps * caps);
+
 static GstFlowReturn gst_rdt_manager_chain_rdt (GstPad * pad,
     GstBuffer * buffer);
 static GstFlowReturn gst_rdt_manager_chain_rtcp (GstPad * pad,
@@ -181,6 +185,7 @@ struct _GstRDTManagerSession
   guint8 pt;
   gint clock_rate;
   GstCaps *caps;
+  gint64 clock_base;
 
   GstSegment segment;
 
@@ -279,7 +284,14 @@ activate_session (GstRDTManager * rdtmanager, GstRDTManagerSession * session,
   g_signal_emitv (args, gst_rdt_manager_signals[SIGNAL_REQUEST_PT_MAP], 0,
       &ret);
 
-  caps = (GstCaps *) g_value_get_boxed (&ret);
+  g_value_unset (&args[0]);
+  g_value_unset (&args[1]);
+  g_value_unset (&args[2]);
+  caps = (GstCaps *) g_value_dup_boxed (&ret);
+  g_value_unset (&ret);
+
+  if (caps)
+    gst_rdt_manager_parse_caps (rdtmanager, session, caps);
 
   name = g_strdup_printf ("recv_rtp_src_%d_%u_%d", session->id, ssrc, pt);
   klass = GST_ELEMENT_GET_CLASS (rdtmanager);
@@ -288,6 +300,7 @@ activate_session (GstRDTManager * rdtmanager, GstRDTManagerSession * session,
   g_free (name);
 
   gst_pad_set_caps (session->recv_rtp_src, caps);
+  gst_caps_unref (caps);
 
   gst_pad_set_element_private (session->recv_rtp_src, session);
   gst_pad_set_query_function (session->recv_rtp_src, gst_rdt_manager_query_src);
@@ -651,6 +664,73 @@ duplicate:
   }
 }
 
+static gboolean
+gst_rdt_manager_parse_caps (GstRDTManager * rdtmanager,
+    GstRDTManagerSession * session, GstCaps * caps)
+{
+  GstStructure *caps_struct;
+  guint val;
+
+  /* first parse the caps */
+  caps_struct = gst_caps_get_structure (caps, 0);
+
+  GST_DEBUG_OBJECT (rdtmanager, "got caps");
+
+  /* we need a clock-rate to convert the rtp timestamps to GStreamer time and to
+   * measure the amount of data in the buffer */
+  if (!gst_structure_get_int (caps_struct, "clock-rate", &session->clock_rate))
+    session->clock_rate = 1000;
+
+  if (session->clock_rate <= 0)
+    goto wrong_rate;
+
+  GST_DEBUG_OBJECT (rdtmanager, "got clock-rate %d", session->clock_rate);
+
+  /* gah, clock-base is uint. If we don't have a base, we will use the first
+   * buffer timestamp as the base time. This will screw up sync but it's better
+   * than nothing. */
+  if (gst_structure_get_uint (caps_struct, "clock-base", &val))
+    session->clock_base = val;
+  else
+    session->clock_base = -1;
+
+  GST_DEBUG_OBJECT (rdtmanager, "got clock-base %" G_GINT64_FORMAT,
+      session->clock_base);
+
+  /* first expected seqnum */
+  if (gst_structure_get_uint (caps_struct, "seqnum-base", &val))
+    session->next_seqnum = val;
+  else
+    session->next_seqnum = -1;
+
+  GST_DEBUG_OBJECT (rdtmanager, "got seqnum-base %d", session->next_seqnum);
+
+  return TRUE;
+
+  /* ERRORS */
+wrong_rate:
+  {
+    GST_DEBUG_OBJECT (rdtmanager, "Invalid clock-rate %d", session->clock_rate);
+    return FALSE;
+  }
+}
+
+static gboolean
+gst_rdt_manager_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstRDTManager *rdtmanager;
+  GstRDTManagerSession *session;
+  gboolean res;
+
+  rdtmanager = GST_RDT_MANAGER (GST_PAD_PARENT (pad));
+  /* find session */
+  session = gst_pad_get_element_private (pad);
+
+  res = gst_rdt_manager_parse_caps (rdtmanager, session, caps);
+
+  return res;
+}
+
 static GstFlowReturn
 gst_rdt_manager_chain_rdt (GstPad * pad, GstBuffer * buffer)
 {
@@ -1072,6 +1152,8 @@ create_recv_rtp (GstRDTManager * rdtmanager, GstPadTemplate * templ,
 
   session->recv_rtp_sink = gst_pad_new_from_template (templ, name);
   gst_pad_set_element_private (session->recv_rtp_sink, session);
+  gst_pad_set_setcaps_function (session->recv_rtp_sink,
+      gst_rdt_manager_setcaps);
   gst_pad_set_chain_function (session->recv_rtp_sink,
       gst_rdt_manager_chain_rdt);
   gst_pad_set_active (session->recv_rtp_sink, TRUE);
index bf9b1df..6384b12 100644 (file)
@@ -2311,16 +2311,18 @@ gst_rmdemux_parse_video_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
       stream->frag_length = 0;
 
       gst_buffer_set_caps (out, GST_PAD_CAPS (stream->pad));
-      timestamp =
-          gst_rmdemux_fix_timestamp (rmdemux, stream, outdata, timestamp);
 
-      if (rmdemux->first_ts != -1 && timestamp > rmdemux->first_ts)
-        timestamp -= rmdemux->first_ts;
-      else
-        timestamp = 0;
+      if (timestamp != -1) {
+        if (rmdemux->first_ts != -1 && timestamp > rmdemux->first_ts)
+          timestamp -= rmdemux->first_ts;
+        else
+          timestamp = 0;
 
-      if (rmdemux->base_ts != -1)
-        timestamp += rmdemux->base_ts;
+        if (rmdemux->base_ts != -1)
+          timestamp += rmdemux->base_ts;
+      }
+      timestamp =
+          gst_rmdemux_fix_timestamp (rmdemux, stream, outdata, timestamp);
 
       GST_BUFFER_TIMESTAMP (out) = timestamp;