qtmux: include sdtp atoms for ismv fragmented files
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Fri, 19 Nov 2010 16:41:41 +0000 (17:41 +0100)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 12 Apr 2011 19:32:19 +0000 (20:32 +0100)
Based on patch by Marc-André Lureau <mlureau@flumotion.com>

gst/quicktime/atoms.c
gst/quicktime/atoms.h
gst/quicktime/gstqtmux.c

index 7556078..2fcb45f 100644 (file)
@@ -3324,6 +3324,14 @@ atom_trun_free (AtomTRUN * trun)
   g_free (trun);
 }
 
+static void
+atom_sdtp_free (AtomSDTP * sdtp)
+{
+  atom_full_clear (&sdtp->header);
+  atom_array_clear (&sdtp->entries);
+  g_free (sdtp);
+}
+
 void
 atom_traf_free (AtomTRAF * traf)
 {
@@ -3337,6 +3345,14 @@ atom_traf_free (AtomTRAF * traf)
   g_list_free (traf->truns);
   traf->truns = NULL;
 
+  walker = traf->sdtps;
+  while (walker) {
+    atom_sdtp_free ((AtomSDTP *) walker->data);
+    walker = g_list_next (walker);
+  }
+  g_list_free (traf->sdtps);
+  traf->sdtps = NULL;
+
   g_free (traf);
 }
 
@@ -3453,6 +3469,24 @@ atom_trun_copy_data (AtomTRUN * trun, guint8 ** buffer, guint64 * size,
 }
 
 static guint64
+atom_sdtp_copy_data (AtomSDTP * sdtp, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&sdtp->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  /* all entries at once */
+  prop_copy_fixed_size_string (&atom_array_index (&sdtp->entries, 0),
+      atom_array_get_len (&sdtp->entries), buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
 atom_traf_copy_data (AtomTRAF * traf, guint8 ** buffer, guint64 * size,
     guint64 * offset, guint32 * data_offset)
 {
@@ -3475,6 +3509,14 @@ atom_traf_copy_data (AtomTRAF * traf, guint8 ** buffer, guint64 * size,
     walker = g_list_next (walker);
   }
 
+  walker = g_list_first (traf->sdtps);
+  while (walker != NULL) {
+    if (!atom_sdtp_copy_data ((AtomSDTP *) walker->data, buffer, size, offset)) {
+      return 0;
+    }
+    walker = g_list_next (walker);
+  }
+
   atom_write_size (buffer, size, offset, original_offset);
   return *offset - original_offset;
 }
@@ -3551,6 +3593,38 @@ atom_trun_new (void)
 }
 
 static void
+atom_sdtp_init (AtomSDTP * sdtp)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+
+  atom_full_init (&sdtp->header, FOURCC_sdtp, 0, 0, 0, flags);
+  atom_array_init (&sdtp->entries, 512);
+}
+
+static AtomSDTP *
+atom_sdtp_new (AtomsContext * context)
+{
+  AtomSDTP *sdtp = g_new0 (AtomSDTP, 1);
+
+  atom_sdtp_init (sdtp);
+  return sdtp;
+}
+
+static void
+atom_traf_add_sdtp (AtomTRAF * traf, AtomSDTP * sdtp)
+{
+  traf->sdtps = g_list_append (traf->sdtps, sdtp);
+}
+
+static void
+atom_sdtp_add_samples (AtomSDTP * sdtp, guint8 val)
+{
+  /* it does not make much/any sense according to specs,
+   * but that's how MS isml samples seem to do it */
+  atom_array_append (&sdtp->entries, val, 256);
+}
+
+static void
 atom_trun_add_samples (AtomTRUN * trun, guint32 delta, guint32 size,
     guint32 flags, gboolean do_pts, gint64 pts_offset)
 {
@@ -3574,6 +3648,9 @@ atom_traf_init (AtomTRAF * traf, AtomsContext * context, guint32 track_ID)
   atom_header_set (&traf->header, FOURCC_traf, 0, 0);
   atom_tfhd_init (&traf->tfhd, track_ID);
   traf->truns = NULL;
+
+  if (context->flavor == ATOMS_TREE_FLAVOR_ISML)
+    atom_traf_add_sdtp (traf, atom_sdtp_new (context));
 }
 
 AtomTRAF *
@@ -3593,14 +3670,14 @@ atom_traf_add_trun (AtomTRAF * traf, AtomTRUN * trun)
 
 void
 atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size,
-    gboolean sync, gboolean do_pts, gint64 pts_offset)
+    gboolean sync, gboolean do_pts, gint64 pts_offset, gboolean sdtp_sync)
 {
   AtomTRUN *trun;
   guint32 flags;
 
   /* 0x10000 is sample-is-difference-sample flag
    * low byte stuff is what ismv uses */
-  flags = sync ? 0x0040 : 0x1000c;
+  flags = (sync ? 0x0 : 0x10000) | (sdtp_sync ? 0x40 : 0xc0);
 
   if (G_UNLIKELY (!traf->truns)) {
     trun = atom_trun_new ();
@@ -3641,6 +3718,9 @@ atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size,
 
   atom_trun_add_samples (traf->truns->data, delta, size, flags, do_pts,
       pts_offset);
+
+  if (traf->sdtps)
+    atom_sdtp_add_samples (traf->sdtps->data, 0x10 | ((flags & 0xff) >> 4));
 }
 
 guint32
index a3ec67a..d074df4 100644 (file)
@@ -684,6 +684,17 @@ typedef struct _AtomTRUN
   ATOM_ARRAY (TRUNSampleEntry) entries;
 } AtomTRUN;
 
+typedef struct _AtomSDTP
+{
+  AtomFull header;
+
+  /* not serialized */
+  guint32 sample_count;
+
+  /* array of fields */
+  ATOM_ARRAY (guint8) entries;
+} AtomSDTP;
+
 typedef struct _AtomTRAF
 {
   Atom header;
@@ -692,6 +703,8 @@ typedef struct _AtomTRAF
 
   /* list of AtomTRUN */
   GList *truns;
+  /* list of AtomSDTP */
+  GList *sdtps;
 } AtomTRAF;
 
 typedef struct _AtomMOOF
@@ -839,7 +852,8 @@ AtomTRAF * atom_traf_new               (AtomsContext * context, guint32 track_ID
 void       atom_traf_free              (AtomTRAF * traf);
 void       atom_traf_add_samples       (AtomTRAF * traf, guint32 delta,
                                         guint32 size, gboolean sync,
-                                        gboolean do_pts, gint64 pts_offset);
+                                        gboolean do_pts, gint64 pts_offset,
+                                        gboolean sdtp_sync);
 guint32    atom_traf_get_sample_num    (AtomTRAF * traf);
 void       atom_moof_add_traf          (AtomMOOF *moof, AtomTRAF *traf);
 
index b54ed05..2841599 100644 (file)
@@ -1875,7 +1875,8 @@ init:
   }
 
   /* add buffer and metadata */
-  atom_traf_add_samples (pad->traf, delta, size, sync, do_pts, pts_offset);
+  atom_traf_add_samples (pad->traf, delta, size, sync, do_pts, pts_offset,
+      pad->sync && sync);
   atom_array_append (&pad->fragment_buffers, buf, 256);
   pad->fragment_duration -= delta;