dvdemux: Remember if upstream had a time segment and if not properly create time...
authorSebastian Dröge <sebastian@centricular.com>
Fri, 3 Jun 2016 07:36:32 +0000 (10:36 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 3 Jun 2016 10:13:21 +0000 (13:13 +0300)
Previously the segment.time was wrong, and the position was not updated
correctly, resulting in seeks in PUSH mode with upstream providing a BYTES
segment to not work at all.

https://bugzilla.gnome.org/show_bug.cgi?id=767157

ext/dv/gstdvdemux.c
ext/dv/gstdvdemux.h

index 3ac61b7..e02a006 100644 (file)
@@ -268,6 +268,7 @@ gst_dvdemux_reset (GstDVDemux * dvdemux)
   dvdemux->wide = FALSE;
   gst_segment_init (&dvdemux->byte_segment, GST_FORMAT_BYTES);
   gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
+  dvdemux->upstream_time_segment = FALSE;
   dvdemux->have_group_id = FALSE;
   dvdemux->group_id = G_MAXUINT;
 }
@@ -797,6 +798,8 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
         case GST_FORMAT_TIME:
           gst_segment_copy_into (segment, &dvdemux->time_segment);
 
+          dvdemux->upstream_time_segment = TRUE;
+
           /* and we can just forward this time event */
           res = gst_dvdemux_push_event (dvdemux, event);
           break;
@@ -1484,9 +1487,11 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
   GstSMPTETimeCode timecode;
   int frame_number;
 
-  if (G_UNLIKELY (dvdemux->need_segment)) {
+  if (dvdemux->need_segment) {
     GstFormat format;
 
+    g_assert (!dvdemux->upstream_time_segment);
+
     /* convert to time and store as start/end_timestamp */
     format = GST_FORMAT_TIME;
     if (!(gst_dvdemux_convert_sink_pair (dvdemux,
@@ -1496,8 +1501,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
                 (gint64 *) & dvdemux->time_segment.stop)))
       goto segment_error;
 
+    dvdemux->time_segment.time = dvdemux->time_segment.start;
     dvdemux->time_segment.rate = dvdemux->byte_segment.rate;
-    dvdemux->time_segment.position = dvdemux->time_segment.start;
+
+    gst_dvdemux_sink_convert (dvdemux,
+        GST_FORMAT_BYTES, dvdemux->byte_segment.position,
+        GST_FORMAT_TIME, (gint64 *) & dvdemux->time_segment.position);
 
     gst_dvdemux_update_frame_offsets (dvdemux, dvdemux->time_segment.position);
 
@@ -1652,6 +1661,10 @@ gst_dvdemux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
     gst_adapter_clear (dvdemux->adapter);
     dvdemux->discont = TRUE;
+
+    /* Should recheck where we are */
+    if (!dvdemux->upstream_time_segment)
+      dvdemux->need_segment = TRUE;
   }
 
   /* a timestamp always should be respected */
@@ -1662,6 +1675,11 @@ gst_dvdemux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
     if (dvdemux->discont)
       gst_dvdemux_update_frame_offsets (dvdemux,
           dvdemux->time_segment.position);
+  } else if (dvdemux->upstream_time_segment && dvdemux->discont) {
+    /* This will probably fail later to provide correct
+     * timestamps and/or durations but also should not happen */
+    GST_ERROR_OBJECT (dvdemux,
+        "Upstream provides TIME segment but no PTS after discont");
   }
 
   gst_adapter_push (dvdemux->adapter, buffer);
index 4f69433..be1d783 100644 (file)
@@ -76,6 +76,7 @@ struct _GstDVDemux {
 
   GstDVDemuxSeekHandler seek_handler;
   GstSegment     byte_segment;
+  gboolean       upstream_time_segment;
   GstSegment     time_segment;
   gboolean       need_segment;
   gboolean       new_media;