mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-20 06:08:14 +00:00
qtmux: add mfra to fragmented file
Based on patch by Marc-André Lureau <mlureau@flumotion.com>
This commit is contained in:
parent
68d5ab1a1d
commit
f03dc57faf
4 changed files with 320 additions and 9 deletions
|
@ -3643,12 +3643,238 @@ atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size,
|
||||||
pts_offset);
|
pts_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint32
|
||||||
|
atom_traf_get_sample_num (AtomTRAF * traf)
|
||||||
|
{
|
||||||
|
AtomTRUN *trun;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!traf->truns))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
trun = traf->truns->data;
|
||||||
|
return atom_array_get_len (&trun->entries);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
atom_moof_add_traf (AtomMOOF * moof, AtomTRAF * traf)
|
atom_moof_add_traf (AtomMOOF * moof, AtomTRAF * traf)
|
||||||
{
|
{
|
||||||
moof->trafs = g_list_append (moof->trafs, traf);
|
moof->trafs = g_list_append (moof->trafs, traf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_tfra_free (AtomTFRA * tfra)
|
||||||
|
{
|
||||||
|
atom_full_clear (&tfra->header);
|
||||||
|
atom_array_clear (&tfra->entries);
|
||||||
|
g_free (tfra);
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomMFRA *
|
||||||
|
atom_mfra_new (AtomsContext * context)
|
||||||
|
{
|
||||||
|
AtomMFRA *mfra = g_new0 (AtomMFRA, 1);
|
||||||
|
|
||||||
|
atom_header_set (&mfra->header, FOURCC_mfra, 0, 0);
|
||||||
|
return mfra;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_mfra_add_tfra (AtomMFRA * mfra, AtomTFRA * tfra)
|
||||||
|
{
|
||||||
|
mfra->tfras = g_list_append (mfra->tfras, tfra);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_mfra_free (AtomMFRA * mfra)
|
||||||
|
{
|
||||||
|
GList *walker;
|
||||||
|
|
||||||
|
walker = mfra->tfras;
|
||||||
|
while (walker) {
|
||||||
|
atom_tfra_free ((AtomTFRA *) walker->data);
|
||||||
|
walker = g_list_next (walker);
|
||||||
|
}
|
||||||
|
g_list_free (mfra->tfras);
|
||||||
|
mfra->tfras = NULL;
|
||||||
|
|
||||||
|
atom_clear (&mfra->header);
|
||||||
|
g_free (mfra);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_tfra_init (AtomTFRA * tfra, guint32 track_ID)
|
||||||
|
{
|
||||||
|
guint8 flags[3] = { 0, 0, 0 };
|
||||||
|
|
||||||
|
atom_full_init (&tfra->header, FOURCC_tfra, 0, 0, 0, flags);
|
||||||
|
tfra->track_ID = track_ID;
|
||||||
|
atom_array_init (&tfra->entries, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomTFRA *
|
||||||
|
atom_tfra_new (AtomsContext * context, guint32 track_ID)
|
||||||
|
{
|
||||||
|
AtomTFRA *tfra = g_new0 (AtomTFRA, 1);
|
||||||
|
|
||||||
|
atom_tfra_init (tfra, track_ID);
|
||||||
|
return tfra;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gint
|
||||||
|
need_bytes (guint32 num)
|
||||||
|
{
|
||||||
|
gint n = 0;
|
||||||
|
|
||||||
|
while (num >>= 8)
|
||||||
|
n++;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_tfra_add_entry (AtomTFRA * tfra, guint64 dts, guint32 sample_num)
|
||||||
|
{
|
||||||
|
TFRAEntry entry;
|
||||||
|
|
||||||
|
entry.time = dts;
|
||||||
|
/* fill in later */
|
||||||
|
entry.moof_offset = 0;
|
||||||
|
/* always write a single trun in a single traf */
|
||||||
|
entry.traf_number = 1;
|
||||||
|
entry.trun_number = 1;
|
||||||
|
entry.sample_number = sample_num;
|
||||||
|
|
||||||
|
/* auto-use 64 bits if needed */
|
||||||
|
if (dts > G_MAXUINT32)
|
||||||
|
tfra->header.version = 1;
|
||||||
|
|
||||||
|
/* 1 byte will always do for traf and trun number,
|
||||||
|
* check how much sample_num needs */
|
||||||
|
tfra->lengths = (tfra->lengths & 0xfc) ||
|
||||||
|
MAX (tfra->lengths, need_bytes (sample_num));
|
||||||
|
|
||||||
|
atom_array_append (&tfra->entries, entry, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
/* auto-use 64 bits if needed */
|
||||||
|
if (offset > G_MAXUINT32)
|
||||||
|
tfra->header.version = 1;
|
||||||
|
|
||||||
|
for (i = atom_array_get_len (&tfra->entries) - 1; i >= 0; i--) {
|
||||||
|
TFRAEntry *entry = &atom_array_index (&tfra->entries, i);
|
||||||
|
|
||||||
|
if (entry->moof_offset)
|
||||||
|
break;
|
||||||
|
entry->moof_offset = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
atom_tfra_copy_data (AtomTFRA * tfra, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
guint32 i;
|
||||||
|
TFRAEntry *entry;
|
||||||
|
guint32 data;
|
||||||
|
guint bytes;
|
||||||
|
guint version;
|
||||||
|
|
||||||
|
if (!atom_full_copy_data (&tfra->header, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_copy_uint32 (tfra->track_ID, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (tfra->lengths, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (atom_array_get_len (&tfra->entries), buffer, size, offset);
|
||||||
|
|
||||||
|
version = tfra->header.version;
|
||||||
|
for (i = 0; i < atom_array_get_len (&tfra->entries); ++i) {
|
||||||
|
entry = &atom_array_index (&tfra->entries, i);
|
||||||
|
if (version) {
|
||||||
|
prop_copy_uint64 (entry->time, buffer, size, offset);
|
||||||
|
prop_copy_uint64 (entry->moof_offset, buffer, size, offset);
|
||||||
|
} else {
|
||||||
|
prop_copy_uint32 (entry->time, buffer, size, offset);
|
||||||
|
prop_copy_uint32 (entry->moof_offset, buffer, size, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = (tfra->lengths & (0x3 << 4)) + 1;
|
||||||
|
data = GUINT32_TO_BE (entry->traf_number);
|
||||||
|
prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
|
||||||
|
buffer, size, offset);
|
||||||
|
|
||||||
|
bytes = (tfra->lengths & (0x3 << 2)) + 1;
|
||||||
|
data = GUINT32_TO_BE (entry->trun_number);
|
||||||
|
prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
|
||||||
|
buffer, size, offset);
|
||||||
|
|
||||||
|
bytes = (tfra->lengths & (0x3)) + 1;
|
||||||
|
data = GUINT32_TO_BE (entry->sample_number);
|
||||||
|
prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
|
||||||
|
buffer, size, offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint64
|
||||||
|
atom_mfro_copy_data (guint32 s, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
guint8 flags[3] = { 0, 0, 0 };
|
||||||
|
AtomFull mfro;
|
||||||
|
|
||||||
|
atom_full_init (&mfro, FOURCC_mfro, 0, 0, 0, flags);
|
||||||
|
|
||||||
|
if (!atom_full_copy_data (&mfro, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop_copy_uint32 (s, buffer, size, offset);
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
guint64
|
||||||
|
atom_mfra_copy_data (AtomMFRA * mfra, guint8 ** buffer, guint64 * size,
|
||||||
|
guint64 * offset)
|
||||||
|
{
|
||||||
|
guint64 original_offset = *offset;
|
||||||
|
GList *walker;
|
||||||
|
|
||||||
|
if (!atom_copy_data (&mfra->header, buffer, size, offset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
walker = g_list_first (mfra->tfras);
|
||||||
|
while (walker != NULL) {
|
||||||
|
if (!atom_tfra_copy_data ((AtomTFRA *) walker->data, buffer, size, offset)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
walker = g_list_next (walker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16 is the size of the mfro atom */
|
||||||
|
if (!atom_mfro_copy_data (*offset - original_offset + 16, buffer,
|
||||||
|
size, offset))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
atom_write_size (buffer, size, offset, original_offset);
|
||||||
|
return *offset - original_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* some sample description construction helpers */
|
/* some sample description construction helpers */
|
||||||
|
|
||||||
AtomInfo *
|
AtomInfo *
|
||||||
|
|
|
@ -729,6 +729,33 @@ typedef struct _AtomWAVE
|
||||||
GList *extension_atoms;
|
GList *extension_atoms;
|
||||||
} AtomWAVE;
|
} AtomWAVE;
|
||||||
|
|
||||||
|
typedef struct _TFRAEntry
|
||||||
|
{
|
||||||
|
guint64 time;
|
||||||
|
guint64 moof_offset;
|
||||||
|
guint32 traf_number;
|
||||||
|
guint32 trun_number;
|
||||||
|
guint32 sample_number;
|
||||||
|
} TFRAEntry;
|
||||||
|
|
||||||
|
typedef struct _AtomTFRA
|
||||||
|
{
|
||||||
|
AtomFull header;
|
||||||
|
|
||||||
|
guint32 track_ID;
|
||||||
|
guint32 lengths;
|
||||||
|
/* array of entries */
|
||||||
|
ATOM_ARRAY (TFRAEntry) entries;
|
||||||
|
} AtomTFRA;
|
||||||
|
|
||||||
|
typedef struct _AtomMFRA
|
||||||
|
{
|
||||||
|
Atom header;
|
||||||
|
|
||||||
|
/* list of tfra */
|
||||||
|
GList *tfras;
|
||||||
|
} AtomMFRA;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to serialize an atom
|
* Function to serialize an atom
|
||||||
*/
|
*/
|
||||||
|
@ -812,8 +839,18 @@ void atom_traf_free (AtomTRAF * traf);
|
||||||
void atom_traf_add_samples (AtomTRAF * traf, guint32 delta,
|
void atom_traf_add_samples (AtomTRAF * traf, guint32 delta,
|
||||||
guint32 size, gboolean sync,
|
guint32 size, gboolean sync,
|
||||||
gboolean do_pts, gint64 pts_offset);
|
gboolean do_pts, gint64 pts_offset);
|
||||||
|
guint32 atom_traf_get_sample_num (AtomTRAF * traf);
|
||||||
void atom_moof_add_traf (AtomMOOF *moof, AtomTRAF *traf);
|
void atom_moof_add_traf (AtomMOOF *moof, AtomTRAF *traf);
|
||||||
|
|
||||||
|
AtomMFRA* atom_mfra_new (AtomsContext *context);
|
||||||
|
void atom_mfra_free (AtomMFRA *mfra);
|
||||||
|
AtomTFRA* atom_tfra_new (AtomsContext *context, guint32 track_ID);
|
||||||
|
void atom_tfra_add_entry (AtomTFRA *tfra, guint64 dts, guint32 sample_num);
|
||||||
|
void atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset);
|
||||||
|
void atom_mfra_add_tfra (AtomMFRA *mfra, AtomTFRA *tfra);
|
||||||
|
guint64 atom_mfra_copy_data (AtomMFRA *mfra, guint8 **buffer, guint64 *size, guint64* offset);
|
||||||
|
|
||||||
|
|
||||||
/* media sample description related helpers */
|
/* media sample description related helpers */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -283,6 +283,9 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad)
|
||||||
qtpad->traf = NULL;
|
qtpad->traf = NULL;
|
||||||
}
|
}
|
||||||
atom_array_clear (&qtpad->fragment_buffers);
|
atom_array_clear (&qtpad->fragment_buffers);
|
||||||
|
|
||||||
|
/* reference owned elsewhere */
|
||||||
|
qtpad->tfra = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -310,6 +313,10 @@ gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc)
|
||||||
atom_moov_free (qtmux->moov);
|
atom_moov_free (qtmux->moov);
|
||||||
qtmux->moov = NULL;
|
qtmux->moov = NULL;
|
||||||
}
|
}
|
||||||
|
if (qtmux->mfra) {
|
||||||
|
atom_mfra_free (qtmux->mfra);
|
||||||
|
qtmux->mfra = NULL;
|
||||||
|
}
|
||||||
if (qtmux->fast_start_file) {
|
if (qtmux->fast_start_file) {
|
||||||
fclose (qtmux->fast_start_file);
|
fclose (qtmux->fast_start_file);
|
||||||
g_remove (qtmux->fast_start_file_path);
|
g_remove (qtmux->fast_start_file_path);
|
||||||
|
@ -1532,13 +1539,16 @@ gst_qt_mux_start_file (GstQTMux * qtmux)
|
||||||
/* prepare moov and/or tags */
|
/* prepare moov and/or tags */
|
||||||
gst_qt_mux_configure_moov (qtmux, NULL);
|
gst_qt_mux_configure_moov (qtmux, NULL);
|
||||||
gst_qt_mux_setup_metadata (qtmux);
|
gst_qt_mux_setup_metadata (qtmux);
|
||||||
ret = gst_qt_mux_send_moov (qtmux, NULL, FALSE);
|
ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
/* extra atoms */
|
/* extra atoms */
|
||||||
ret = gst_qt_mux_send_extra_atoms (qtmux, TRUE, NULL, FALSE);
|
ret =
|
||||||
|
gst_qt_mux_send_extra_atoms (qtmux, TRUE, &qtmux->header_size, FALSE);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
/* prepare index */
|
||||||
|
qtmux->mfra = atom_mfra_new (qtmux->context);
|
||||||
} else {
|
} else {
|
||||||
/* extended to ensure some spare space */
|
/* extended to ensure some spare space */
|
||||||
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
|
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
|
||||||
|
@ -1595,6 +1605,20 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
if (qtmux->fragment_sequence) {
|
if (qtmux->fragment_sequence) {
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
|
||||||
|
if (qtmux->mfra) {
|
||||||
|
guint8 *data = NULL;
|
||||||
|
GstBuffer *buf;
|
||||||
|
|
||||||
|
size = offset = 0;
|
||||||
|
GST_DEBUG_OBJECT (qtmux, "adding mfra");
|
||||||
|
if (!atom_mfra_copy_data (qtmux->mfra, &data, &size, &offset))
|
||||||
|
goto serialize_error;
|
||||||
|
buf = _gst_buffer_new_take_data (data, offset);
|
||||||
|
ret = gst_qt_mux_send_buffer (qtmux, buf, NULL, FALSE);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
timescale = qtmux->timescale;
|
timescale = qtmux->timescale;
|
||||||
/* only mvex duration is updated,
|
/* only mvex duration is updated,
|
||||||
* mvhd should be consistent with empty moov
|
* mvhd should be consistent with empty moov
|
||||||
|
@ -1732,8 +1756,9 @@ ftyp_error:
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_qt_mux_pad_fragment_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
|
gst_qt_mux_pad_fragment_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
|
||||||
GstBuffer * buf, gboolean force, guint32 nsamples, guint32 delta,
|
GstBuffer * buf, gboolean force, guint32 nsamples, gint64 dts,
|
||||||
guint32 size, gboolean sync, gboolean do_pts, gint64 pts_offset)
|
guint32 delta, guint32 size, gboolean sync, gboolean do_pts,
|
||||||
|
gint64 pts_offset)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
|
@ -1752,6 +1777,10 @@ flush:
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
guint i, total_size;
|
guint i, total_size;
|
||||||
|
|
||||||
|
/* now we know where moof ends up, update offset in tfra */
|
||||||
|
if (pad->tfra)
|
||||||
|
atom_tfra_update_offset (pad->tfra, qtmux->header_size);
|
||||||
|
|
||||||
moof = atom_moof_new (qtmux->context, qtmux->fragment_sequence);
|
moof = atom_moof_new (qtmux->context, qtmux->fragment_sequence);
|
||||||
/* takes ownership */
|
/* takes ownership */
|
||||||
atom_moof_add_traf (moof, pad->traf);
|
atom_moof_add_traf (moof, pad->traf);
|
||||||
|
@ -1759,7 +1788,7 @@ flush:
|
||||||
atom_moof_copy_data (moof, &data, &size, &offset);
|
atom_moof_copy_data (moof, &data, &size, &offset);
|
||||||
buffer = _gst_buffer_new_take_data (data, offset);
|
buffer = _gst_buffer_new_take_data (data, offset);
|
||||||
GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer));
|
GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer));
|
||||||
ret = gst_qt_mux_send_buffer (qtmux, buffer, NULL, FALSE);
|
ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE);
|
||||||
|
|
||||||
/* and actual data */
|
/* and actual data */
|
||||||
total_size = 0;
|
total_size = 0;
|
||||||
|
@ -1771,11 +1800,13 @@ flush:
|
||||||
GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
|
GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
|
||||||
atom_array_get_len (&pad->fragment_buffers), total_size);
|
atom_array_get_len (&pad->fragment_buffers), total_size);
|
||||||
if (ret == GST_FLOW_OK)
|
if (ret == GST_FLOW_OK)
|
||||||
ret = gst_qt_mux_send_mdat_header (qtmux, NULL, total_size, FALSE);
|
ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, total_size,
|
||||||
|
FALSE);
|
||||||
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
|
for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
|
||||||
if (G_LIKELY (ret == GST_FLOW_OK))
|
if (G_LIKELY (ret == GST_FLOW_OK))
|
||||||
ret = gst_qt_mux_send_buffer (qtmux,
|
ret = gst_qt_mux_send_buffer (qtmux,
|
||||||
atom_array_index (&pad->fragment_buffers, i), NULL, FALSE);
|
atom_array_index (&pad->fragment_buffers, i), &qtmux->header_size,
|
||||||
|
FALSE);
|
||||||
else
|
else
|
||||||
gst_buffer_unref (atom_array_index (&pad->fragment_buffers, i));
|
gst_buffer_unref (atom_array_index (&pad->fragment_buffers, i));
|
||||||
}
|
}
|
||||||
|
@ -1793,6 +1824,11 @@ init:
|
||||||
atom_array_init (&pad->fragment_buffers, 512);
|
atom_array_init (&pad->fragment_buffers, 512);
|
||||||
pad->fragment_duration = gst_util_uint64_scale (qtmux->fragment_duration,
|
pad->fragment_duration = gst_util_uint64_scale (qtmux->fragment_duration,
|
||||||
atom_trak_get_timescale (pad->trak), 1000);
|
atom_trak_get_timescale (pad->trak), 1000);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (qtmux->mfra && !pad->tfra)) {
|
||||||
|
pad->tfra = atom_tfra_new (qtmux->context, atom_trak_get_id (pad->trak));
|
||||||
|
atom_mfra_add_tfra (qtmux->mfra, pad->tfra);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add buffer and metadata */
|
/* add buffer and metadata */
|
||||||
|
@ -1800,6 +1836,13 @@ init:
|
||||||
atom_array_append (&pad->fragment_buffers, buf, 256);
|
atom_array_append (&pad->fragment_buffers, buf, 256);
|
||||||
pad->fragment_duration -= delta;
|
pad->fragment_duration -= delta;
|
||||||
|
|
||||||
|
if (pad->tfra) {
|
||||||
|
guint32 sn = atom_traf_get_sample_num (pad->traf);
|
||||||
|
|
||||||
|
if ((sync && pad->sync) || (sn == 1 && !pad->sync))
|
||||||
|
atom_tfra_add_entry (pad->tfra, dts, sn);
|
||||||
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (force))
|
if (G_UNLIKELY (force))
|
||||||
goto flush;
|
goto flush;
|
||||||
|
|
||||||
|
@ -2049,8 +2092,8 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
|
||||||
if (qtmux->fragment_sequence) {
|
if (qtmux->fragment_sequence) {
|
||||||
/* ensure that always sync samples are marked as such */
|
/* ensure that always sync samples are marked as such */
|
||||||
return gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf,
|
return gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf,
|
||||||
buf == NULL, nsamples, scaled_duration, sample_size, !pad->sync || sync,
|
buf == NULL, nsamples, last_dts, scaled_duration, sample_size,
|
||||||
do_pts, pts_offset);
|
!pad->sync || sync, do_pts, pts_offset);
|
||||||
} else {
|
} else {
|
||||||
atom_trak_add_samples (pad->trak, nsamples, scaled_duration, sample_size,
|
atom_trak_add_samples (pad->trak, nsamples, scaled_duration, sample_size,
|
||||||
chunk_offset, sync, do_pts, pts_offset);
|
chunk_offset, sync, do_pts, pts_offset);
|
||||||
|
|
|
@ -113,6 +113,8 @@ struct _GstQTPad
|
||||||
ATOM_ARRAY (GstBuffer *) fragment_buffers;
|
ATOM_ARRAY (GstBuffer *) fragment_buffers;
|
||||||
/* running fragment duration */
|
/* running fragment duration */
|
||||||
gint64 fragment_duration;
|
gint64 fragment_duration;
|
||||||
|
/* optional fragment index book-keeping */
|
||||||
|
AtomTFRA *tfra;
|
||||||
|
|
||||||
/* if nothing is set, it won't be called */
|
/* if nothing is set, it won't be called */
|
||||||
GstQTPadPrepareBufferFunc prepare_buf_func;
|
GstQTPadPrepareBufferFunc prepare_buf_func;
|
||||||
|
@ -154,6 +156,9 @@ struct _GstQTMux
|
||||||
GSList *extra_atoms; /* list of extra top-level atoms (e.g. UUID for xmp)
|
GSList *extra_atoms; /* list of extra top-level atoms (e.g. UUID for xmp)
|
||||||
* Stored as AtomInfo structs */
|
* Stored as AtomInfo structs */
|
||||||
|
|
||||||
|
/* fragmented file index */
|
||||||
|
AtomMFRA *mfra;
|
||||||
|
|
||||||
/* fast start */
|
/* fast start */
|
||||||
FILE *fast_start_file;
|
FILE *fast_start_file;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue