isomp4/qtmux: Write correct file duration when gaps exist.
authorJan Schmidt <jan@centricular.com>
Thu, 7 Aug 2014 17:58:14 +0000 (03:58 +1000)
committerJan Schmidt <jan@centricular.com>
Thu, 7 Aug 2014 18:01:19 +0000 (04:01 +1000)
When writing out a trak with an edit list, make sure the
overall file duration is also updated to reflect the
lengthening of the stream.

Add some more debug to qtdemux to warn about streams that
are longer than the file and get truncated.

gst/isomp4/gstqtmux.c
gst/isomp4/qtdemux.c

index 08aa05c..11ab253 100644 (file)
@@ -2002,7 +2002,15 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
           (guint32) (1 * 65536.0));
 
       /* need to add the empty time to the trak duration */
-      qtpad->trak->tkhd.duration += lateness;
+      duration += lateness;
+
+      qtpad->trak->tkhd.duration = duration;
+
+      /* And possibly grow the moov duration */
+      if (duration > qtmux->moov->mvhd.time_info.duration) {
+        qtmux->moov->mvhd.time_info.duration = duration;
+        qtmux->moov->mvex.mehd.fragment_duration = duration;
+      }
     }
   }
 
index 4348d12..08942a4 100644 (file)
@@ -3516,15 +3516,15 @@ gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
       stream->to_sample = G_MAXUINT32;
       GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
           ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
-          GST_TIME_ARGS (gst_util_uint64_scale (stream->
-                  samples[index].timestamp, GST_SECOND, stream->timescale)));
+          GST_TIME_ARGS (gst_util_uint64_scale (stream->samples[index].
+                  timestamp, GST_SECOND, stream->timescale)));
     } else {
       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
       stream->to_sample = index;
       GST_DEBUG_OBJECT (qtdemux, "moving data pointer to %" GST_TIME_FORMAT
           ", index: %u, pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
-          GST_TIME_ARGS (gst_util_uint64_scale (stream->
-                  samples[index].timestamp, GST_SECOND, stream->timescale)));
+          GST_TIME_ARGS (gst_util_uint64_scale (stream->samples[index].
+                  timestamp, GST_SECOND, stream->timescale)));
     }
   } else {
     GST_DEBUG_OBJECT (qtdemux, "No need to look for keyframe, "
@@ -3619,8 +3619,8 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
   if (G_UNLIKELY (stream->segment_index != seg_idx))
     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
 
-  if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
-              segments[stream->segment_index]))) {
+  if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
+                  segment_index]))) {
     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
 
     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
@@ -6833,10 +6833,21 @@ qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
       }
 
       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
-          ", duration %" GST_TIME_FORMAT ", media_time %" GST_TIME_FORMAT
-          ", rate %g, (%d)", i, GST_TIME_ARGS (segment->time),
+          ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
+          ", media_stop %" GST_TIME_FORMAT " stop_time %" GST_TIME_FORMAT
+          " rate %g, (%d)", i, GST_TIME_ARGS (segment->time),
           GST_TIME_ARGS (segment->duration),
-          GST_TIME_ARGS (segment->media_start), segment->rate, rate_int);
+          GST_TIME_ARGS (segment->media_start),
+          GST_TIME_ARGS (segment->media_stop),
+          GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int);
+      if (segment->stop_time > qtdemux->segment.stop) {
+        GST_WARNING_OBJECT (qtdemux, "Segment %d "
+            " extends to %" GST_TIME_FORMAT
+            " past the end of the file duration %" GST_TIME_FORMAT
+            " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
+            GST_TIME_ARGS (qtdemux->segment.stop));
+        qtdemux->segment.stop = segment->stop_time;
+      }
     }
     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
     stream->n_segments = count;
@@ -10229,14 +10240,6 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
       qtdemux_parse_mehd (qtdemux, &mehd_data);
   }
 
-  /* parse all traks */
-  trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
-  while (trak) {
-    qtdemux_parse_trak (qtdemux, trak);
-    /* iterate all siblings */
-    trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
-  }
-
   /* set duration in the segment info */
   gst_qtdemux_get_duration (qtdemux, &duration);
   if (duration) {
@@ -10247,6 +10250,14 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
     qtdemux->segment.stop = duration;
   }
 
+  /* parse all traks */
+  trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
+  while (trak) {
+    qtdemux_parse_trak (qtdemux, trak);
+    /* iterate all siblings */
+    trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
+  }
+
   /* find tags */
   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
   if (udta) {