mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-25 16:48:11 +00:00
qtmux: add mvex/trex in header if fragmented
One "trex" is added per "trak". We don't support default values, but the "trex" box is mandatory.
This commit is contained in:
parent
9100168eae
commit
2618cb03af
3 changed files with 205 additions and 4 deletions
|
@ -1183,11 +1183,29 @@ atom_mvhd_clear (AtomMVHD * mvhd)
|
||||||
atom_full_clear (&mvhd->header);
|
atom_full_clear (&mvhd->header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_mehd_init (AtomMEHD * mehd)
|
||||||
|
{
|
||||||
|
guint8 flags[3] = { 0, 0, 0 };
|
||||||
|
|
||||||
|
atom_full_init (&mehd->header, FOURCC_mehd, 0, 0, 1, flags);
|
||||||
|
mehd->fragment_duration = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_mvex_init (AtomMVEX * mvex)
|
||||||
|
{
|
||||||
|
atom_header_set (&mvex->header, FOURCC_mvex, 0, 0);
|
||||||
|
atom_mehd_init (&mvex->mehd);
|
||||||
|
mvex->trexs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atom_moov_init (AtomMOOV * moov, AtomsContext * context)
|
atom_moov_init (AtomMOOV * moov, AtomsContext * context)
|
||||||
{
|
{
|
||||||
atom_header_set (&(moov->header), FOURCC_moov, 0, 0);
|
atom_header_set (&(moov->header), FOURCC_moov, 0, 0);
|
||||||
atom_mvhd_init (&(moov->mvhd));
|
atom_mvhd_init (&(moov->mvhd));
|
||||||
|
atom_mvex_init (&(moov->mvex));
|
||||||
moov->udta = NULL;
|
moov->udta = NULL;
|
||||||
moov->traks = NULL;
|
moov->traks = NULL;
|
||||||
moov->context = *context;
|
moov->context = *context;
|
||||||
|
@ -1202,6 +1220,28 @@ atom_moov_new (AtomsContext * context)
|
||||||
return moov;
|
return moov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_trex_free (AtomTREX * trex)
|
||||||
|
{
|
||||||
|
atom_full_clear (&trex->header);
|
||||||
|
g_free (trex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_mvex_clear (AtomMVEX * mvex)
|
||||||
|
{
|
||||||
|
GList *walker;
|
||||||
|
|
||||||
|
atom_clear (&mvex->header);
|
||||||
|
walker = mvex->trexs;
|
||||||
|
while (walker) {
|
||||||
|
atom_trex_free ((AtomTREX *) walker->data);
|
||||||
|
walker = g_list_next (walker);
|
||||||
|
}
|
||||||
|
g_list_free (mvex->trexs);
|
||||||
|
mvex->trexs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
atom_moov_free (AtomMOOV * moov)
|
atom_moov_free (AtomMOOV * moov)
|
||||||
{
|
{
|
||||||
|
@ -1223,6 +1263,8 @@ atom_moov_free (AtomMOOV * moov)
|
||||||
moov->udta = NULL;
|
moov->udta = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atom_mvex_clear (&moov->mvex);
|
||||||
|
|
||||||
g_free (moov);
|
g_free (moov);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2279,6 +2321,70 @@ atom_udta_copy_data (AtomUDTA * udta, guint8 ** buffer, guint64 * size,
|
||||||
return *offset - original_offset;
|
return *offset - original_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
atom_mehd_copy_data (AtomMEHD * mehd, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
|
||||||
|
if (!atom_full_copy_data (&mehd->header, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_copy_uint64 (mehd->fragment_duration, buffer, size, offset);
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
atom_trex_copy_data (AtomTREX * trex, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
|
||||||
|
if (!atom_full_copy_data (&trex->header, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_copy_uint32 (trex->track_ID, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (trex->default_sample_description_index, buffer, size,
|
||||||
|
offset);
|
||||||
|
prop_copy_uint32 (trex->default_sample_duration, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (trex->default_sample_size, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (trex->default_sample_flags, buffer, size, offset);
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
atom_mvex_copy_data (AtomMVEX * mvex, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
GList *walker;
|
||||||
|
|
||||||
|
if (!atom_copy_data (&mvex->header, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!atom_mehd_copy_data (&mvex->mehd, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
walker = g_list_first (mvex->trexs);
|
||||||
|
while (walker != NULL) {
|
||||||
|
if (!atom_trex_copy_data ((AtomTREX *) walker->data, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
walker = g_list_next (walker);
|
||||||
|
}
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
guint64
|
guint64
|
||||||
atom_moov_copy_data (AtomMOOV * atom, guint8 ** buffer, guint64 * size,
|
atom_moov_copy_data (AtomMOOV * atom, guint8 ** buffer, guint64 * size,
|
||||||
guint64 * offset)
|
guint64 * offset)
|
||||||
|
@ -2306,6 +2412,12 @@ atom_moov_copy_data (AtomMOOV * atom, guint8 ** buffer, guint64 * size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atom->fragmented) {
|
||||||
|
if (!atom_mvex_copy_data (&atom->mvex, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
atom_write_size (buffer, size, offset, original_offset);
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
return *offset - original_offset;
|
return *offset - original_offset;
|
||||||
}
|
}
|
||||||
|
@ -2488,6 +2600,32 @@ atom_moov_add_trak (AtomMOOV * moov, AtomTRAK * trak)
|
||||||
moov->traks = g_list_append (moov->traks, trak);
|
moov->traks = g_list_append (moov->traks, trak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_moov_add_trex (AtomMOOV * moov, AtomTREX * trex)
|
||||||
|
{
|
||||||
|
moov->mvex.trexs = g_list_append (moov->mvex.trexs, trex);
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomTREX *
|
||||||
|
atom_trex_new (AtomsContext * context, AtomTRAK * trak,
|
||||||
|
guint32 default_sample_description_index,
|
||||||
|
guint32 default_sample_duration, guint32 default_sample_size,
|
||||||
|
guint32 default_sample_flags)
|
||||||
|
{
|
||||||
|
guint8 flags[3] = { 0, 0, 0 };
|
||||||
|
AtomTREX *trex = g_new0 (AtomTREX, 1);
|
||||||
|
|
||||||
|
atom_full_init (&trex->header, FOURCC_trex, 0, 0, 0, flags);
|
||||||
|
|
||||||
|
trex->track_ID = trak->tkhd.track_ID;
|
||||||
|
trex->default_sample_description_index = default_sample_description_index;
|
||||||
|
trex->default_sample_duration = default_sample_duration;
|
||||||
|
trex->default_sample_size = default_sample_size;
|
||||||
|
trex->default_sample_flags = default_sample_flags;
|
||||||
|
|
||||||
|
return trex;
|
||||||
|
}
|
||||||
|
|
||||||
static guint64
|
static guint64
|
||||||
atom_trak_get_duration (AtomTRAK * trak)
|
atom_trak_get_duration (AtomTRAK * trak)
|
||||||
{
|
{
|
||||||
|
@ -2550,6 +2688,7 @@ atom_moov_update_duration (AtomMOOV * moov)
|
||||||
traks = g_list_next (traks);
|
traks = g_list_next (traks);
|
||||||
}
|
}
|
||||||
moov->mvhd.time_info.duration = duration;
|
moov->mvhd.time_info.duration = duration;
|
||||||
|
moov->mvex.mehd.fragment_duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2587,6 +2726,12 @@ atom_moov_set_64bits (AtomMOOV * moov, gboolean large_file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_moov_set_fragmented (AtomMOOV * moov, gboolean fragmented)
|
||||||
|
{
|
||||||
|
moov->fragmented = fragmented;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
|
atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
|
||||||
{
|
{
|
||||||
|
|
|
@ -595,6 +595,35 @@ typedef struct _AtomTRAK
|
||||||
gboolean is_h264;
|
gboolean is_h264;
|
||||||
} AtomTRAK;
|
} AtomTRAK;
|
||||||
|
|
||||||
|
typedef struct _AtomTREX
|
||||||
|
{
|
||||||
|
AtomFull header;
|
||||||
|
|
||||||
|
guint32 track_ID;
|
||||||
|
guint32 default_sample_description_index;
|
||||||
|
guint32 default_sample_duration;
|
||||||
|
guint32 default_sample_size;
|
||||||
|
guint32 default_sample_flags;
|
||||||
|
} AtomTREX;
|
||||||
|
|
||||||
|
typedef struct _AtomMEHD
|
||||||
|
{
|
||||||
|
AtomFull header;
|
||||||
|
|
||||||
|
guint64 fragment_duration;
|
||||||
|
} AtomMEHD;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _AtomMVEX
|
||||||
|
{
|
||||||
|
Atom header;
|
||||||
|
|
||||||
|
AtomMEHD mehd;
|
||||||
|
|
||||||
|
/* list of AtomTREX */
|
||||||
|
GList *trexs;
|
||||||
|
} AtomMVEX;
|
||||||
|
|
||||||
typedef struct _AtomMOOV
|
typedef struct _AtomMOOV
|
||||||
{
|
{
|
||||||
/* style */
|
/* style */
|
||||||
|
@ -603,10 +632,13 @@ typedef struct _AtomMOOV
|
||||||
Atom header;
|
Atom header;
|
||||||
|
|
||||||
AtomMVHD mvhd;
|
AtomMVHD mvhd;
|
||||||
|
AtomMVEX mvex;
|
||||||
|
|
||||||
/* list of AtomTRAK */
|
/* list of AtomTRAK */
|
||||||
GList *traks;
|
GList *traks;
|
||||||
AtomUDTA *udta;
|
AtomUDTA *udta;
|
||||||
|
|
||||||
|
gboolean fragmented;
|
||||||
} AtomMOOV;
|
} AtomMOOV;
|
||||||
|
|
||||||
typedef struct _AtomWAVE
|
typedef struct _AtomWAVE
|
||||||
|
@ -662,14 +694,20 @@ void atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples,
|
||||||
guint64 chunk_offset, gboolean sync,
|
guint64 chunk_offset, gboolean sync,
|
||||||
gboolean do_pts, gint64 pts_offset);
|
gboolean do_pts, gint64 pts_offset);
|
||||||
|
|
||||||
|
AtomTREX* atom_trex_new (AtomsContext *context, AtomTRAK *trak,
|
||||||
|
guint32 default_sample_description_index,
|
||||||
|
guint32 default_sample_duration, guint32 default_sample_size,
|
||||||
|
guint32 default_sample_flags);
|
||||||
AtomMOOV* atom_moov_new (AtomsContext *context);
|
AtomMOOV* atom_moov_new (AtomsContext *context);
|
||||||
void atom_moov_free (AtomMOOV *moov);
|
void atom_moov_free (AtomMOOV *moov);
|
||||||
guint64 atom_moov_copy_data (AtomMOOV *atom, guint8 **buffer, guint64 *size, guint64* offset);
|
guint64 atom_moov_copy_data (AtomMOOV *atom, guint8 **buffer, guint64 *size, guint64* offset);
|
||||||
void atom_moov_update_timescale (AtomMOOV *moov, guint32 timescale);
|
void atom_moov_update_timescale (AtomMOOV *moov, guint32 timescale);
|
||||||
void atom_moov_update_duration (AtomMOOV *moov);
|
void atom_moov_update_duration (AtomMOOV *moov);
|
||||||
void atom_moov_set_64bits (AtomMOOV *moov, gboolean large_file);
|
void atom_moov_set_64bits (AtomMOOV *moov, gboolean large_file);
|
||||||
|
void atom_moov_set_fragmented (AtomMOOV *moov, gboolean fragmented);
|
||||||
void atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset);
|
void atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset);
|
||||||
void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak);
|
void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak);
|
||||||
|
void atom_moov_add_trex (AtomMOOV *moov, AtomTREX *trex);
|
||||||
|
|
||||||
guint64 atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer,
|
guint64 atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer,
|
||||||
guint64 * size, guint64 * offset);
|
guint64 * size, guint64 * offset);
|
||||||
|
|
|
@ -271,6 +271,23 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad)
|
||||||
qtpad->trak = NULL;
|
qtpad->trak = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AtomTRAK *
|
||||||
|
gst_qt_mux_add_trak (GstQTMux * qtmux)
|
||||||
|
{
|
||||||
|
AtomTRAK *trak;
|
||||||
|
|
||||||
|
trak = atom_trak_new (qtmux->context);
|
||||||
|
atom_moov_add_trak (qtmux->moov, trak);
|
||||||
|
if (qtmux->fragmented) {
|
||||||
|
AtomTREX *trex;
|
||||||
|
|
||||||
|
trex = atom_trex_new (qtmux->context, trak, 1, 0, 0, 0);
|
||||||
|
atom_moov_add_trex (qtmux->moov, trex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trak;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Takes GstQTMux back to its initial state
|
* Takes GstQTMux back to its initial state
|
||||||
*/
|
*/
|
||||||
|
@ -331,8 +348,7 @@ gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc)
|
||||||
for (walk = qtmux->sinkpads; walk; walk = g_slist_next (walk)) {
|
for (walk = qtmux->sinkpads; walk; walk = g_slist_next (walk)) {
|
||||||
GstQTPad *qtpad = (GstQTPad *) walk->data;
|
GstQTPad *qtpad = (GstQTPad *) walk->data;
|
||||||
|
|
||||||
qtpad->trak = atom_trak_new (qtmux->context);
|
qtpad->trak = gst_qt_mux_add_trak (qtmux);
|
||||||
atom_moov_add_trak (qtmux->moov, qtpad->trak);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1460,6 +1476,8 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
timescale);
|
timescale);
|
||||||
atom_moov_update_timescale (qtmux->moov, timescale);
|
atom_moov_update_timescale (qtmux->moov, timescale);
|
||||||
atom_moov_set_64bits (qtmux->moov, large_file);
|
atom_moov_set_64bits (qtmux->moov, large_file);
|
||||||
|
atom_moov_set_fragmented (qtmux->moov, qtmux->fragmented);
|
||||||
|
|
||||||
atom_moov_update_duration (qtmux->moov);
|
atom_moov_update_duration (qtmux->moov);
|
||||||
|
|
||||||
/* check for late streams */
|
/* check for late streams */
|
||||||
|
@ -2696,8 +2714,8 @@ gst_qt_mux_request_new_pad (GstElement * element,
|
||||||
(GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
|
(GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
|
||||||
/* set up pad */
|
/* set up pad */
|
||||||
gst_qt_mux_pad_reset (collect_pad);
|
gst_qt_mux_pad_reset (collect_pad);
|
||||||
collect_pad->trak = atom_trak_new (qtmux->context);
|
|
||||||
atom_moov_add_trak (qtmux->moov, collect_pad->trak);
|
collect_pad->trak = gst_qt_mux_add_trak (qtmux);
|
||||||
qtmux->sinkpads = g_slist_append (qtmux->sinkpads, collect_pad);
|
qtmux->sinkpads = g_slist_append (qtmux->sinkpads, collect_pad);
|
||||||
|
|
||||||
/* set up pad functions */
|
/* set up pad functions */
|
||||||
|
|
Loading…
Reference in a new issue