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 08aa05c6c52c6b77b69525b82b4da49fccaa6b14..11ab2536e33ff22eb7fc4cc1e816303130eb989d 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 4348d1203ec1ee0edb7a4c0be395b28baf8481bc..08942a43f9768d38520aeb4775090bb5386f4fa5 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) {