flvmux: Add negative runtime DTS support
[platform/upstream/gst-plugins-good.git] / gst / flv / gstflvmux.c
index ba08603..e13b24f 100644 (file)
@@ -253,6 +253,7 @@ gst_flv_mux_reset (GstElement * element)
   mux->have_audio = mux->have_video = FALSE;
   mux->duration = GST_CLOCK_TIME_NONE;
   mux->new_tags = FALSE;
+  mux->first_timestamp = GST_CLOCK_STIME_NONE;
 
   mux->state = GST_FLV_MUX_STATE_HEADER;
 
@@ -529,8 +530,9 @@ gst_flv_mux_reset_pad (GstFlvMux * mux, GstFlvPad * cpad, gboolean video)
     gst_buffer_unref (cpad->video_codec_data);
   cpad->video_codec_data = NULL;
   cpad->video_codec = G_MAXUINT;
-  cpad->first_timestamp = GST_CLOCK_TIME_NONE;
   cpad->last_timestamp = 0;
+  cpad->pts = GST_CLOCK_STIME_NONE;
+  cpad->dts = GST_CLOCK_STIME_NONE;
 }
 
 static GstPad *
@@ -1006,26 +1008,24 @@ gst_flv_mux_buffer_to_tag_internal (GstFlvMux * mux, GstBuffer * buffer,
   guint8 *data, *bdata;
   gsize bsize;
 
-  if (GST_BUFFER_DTS_IS_VALID (buffer))
-    dts = GST_BUFFER_DTS (buffer) / GST_MSECOND;
-  else
-    dts = cpad->last_timestamp / GST_MSECOND;
-
-  if (GST_BUFFER_PTS_IS_VALID (buffer))
-    pts = GST_BUFFER_PTS (buffer) / GST_MSECOND;
-  else
-    pts = dts;
+  if (GST_CLOCK_STIME_IS_VALID (cpad->dts)) {
+    pts = dts = cpad->last_timestamp / GST_MSECOND;
+  } else {
+    pts = cpad->pts / GST_MSECOND;
+    dts = cpad->dts / GST_MSECOND;
+  }
 
+  /* Be safe in case TS are buggy */
   if (pts > dts)
     cts = pts - dts;
   else
     cts = 0;
 
-  if (!GST_CLOCK_TIME_IS_VALID (cpad->first_timestamp))
-    cpad->first_timestamp = dts;
-
   /* Timestamp must start at zero */
-  dts -= cpad->first_timestamp;
+  if (GST_CLOCK_STIME_IS_VALID (mux->first_timestamp)) {
+    dts -= mux->first_timestamp / GST_MSECOND;
+    pts = dts + cts;
+  }
 
   GST_LOG_OBJECT (mux, "got pts %i dts %i cts %i\n", pts, dts, cts);
 
@@ -1301,6 +1301,7 @@ gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad, GstBuffer * buffer)
 {
   GstBuffer *tag;
   GstFlowReturn ret;
+  GstClockTime dts = GST_BUFFER_DTS (buffer);
 
   /* clipping function arranged for running_time */
 
@@ -1313,8 +1314,9 @@ gst_flv_mux_write_buffer (GstFlvMux * mux, GstFlvPad * cpad, GstBuffer * buffer)
 
   ret = gst_flv_mux_push (mux, tag);
 
-  if (ret == GST_FLOW_OK && GST_BUFFER_DTS_IS_VALID (tag))
-    cpad->last_timestamp = GST_BUFFER_DTS (tag);
+  if (ret == GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (dts))
+    cpad->last_timestamp = dts;
+
 
   return ret;
 }
@@ -1486,7 +1488,7 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
 {
   GstFlvMux *mux = GST_FLV_MUX (user_data);
   GstFlvPad *best;
-  GstClockTime best_time;
+  gint64 best_time;
   GstFlowReturn ret;
 
   if (mux->state == GST_FLV_MUX_STATE_HEADER) {
@@ -1500,6 +1502,11 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
     if (ret != GST_FLOW_OK)
       return ret;
     mux->state = GST_FLV_MUX_STATE_DATA;
+
+    if (GST_COLLECT_PADS_DTS_IS_VALID (cdata))
+      mux->first_timestamp = GST_COLLECT_PADS_DTS (cdata);
+    else
+      mux->first_timestamp = 0;
   }
 
   if (mux->new_tags) {
@@ -1512,15 +1519,27 @@ gst_flv_mux_handle_buffer (GstCollectPads * pads, GstCollectData * cdata,
   best = (GstFlvPad *) cdata;
   if (best) {
     g_assert (buffer);
-    best_time = GST_BUFFER_DTS (buffer);
+    best->dts = GST_COLLECT_PADS_DTS (cdata);
+
+    if (GST_CLOCK_STIME_IS_VALID (best->dts))
+      best_time = best->dts - mux->first_timestamp;
+
+    if (GST_BUFFER_PTS_IS_VALID (buffer))
+      best->pts = GST_BUFFER_PTS (buffer);
+    else
+      best->pts = best->dts;
+
+    GST_LOG_OBJECT (mux, "got buffer PTS %" GST_TIME_FORMAT " DTS %"
+        GST_STIME_FORMAT "\n", GST_TIME_ARGS (best->pts),
+        GST_STIME_ARGS (best->dts));
   } else {
-    best_time = GST_CLOCK_TIME_NONE;
+    best_time = GST_CLOCK_STIME_NONE;
   }
 
   /* The FLV timestamp is an int32 field. For non-live streams error out if a
      bigger timestamp is seen, for live the timestamp will get wrapped in
      gst_flv_mux_buffer_to_tag */
-  if (!mux->streamable && GST_CLOCK_TIME_IS_VALID (best_time)
+  if (!mux->streamable && (GST_CLOCK_STIME_IS_VALID (best_time))
       && best_time / GST_MSECOND > G_MAXINT32) {
     GST_WARNING_OBJECT (mux, "Timestamp larger than FLV supports - EOS");
     gst_buffer_unref (buffer);