qtmux: Write tfdt atom into fragmented files.

The DASH spec requires that tfdt atoms be present, so
write one out. ISO/IEC 23009-1:2014 6.3.4.2

https://bugzilla.gnome.org/show_bug.cgi?id=708221
diff --git a/gst/isomp4/atoms.c b/gst/isomp4/atoms.c
index d110333..3bc6be9 100644
--- a/gst/isomp4/atoms.c
+++ b/gst/isomp4/atoms.c
@@ -4302,6 +4302,26 @@
 }
 
 static guint64
+atom_tfdt_copy_data (AtomTFDT * tfdt, guint8 ** buffer, guint64 * size,
+    guint64 * offset)
+{
+  guint64 original_offset = *offset;
+
+  if (!atom_full_copy_data (&tfdt->header, buffer, size, offset)) {
+    return 0;
+  }
+
+  /* 32-bit time if version == 0 else 64-bit: */
+  if (tfdt->header.version == 0)
+    prop_copy_uint32 (tfdt->base_media_decode_time, buffer, size, offset);
+  else
+    prop_copy_uint64 (tfdt->base_media_decode_time, buffer, size, offset);
+
+  atom_write_size (buffer, size, offset, original_offset);
+  return *offset - original_offset;
+}
+
+static guint64
 atom_trun_copy_data (AtomTRUN * trun, guint8 ** buffer, guint64 * size,
     guint64 * offset, guint32 * data_offset)
 {
@@ -4382,6 +4402,9 @@
   if (!atom_tfhd_copy_data (&traf->tfhd, buffer, size, offset)) {
     return 0;
   }
+  if (!atom_tfdt_copy_data (&traf->tfdt, buffer, size, offset)) {
+    return 0;
+  }
 
   walker = g_list_first (traf->truns);
   while (walker != NULL) {
@@ -4455,6 +4478,15 @@
 }
 
 static void
+atom_tfdt_init (AtomTFDT * tfdt)
+{
+  guint8 flags[3] = { 0, 0, 0 };
+  atom_full_init (&tfdt->header, FOURCC_tfdt, 0, 0, 0, flags);
+
+  tfdt->base_media_decode_time = 0;
+}
+
+static void
 atom_trun_init (AtomTRUN * trun)
 {
   guint8 flags[3] = { 0, 0, 0 };
@@ -4528,6 +4560,7 @@
 atom_traf_init (AtomTRAF * traf, AtomsContext * context, guint32 track_ID)
 {
   atom_header_set (&traf->header, FOURCC_traf, 0, 0);
+  atom_tfdt_init (&traf->tfdt);
   atom_tfhd_init (&traf->tfhd, track_ID);
   traf->truns = NULL;
 
@@ -4544,6 +4577,15 @@
   return traf;
 }
 
+void
+atom_traf_set_base_decode_time (AtomTRAF * traf, guint64 base_decode_time)
+{
+  traf->tfdt.base_media_decode_time = base_decode_time;
+  /* If we need to write a 64-bit tfdt, set the atom version */
+  if (base_decode_time > G_MAXUINT32)
+    traf->tfdt.header.version = 1;
+}
+
 static void
 atom_traf_add_trun (AtomTRAF * traf, AtomTRUN * trun)
 {
diff --git a/gst/isomp4/atoms.h b/gst/isomp4/atoms.h
index b563116..8f2ea1e 100644
--- a/gst/isomp4/atoms.h
+++ b/gst/isomp4/atoms.h
@@ -761,6 +761,13 @@
   guint32 default_sample_flags;
 } AtomTFHD;
 
+typedef struct _AtomTFDT
+{
+  AtomFull header;
+
+  guint64 base_media_decode_time;
+} AtomTFDT;
+
 typedef struct _TRUNSampleEntry
 {
   guint32 sample_duration;
@@ -798,6 +805,8 @@
 
   AtomTFHD tfhd;
 
+  AtomTFDT tfdt;
+
   /* list of AtomTRUN */
   GList *truns;
   /* list of AtomSDTP */
@@ -948,6 +957,7 @@
 guint64    atom_moof_copy_data         (AtomMOOF *moof, guint8 **buffer, guint64 *size, guint64* offset);
 AtomTRAF * atom_traf_new               (AtomsContext * context, guint32 track_ID);
 void       atom_traf_free              (AtomTRAF * traf);
+void       atom_traf_set_base_decode_time (AtomTRAF * traf, guint64 base_decode_time);
 void       atom_traf_add_samples       (AtomTRAF * traf, guint32 delta,
                                         guint32 size, gboolean sync, gint64 pts_offset,
                                         gboolean sdtp_sync);
diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c
index 810c1dd..b8fdf17 100644
--- a/gst/isomp4/gstqtmux.c
+++ b/gst/isomp4/gstqtmux.c
@@ -2848,6 +2848,7 @@
       pad->tfra = atom_tfra_new (qtmux->context, atom_trak_get_id (pad->trak));
       atom_mfra_add_tfra (qtmux->mfra, pad->tfra);
     }
+    atom_traf_set_base_decode_time (pad->traf, dts);
   }
 
   /* add buffer and metadata */