diff --git a/gst/qtmux/ftypcc.h b/gst/qtmux/ftypcc.h index 4855adf7ee..66642b7831 100644 --- a/gst/qtmux/ftypcc.h +++ b/gst/qtmux/ftypcc.h @@ -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',' ',' ') diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 2ed0cea98d..b52b871701 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -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, diff --git a/gst/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h index 567773a03c..d12c23cdb3 100644 --- a/gst/qtmux/gstqtmux.h +++ b/gst/qtmux/gstqtmux.h @@ -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; diff --git a/gst/qtmux/gstqtmuxmap.c b/gst/qtmux/gstqtmuxmap.c index 808856a222..6587c45ab6 100644 --- a/gst/qtmux/gstqtmuxmap.c +++ b/gst/qtmux/gstqtmuxmap.c @@ -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: diff --git a/gst/qtmux/gstqtmuxmap.h b/gst/qtmux/gstqtmuxmap.h index 342d38117b..67c6139022 100644 --- a/gst/qtmux/gstqtmuxmap.h +++ b/gst/qtmux/gstqtmuxmap.h @@ -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);