gppmux: Add support for 3gr6
authorThiago Santos <thiagoss@embedded.ufcg.edu.br>
Fri, 16 Oct 2009 13:47:32 +0000 (10:47 -0300)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 12 Apr 2011 19:32:13 +0000 (20:32 +0100)
Keep track of the chunk durations to be able to add 3gr6
brand if it is a faststart file and the longest chunk is
smaller than a sec. Implemented according to 3gpp
TS 26.244 v6.4.0 (2005-09)

Fixes #584361

gst/quicktime/ftypcc.h
gst/quicktime/gstqtmux.c
gst/quicktime/gstqtmux.h
gst/quicktime/gstqtmuxmap.c
gst/quicktime/gstqtmuxmap.h

index 4855adf..66642b7 100644 (file)
@@ -56,6 +56,7 @@ G_BEGIN_DECLS
 #define FOURCC_3gp4     GST_MAKE_FOURCC('3','g','p','4')
 #define FOURCC_3gp6     GST_MAKE_FOURCC('3','g','p','6')
 #define FOURCC_3gg6     GST_MAKE_FOURCC('3','g','g','6')
+#define FOURCC_3gr6     GST_MAKE_FOURCC('3','g','r','6')
 #define FOURCC_3gg7     GST_MAKE_FOURCC('3','g','g','7')
 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
 #define FOURCC_qt__     GST_MAKE_FOURCC('q','t',' ',' ')
index 2ed0cea..b52b871 100644 (file)
@@ -268,6 +268,7 @@ gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc)
   qtmux->header_size = 0;
   qtmux->mdat_size = 0;
   qtmux->mdat_pos = 0;
+  qtmux->longest_chunk = GST_CLOCK_TIME_NONE;
 
   if (qtmux->ftyp) {
     atom_ftyp_free (qtmux->ftyp);
@@ -1035,7 +1036,8 @@ gst_qt_mux_prepare_and_send_ftyp (GstQTMux * qtmux)
   if (qtmux->ftyp)
     atom_ftyp_free (qtmux->ftyp);
   gst_qt_mux_map_format_to_header (qtmux_klass->format, &prefix, &major,
-      &version, &comp, qtmux->moov);
+      &version, &comp, qtmux->moov, qtmux->longest_chunk,
+      qtmux->fast_start_file != NULL);
   qtmux->ftyp = atom_ftyp_new (qtmux->context, major, version, comp);
   if (comp)
     g_list_free (comp);
@@ -1357,6 +1359,17 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
         GST_PAD_NAME (pad->collect.pad), pts_offset);
   }
 
+  /*
+   * Each buffer starts a new chunk, so we can assume the buffer
+   * duration is the chunk duration
+   */
+  if (GST_CLOCK_TIME_IS_VALID (duration) && (duration > qtmux->longest_chunk ||
+          !GST_CLOCK_TIME_IS_VALID (qtmux->longest_chunk))) {
+    GST_DEBUG_OBJECT (qtmux, "New longest chunk found: %" GST_TIME_FORMAT
+        ", pad %s", GST_TIME_ARGS (duration), GST_PAD_NAME (pad->collect.pad));
+    qtmux->longest_chunk = duration;
+  }
+
   /* now we go and register this buffer/sample all over */
   /* note that a new chunk is started each time (not fancy but works) */
   atom_trak_add_samples (pad->trak, nsamples, scaled_duration, sample_size,
index 567773a..d12c23c 100644 (file)
@@ -112,6 +112,9 @@ struct _GstQTMux
   /* position of mdat atom (for later updating) */
   guint64 mdat_pos;
 
+  /* keep track of the largest chunk to fine-tune brands */
+  GstClockTime longest_chunk;
+
   /* atom helper objects */
   AtomsContext *context;
   AtomFTYP *ftyp;
index 808856a..6587c45 100644 (file)
@@ -243,7 +243,8 @@ gst_qt_mux_map_check_tracks (AtomMOOV * moov, gint * _video, gint * _audio,
  *   (but that might need ftyp rewriting at the end) */
 void
 gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
-    guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov)
+    guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov,
+    GstClockTime longest_chunk, gboolean faststart)
 {
   static guint32 qt_brands[] = { 0 };
   static guint32 mp4_brands[] = { FOURCC_mp41, FOURCC_isom, FOURCC_iso2, 0 };
@@ -287,6 +288,14 @@ gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
         version = 0x100;
       }
       comp = gpp_brands;
+
+      /*
+       * We assume that we have chunks in dts order
+       */
+      if (faststart && longest_chunk <= GST_SECOND) {
+        /* add progressive download profile */
+        result = g_list_append (result, GUINT_TO_POINTER (FOURCC_3gr6));
+      }
       break;
     }
     case GST_QT_MUX_FORMAT_MJ2:
index 342d381..67c6139 100644 (file)
@@ -73,7 +73,9 @@ extern GstQTMuxFormatProp gst_qt_mux_format_list[];
 
 void            gst_qt_mux_map_format_to_header      (GstQTMuxFormat format, GstBuffer ** _prefix,
                                                       guint32 * _major, guint32 * verson,
-                                                      GList ** _compatible, AtomMOOV * moov);
+                                                      GList ** _compatible, AtomMOOV * moov,
+                                                      GstClockTime longest_chunk,
+                                                      gboolean faststart);
 
 AtomsTreeFlavor gst_qt_mux_map_format_to_flavor      (GstQTMuxFormat format);