qtmux: Write tapt atom for MOV files if PAR not 1/1
authorSebastian Dröge <sebastian@centricular.com>
Tue, 10 Jan 2017 16:19:55 +0000 (18:19 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Thu, 12 Jan 2017 17:09:22 +0000 (19:09 +0200)
Needed for QuickTime 7 to properly play files.

Also write the clap atom for MOV files always, not only when ProRes is
used as a video codec. It's mandatory for MOV.

https://bugzilla.gnome.org/show_bug.cgi?id=777100

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

index 3bc6be9..ceadb59 100644 (file)
@@ -2813,6 +2813,11 @@ atom_trak_copy_data (AtomTRAK * trak, guint8 ** buffer, guint64 * size,
   if (!atom_tkhd_copy_data (&trak->tkhd, buffer, size, offset)) {
     return 0;
   }
+  if (trak->tapt) {
+    if (!trak->tapt->copy_data_func (trak->tapt->atom, buffer, size, offset)) {
+      return 0;
+    }
+  }
   if (trak->edts) {
     if (!atom_edts_copy_data (trak->edts, buffer, size, offset)) {
       return 0;
@@ -4097,6 +4102,39 @@ build_clap_extension (gint width_n, gint width_d, gint height_n, gint height_d,
       atom_data_free);
 }
 
+AtomInfo *
+build_tapt_extension (gint clef_width, gint clef_height, gint prof_width,
+    gint prof_height, gint enof_width, gint enof_height)
+{
+  AtomData *atom_data = atom_data_new (FOURCC_tapt);
+  guint8 *data;
+
+  atom_data_alloc_mem (atom_data, 60);
+  data = atom_data->data;
+
+  GST_WRITE_UINT32_BE (data, 20);
+  GST_WRITE_UINT32_LE (data + 4, FOURCC_clef);
+  GST_WRITE_UINT32_BE (data + 8, 0);
+  GST_WRITE_UINT32_BE (data + 12, clef_width);
+  GST_WRITE_UINT32_BE (data + 16, clef_height);
+
+  GST_WRITE_UINT32_BE (data + 20, 20);
+  GST_WRITE_UINT32_LE (data + 24, FOURCC_prof);
+  GST_WRITE_UINT32_BE (data + 28, 0);
+  GST_WRITE_UINT32_BE (data + 32, prof_width);
+  GST_WRITE_UINT32_BE (data + 36, prof_height);
+
+  GST_WRITE_UINT32_BE (data + 40, 20);
+  GST_WRITE_UINT32_LE (data + 44, FOURCC_enof);
+  GST_WRITE_UINT32_BE (data + 48, 0);
+  GST_WRITE_UINT32_BE (data + 52, enof_width);
+  GST_WRITE_UINT32_BE (data + 56, enof_height);
+
+
+  return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+      atom_data_free);
+}
+
 SampleTableEntryMP4V *
 atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
     VisualSampleEntry * entry, guint32 scale, GList * ext_atoms_list)
index 8f2ea1e..d38980b 100644 (file)
@@ -113,6 +113,8 @@ void          atoms_context_free (AtomsContext *context);
 
 /* atom defs and functions */
 
+typedef struct _AtomInfo AtomInfo;
+
 /*
  * Used for storing time related values for some atoms.
  */
@@ -701,6 +703,7 @@ typedef struct _AtomTRAK
   Atom header;
 
   AtomTKHD tkhd;
+  AtomInfo *tapt;
   AtomEDTS *edts;
   AtomMDIA mdia;
   AtomUDTA udta;
@@ -893,13 +896,12 @@ typedef guint64 (*AtomFreeFunc) (Atom *atom);
  * All we need are the two functions (copying it to an array
  * for serialization and the memory releasing function).
  */
-typedef struct _AtomInfo
+struct _AtomInfo
 {
   Atom *atom;
   AtomCopyDataFunc copy_data_func;
   AtomFreeFunc free_func;
-} AtomInfo;
-
+};
 
 guint64    atom_copy_data              (Atom *atom, guint8 **buffer,
                                         guint64 *size, guint64* offset);
@@ -1056,6 +1058,9 @@ AtomInfo *   build_jp2x_extension        (const GstBuffer * prefix);
 AtomInfo *   build_fiel_extension        (GstVideoInterlaceMode mode, GstVideoFieldOrder order);
 AtomInfo *   build_colr_extension        (const GstVideoColorimetry *colorimetry, gboolean is_mp4);
 AtomInfo *   build_clap_extension        (gint width_n, gint width_d, gint height_n, gint height_d, gint h_off_n, gint h_off_d, gint v_off_n, gint v_off_d);
+AtomInfo *   build_tapt_extension        (gint clef_width, gint clef_height, gint prof_width, gint prof_height, gint enof_width, gint enof_height);
+
+
 AtomInfo *   build_ac3_extension         (guint8 fscod, guint8 bsid,
                                           guint8 bsmod, guint8 acmod,
                                           guint8 lfe_on, guint8 bitrate_code);
index 2b86e5c..8643ce9 100644 (file)
@@ -179,6 +179,10 @@ G_BEGIN_DECLS
 #define FOURCC_pasp     GST_MAKE_FOURCC('p','a','s','p')
 #define FOURCC_colr     GST_MAKE_FOURCC('c','o','l','r')
 #define FOURCC_clap     GST_MAKE_FOURCC('c','l','a','p')
+#define FOURCC_tapt     GST_MAKE_FOURCC('t','a','p','t')
+#define FOURCC_clef     GST_MAKE_FOURCC('c','l','e','f')
+#define FOURCC_prof     GST_MAKE_FOURCC('p','r','o','f')
+#define FOURCC_enof     GST_MAKE_FOURCC('e','n','o','f')
 #define FOURCC_fiel     GST_MAKE_FOURCC('f','i','e','l')
 #define FOURCC_pcst     GST_MAKE_FOURCC('p','c','s','t')
 #define FOURCC_pgap     GST_MAKE_FOURCC('p','g','a','p')
index b8fdf17..f47e424 100644 (file)
@@ -4415,6 +4415,43 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
       ext_atom_list = g_list_append (ext_atom_list, ext_atom);
   }
 
+
+  if (qtmux_klass->format == GST_QT_MUX_FORMAT_QT) {
+    /* The 'clap' extension is also defined for MP4 but inventing values in
+     * general seems a bit tricky for this one. We only write it for MOV
+     * then, where it is a requirement.
+     * The same goes for the 'tapt' extension, just that it is not defined for
+     * MP4 and only for MOV
+     *
+     * NTSC and PAL have special values, otherwise just take width and height
+     */
+    if (width == 720 && (height == 480 || height == 486)) {
+      ext_atom = build_clap_extension (704, 1, height, 1, 0, 1, 0, 1);
+      if (ext_atom)
+        ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+
+    } else if (width == 720 && height == 576) {
+      ext_atom = build_clap_extension (768 * 54, 59, 576, 1, 0, 1, 0, 1);
+      if (ext_atom)
+        ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+    } else {
+      ext_atom = build_clap_extension (width, 1, height, 1, 0, 1, 0, 1);
+      if (ext_atom)
+        ext_atom_list = g_list_append (ext_atom_list, ext_atom);
+    }
+
+    if (par_num != par_den) {
+      gint clef_width =
+          gst_util_uint64_scale (width, par_num * G_GUINT64_CONSTANT (65536),
+          par_den);
+
+      ext_atom =
+          build_tapt_extension (clef_width, height << 16, clef_width,
+          height << 16, width << 16, height << 16);
+      qtpad->trak->tapt = ext_atom;
+    }
+  }
+
   /* ok, set the pad info accordingly */
   qtpad->fourcc = entry.fourcc;
   qtpad->sync = sync;
@@ -4457,22 +4494,6 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
       strcpy ((gchar *) mp4v->compressor + 1, compressor);
       mp4v->compressor[0] = strlen (compressor);
     }
-
-    /* The 'clap' extension is also defined for MP4 but inventing values in
-     * general seems a bit tricky for this one. We only write it for ProRes
-     * then, where it is a requirement.
-     *
-     * NTSC and PAL have special values, otherwise just take width and height
-     */
-    if (width == 720 && (height == 480 || height == 486))
-      ext_atom = build_clap_extension (704, 1, height, 1, 0, 1, 0, 1);
-    else if (width == 720 && height == 576)
-      ext_atom = build_clap_extension (768 * 54, 59, 576, 1, 0, 1, 0, 1);
-    else
-      ext_atom = build_clap_extension (width, 1, height, 1, 0, 1, 0, 1);
-
-    if (ext_atom)
-      mp4v->extension_atoms = g_list_append (mp4v->extension_atoms, ext_atom);
   }
 
   gst_object_unref (qtmux);
index 8ce37ce..15a6184 100644 (file)
@@ -85,6 +85,7 @@ static const QtNodeType qt_node_types[] = {
   {FOURCC_jp2h, "jp2h", QT_FLAG_CONTAINER,},
   {FOURCC_colr, "colr", 0,},
   {FOURCC_clap, "clap", 0,},
+  {FOURCC_tapt, "tapt", 0,},
   {FOURCC_ihdr, "ihdr", 0,},
   {FOURCC_fiel, "fiel", 0,},
   {FOURCC_jp2x, "jp2x", 0,},