isomp4: Update edit list when re-writing moov
authorJan Schmidt <jan@centricular.com>
Tue, 31 Mar 2015 13:58:52 +0000 (00:58 +1100)
committerJan Schmidt <jan@centricular.com>
Mon, 8 Jun 2015 04:16:36 +0000 (14:16 +1000)
Correctly update any edit lists each time the moov is recalculated,
updating existing table entries if they already exist instead of just
adding new ones.

gst/isomp4/atoms.c
gst/isomp4/atoms.h
gst/isomp4/gstqtmux.c

index a8ca9cdcf0ecff59a8640e1d70cd7369b77d789e..4ac76703d7515bb2cbd80f4da207ef5d035c2125 100644 (file)
@@ -3279,31 +3279,41 @@ atom_tkhd_set_subtitle (AtomTKHD * tkhd, AtomsContext * context, guint32 width,
 
 
 static void
-atom_edts_add_entry (AtomEDTS * edts, EditListEntry * entry)
+atom_edts_add_entry (AtomEDTS * edts, gint index, EditListEntry * entry)
 {
-  edts->elst.entries = g_slist_append (edts->elst.entries, entry);
+  EditListEntry *e =
+      (EditListEntry *) g_slist_nth_data (edts->elst.entries, index);
+  /* Create a new entry if missing (appends to the list if index is larger) */
+  if (e == NULL) {
+    e = g_new (EditListEntry, 1);
+    edts->elst.entries = g_slist_insert (edts->elst.entries, e, index);
+  }
+
+  /* Update the entry */
+  *e = *entry;
 }
 
-/* 
- * Adds a new entry to this trak edits list
+/*
+ * Update an entry in this trak edits list, creating it if needed.
+ * index is the index of the entry to update, or create if it's past the end.
  * duration is in the moov's timescale
  * media_time is the offset in the media time to start from (media's timescale)
  * rate is a 32 bits fixed-point
  */
 void
-atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration, guint32 media_time,
-    guint32 rate)
+atom_trak_set_elst_entry (AtomTRAK * trak, gint index,
+    guint32 duration, guint32 media_time, guint32 rate)
 {
-  EditListEntry *entry = g_new (EditListEntry, 1);
+  EditListEntry entry;
 
-  entry->duration = duration;
-  entry->media_time = media_time;
-  entry->media_rate = rate;
+  entry.duration = duration;
+  entry.media_time = media_time;
+  entry.media_rate = rate;
 
-  if (trak->edts == NULL) {
+  if (trak->edts == NULL)
     trak->edts = atom_edts_new ();
-  }
-  atom_edts_add_entry (trak->edts, entry);
+
+  atom_edts_add_entry (trak->edts, index, &entry);
 }
 
 /* re-negotiation is prevented at top-level, so only 1 entry expected.
index a54838093db295914a104b81243e4cf8d51b71f5..943dfd6ee43dab15590917c97b937662e3023142 100644 (file)
@@ -828,7 +828,7 @@ AtomTRAK*  atom_trak_new               (AtomsContext *context);
 void       atom_trak_add_samples       (AtomTRAK * trak, guint32 nsamples, guint32 delta,
                                         guint32 size, guint64 chunk_offset, gboolean sync,
                                         gint64 pts_offset);
-void       atom_trak_add_elst_entry    (AtomTRAK * trak, guint32 duration,
+void       atom_trak_set_elst_entry    (AtomTRAK * trak, gint index, guint32 duration,
                                         guint32 media_time, guint32 rate);
 guint32    atom_trak_get_timescale     (AtomTRAK *trak);
 guint32    atom_trak_get_id            (AtomTRAK * trak);
index d1426b179d78e199cf6ca2aee06cebbbf3508fdd..d20ac9b894d0685731d042bab42a011b71393761 100644 (file)
@@ -249,7 +249,6 @@ enum
 #define DEFAULT_DTS_METHOD              DTS_METHOD_REORDER
 #endif
 
-
 static void gst_qt_mux_finalize (GObject * object);
 
 static GstStateChangeReturn gst_qt_mux_change_state (GstElement * element,
@@ -2110,25 +2109,29 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
       first_ts = qtpad->first_ts;
     }
   }
+
   GST_DEBUG_OBJECT (qtmux, "Media first ts selected: %" GST_TIME_FORMAT,
       GST_TIME_ARGS (first_ts));
-  /* add EDTSs for late streams */
+  /* add/update EDTSs for late streams. configure_moov will have
+   * set the trak durations above by summing the sample tables */
   for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
     GstCollectData *cdata = (GstCollectData *) walk->data;
     GstQTPad *qtpad = (GstQTPad *) cdata;
     guint32 lateness;
     guint32 duration;
 
-    if (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) && qtpad->first_ts > first_ts) {
+    if (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts)
+        && qtpad->first_ts > first_ts) {
       GST_DEBUG_OBJECT (qtmux, "Pad %s is a late stream by %" GST_TIME_FORMAT,
           GST_PAD_NAME (qtpad->collect.pad),
           GST_TIME_ARGS (qtpad->first_ts - first_ts));
-      lateness = gst_util_uint64_scale_round (qtpad->first_ts - first_ts,
-          timescale, GST_SECOND);
+      lateness =
+          gst_util_uint64_scale_round (qtpad->first_ts - first_ts, timescale,
+          GST_SECOND);
       duration = qtpad->trak->tkhd.duration;
-      atom_trak_add_elst_entry (qtpad->trak, lateness, (guint32) - 1,
+      atom_trak_set_elst_entry (qtpad->trak, 0, lateness, (guint32) - 1,
           (guint32) (1 * 65536.0));
-      atom_trak_add_elst_entry (qtpad->trak, duration, 0,
+      atom_trak_set_elst_entry (qtpad->trak, 1, duration, 0,
           (guint32) (1 * 65536.0));
 
       /* need to add the empty time to the trak duration */