[vlc-commits] mux: mp4: rework mux helper for better abstraction
Francois Cartegnie
git at videolan.org
Fri Oct 26 17:53:14 CEST 2018
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Oct 25 22:34:58 2018 +0200| [be35a870d7ae4592e1f47484b03f82da529f2213] | committer: Francois Cartegnie
mux: mp4: rework mux helper for better abstraction
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=be35a870d7ae4592e1f47484b03f82da529f2213
---
.../demux/smooth/playlist/ForgedInitSegment.cpp | 92 ++---
modules/mux/mp4/libmp4mux.c | 269 ++++++++++-----
modules/mux/mp4/libmp4mux.h | 42 ++-
modules/mux/mp4/mp4.c | 382 ++++++++++-----------
4 files changed, 446 insertions(+), 339 deletions(-)
diff --git a/modules/demux/smooth/playlist/ForgedInitSegment.cpp b/modules/demux/smooth/playlist/ForgedInitSegment.cpp
index 631e580ac9..8375e0a243 100644
--- a/modules/demux/smooth/playlist/ForgedInitSegment.cpp
+++ b/modules/demux/smooth/playlist/ForgedInitSegment.cpp
@@ -210,16 +210,10 @@ void ForgedInitSegment::setLanguage(const std::string &lang)
block_t * ForgedInitSegment::buildMoovBox()
{
const Timescale &trackTimescale = inheritTimescale();
- mp4mux_trackinfo_t trackinfo;
- mp4mux_trackinfo_Init(&trackinfo,
- 0x01, /* Will always be 1st and unique track; tfhd patched on block read */
- (uint32_t) trackTimescale);
- trackinfo.i_read_duration = duration.Get();
- trackinfo.i_trex_default_length = 1;
- trackinfo.i_trex_default_size = 1;
-
- es_format_Init(&trackinfo.fmt, es_type, vlc_fourcc_GetCodec(es_type, fourcc));
- trackinfo.fmt.i_original_fourcc = fourcc;
+
+ es_format_t fmt;
+ es_format_Init(&fmt, es_type, vlc_fourcc_GetCodec(es_type, fourcc));
+ fmt.i_original_fourcc = fourcc;
switch(es_type)
{
case VIDEO_ES:
@@ -227,44 +221,44 @@ block_t * ForgedInitSegment::buildMoovBox()
fourcc == VLC_FOURCC( 'A', 'V', 'C', 'B' ) ||
fourcc == VLC_FOURCC( 'H', '2', '6', '4' ) )
{
- trackinfo.fmt.i_codec = VLC_CODEC_H264;
+ fmt.i_codec = VLC_CODEC_H264;
}
else if( fourcc == VLC_FOURCC( 'W', 'V', 'C', '1' ) )
{
- trackinfo.fmt.i_codec = VLC_CODEC_VC1;
-// trackinfo.fmt.video.i_bits_per_pixel = 0x18; // No clue why this was set in smooth streamfilter
+ fmt.i_codec = VLC_CODEC_VC1;
+// fmt.video.i_bits_per_pixel = 0x18; // No clue why this was set in smooth streamfilter
}
- trackinfo.fmt.video.i_width = width;
- trackinfo.fmt.video.i_height = height;
- trackinfo.fmt.video.i_visible_width = width;
- trackinfo.fmt.video.i_visible_height = height;
+ fmt.video.i_width = width;
+ fmt.video.i_height = height;
+ fmt.video.i_visible_width = width;
+ fmt.video.i_visible_height = height;
if(i_extradata && extradata)
{
- trackinfo.fmt.p_extra = malloc(i_extradata);
- if(trackinfo.fmt.p_extra)
+ fmt.p_extra = malloc(i_extradata);
+ if(fmt.p_extra)
{
- memcpy(trackinfo.fmt.p_extra, extradata, i_extradata);
- trackinfo.fmt.i_extra = i_extradata;
+ memcpy(fmt.p_extra, extradata, i_extradata);
+ fmt.i_extra = i_extradata;
}
}
break;
case AUDIO_ES:
- trackinfo.fmt.audio.i_channels = formatex.nChannels;
- trackinfo.fmt.audio.i_rate = formatex.nSamplesPerSec;
- trackinfo.fmt.audio.i_bitspersample = formatex.wBitsPerSample;
- trackinfo.fmt.audio.i_blockalign = formatex.nBlockAlign;
- trackinfo.fmt.i_bitrate = formatex.nAvgBytesPerSec * 8; // FIXME (use bitrate) ?
+ fmt.audio.i_channels = formatex.nChannels;
+ fmt.audio.i_rate = formatex.nSamplesPerSec;
+ fmt.audio.i_bitspersample = formatex.wBitsPerSample;
+ fmt.audio.i_blockalign = formatex.nBlockAlign;
+ fmt.i_bitrate = formatex.nAvgBytesPerSec * 8; // FIXME (use bitrate) ?
if(i_extradata && extradata)
{
- trackinfo.fmt.p_extra = malloc(i_extradata);
- if(trackinfo.fmt.p_extra)
+ fmt.p_extra = malloc(i_extradata);
+ if(fmt.p_extra)
{
- memcpy(trackinfo.fmt.p_extra, extradata, i_extradata);
- trackinfo.fmt.i_extra = i_extradata;
+ memcpy(fmt.p_extra, extradata, i_extradata);
+ fmt.i_extra = i_extradata;
}
}
break;
@@ -277,28 +271,36 @@ block_t * ForgedInitSegment::buildMoovBox()
}
if(!language.empty())
- trackinfo.fmt.psz_language = strdup(language.c_str());
+ fmt.psz_language = strdup(language.c_str());
- mp4mux_trackinfo_t *p_tracks = &trackinfo;
bo_t *box = NULL;
-
- if(mp4mux_CanMux( NULL, &trackinfo.fmt, VLC_FOURCC('s', 'm', 'o', 'o'), true ))
- box = mp4mux_GetMoovBox(NULL, &p_tracks, 1,
- trackTimescale.ToTime(duration.Get()),
- true, false, false, false);
-
- mp4mux_trackinfo_Clear(&trackinfo);
-
- block_t *moov = NULL;
- if(box)
+ mp4mux_handle_t *muxh = mp4mux_New(FRAGMENTED);
+ if(muxh)
{
- moov = box->b;
- free(box);
+ if(mp4mux_CanMux(NULL, &fmt, VLC_FOURCC('s', 'm', 'o', 'o'), true ))
+ {
+ mp4mux_trackinfo_t *p_track = mp4mux_track_Add(muxh,
+ 0x01, /* Will always be 1st and unique track; tfhd patched on block read */
+ &fmt, (uint32_t) trackTimescale);
+ if(p_track)
+ {
+ p_track->i_read_duration = duration.Get();
+ p_track->i_trex_default_length = 1;
+ p_track->i_trex_default_size = 1;
+ }
+ }
+
+ box = mp4mux_GetMoov(muxh, NULL, trackTimescale.ToTime(duration.Get()));
+ mp4mux_Delete(muxh);
}
+ es_format_Clean(&fmt);
- if(!moov)
+ if(!box)
return NULL;
+ block_t *moov = box->b;
+ free(box);
+
vlc_fourcc_t extra[] = {MAJOR_isom, VLC_FOURCC('p','i','f','f'), VLC_FOURCC('i','s','o','2'), VLC_FOURCC('s','m','o','o')};
box = mp4mux_GetFtyp(VLC_FOURCC('i','s','m','l'), 1, extra, ARRAY_SIZE(extra));
diff --git a/modules/mux/mp4/libmp4mux.c b/modules/mux/mp4/libmp4mux.c
index a78f8d8794..7cfea5dde3 100644
--- a/modules/mux/mp4/libmp4mux.c
+++ b/modules/mux/mp4/libmp4mux.c
@@ -34,36 +34,145 @@
#include <vlc_es.h>
#include <vlc_iso_lang.h>
#include <vlc_bits.h>
+#include <vlc_arrays.h>
#include <vlc_text_style.h>
#include <assert.h>
#include <time.h>
-bool mp4mux_trackinfo_Init(mp4mux_trackinfo_t *p_stream, unsigned i_id,
- uint32_t i_timescale)
+struct mp4mux_handle_t
+{
+ unsigned options;
+ vlc_array_t tracks;
+};
+
+static bool mp4mux_trackinfo_Init(mp4mux_trackinfo_t *p_stream, unsigned i_id,
+ uint32_t i_timescale)
{
memset(p_stream, 0, sizeof(*p_stream));
p_stream->i_track_id = i_id;
p_stream->i_timescale = i_timescale;
- p_stream->i_entry_count = 0;
- p_stream->i_entry_max = 1000;
-
- p_stream->entry = calloc(p_stream->i_entry_max, sizeof(mp4mux_entry_t));
- if(!p_stream->entry)
- return false;
+ es_format_Init(&p_stream->fmt, 0, 0);
return true;
}
-void mp4mux_trackinfo_Clear(mp4mux_trackinfo_t *p_stream)
+static void mp4mux_trackinfo_Clear(mp4mux_trackinfo_t *p_stream)
{
es_format_Clean(&p_stream->fmt);
if (p_stream->a52_frame)
block_Release(p_stream->a52_frame);
- free(p_stream->entry);
+ free(p_stream->samples);
free(p_stream->p_edits);
}
+mp4mux_trackinfo_t * mp4mux_track_Add(mp4mux_handle_t *h, unsigned id,
+ const es_format_t *fmt, uint32_t timescale)
+{
+ mp4mux_trackinfo_t *t = malloc(sizeof(*t));
+ if(!mp4mux_trackinfo_Init(t, 0, 0))
+ {
+ free(t);
+ return NULL;
+ }
+ t->i_track_id = id;
+ t->i_timescale = timescale;
+ t->i_firstdts = VLC_TICK_INVALID;
+ es_format_Init(&t->fmt, fmt->i_cat, fmt->i_codec);
+ es_format_Copy(&t->fmt, fmt);
+ vlc_array_append(&h->tracks, t);
+ return t;
+}
+
+bool mp4mux_track_AddEdit(mp4mux_trackinfo_t *t, const mp4mux_edit_t *p_newedit)
+{
+ mp4mux_edit_t *p_realloc = realloc( t->p_edits, sizeof(mp4mux_edit_t) *
+ (t->i_edits_count + 1) );
+ if(unlikely(!p_realloc))
+ return false;
+
+ t->p_edits = p_realloc;
+ t->p_edits[t->i_edits_count++] = *p_newedit;
+
+ return true;
+}
+
+const mp4mux_edit_t *mp4mux_track_GetLastEdit(const mp4mux_trackinfo_t *t)
+{
+ if(t->i_edits_count)
+ return &t->p_edits[t->i_edits_count - 1];
+ else return NULL;
+}
+
+void mp4mux_track_DebugEdits(vlc_object_t *obj, const mp4mux_trackinfo_t *t)
+{
+ for( unsigned i=0; i<t->i_edits_count; i++ )
+ {
+ msg_Dbg(obj, "tk %d elst media time %" PRId64 " duration %" PRIu64 " offset %" PRId64 ,
+ t->i_track_id,
+ t->p_edits[i].i_start_time,
+ t->p_edits[i].i_duration,
+ t->p_edits[i].i_start_offset);
+ }
+}
+
+bool mp4mux_track_AddSample(mp4mux_trackinfo_t *t, const mp4mux_sample_t *entry)
+{
+ /* XXX: -1 to always have 2 entry for easy adding of empty SPU */
+ if (t->i_samples_count + 2 >= t->i_samples_max)
+ {
+ mp4mux_sample_t *p_realloc =
+ realloc(t->samples, sizeof(*p_realloc) * (t->i_samples_max + 1000));
+ if(!p_realloc)
+ return false;
+ t->samples = p_realloc;
+ t->i_samples_max += 1000;
+ }
+ t->samples[t->i_samples_count++] = *entry;
+ return true;
+}
+
+mp4mux_sample_t *mp4mux_track_GetLastSample(mp4mux_trackinfo_t *t)
+{
+ if(t->i_samples_count)
+ return &t->samples[t->i_samples_count - 1];
+ else return NULL;
+}
+
+mp4mux_handle_t * mp4mux_New(enum mp4mux_options options)
+{
+ mp4mux_handle_t *h = malloc(sizeof(*h));
+ vlc_array_init(&h->tracks);
+ h->options = options;
+ return h;
+}
+
+void mp4mux_Delete(mp4mux_handle_t *h)
+{
+ for(size_t i=0; i<vlc_array_count(&h->tracks); i++)
+ {
+ mp4mux_trackinfo_t *t = vlc_array_item_at_index(&h->tracks, i);
+ mp4mux_trackinfo_Clear(t);
+ free(t);
+ }
+ vlc_array_clear(&h->tracks);
+ free(h);
+}
+
+void mp4mux_Set64BitExt(mp4mux_handle_t *h)
+{
+ /* FIXME FIXME
+ * Quicktime actually doesn't like the 64 bits extensions !!! */
+ if(h->options & QUICKTIME)
+ return;
+
+ h->options |= USE64BITEXT;
+}
+
+bool mp4mux_Is(mp4mux_handle_t *h, enum mp4mux_options o)
+{
+ return h->options & o;
+}
bo_t *box_new(const char *fcc)
{
@@ -235,10 +344,10 @@ static bo_t *GetESDS(mp4mux_trackinfo_t *p_track)
int64_t i_bitrate_avg = 0;
int64_t i_bitrate_max = 0;
/* Compute avg/max bitrate */
- for (unsigned i = 0; i < p_track->i_entry_count; i++) {
- i_bitrate_avg += p_track->entry[i].i_size;
- if (p_track->entry[i].i_length > 0) {
- int64_t i_bitrate = CLOCK_FREQ * 8 * p_track->entry[i].i_size / p_track->entry[i].i_length;
+ for (unsigned i = 0; i < p_track->i_samples_count; i++) {
+ i_bitrate_avg += p_track->samples[i].i_size;
+ if (p_track->samples[i].i_length > 0) {
+ int64_t i_bitrate = CLOCK_FREQ * 8 * p_track->samples[i].i_size / p_track->samples[i].i_length;
if (i_bitrate > i_bitrate_max)
i_bitrate_max = i_bitrate;
}
@@ -828,15 +937,15 @@ static bo_t *GetSVQ3Tag(es_format_t *p_fmt)
return smi;
}
-static bo_t *GetUdtaTag(mp4mux_trackinfo_t **pp_tracks, unsigned int i_tracks)
+static bo_t *GetUdtaTag(mp4mux_handle_t *muxh)
{
bo_t *udta = box_new("udta");
if (!udta)
return NULL;
/* Requirements */
- for (unsigned int i = 0; i < i_tracks; i++) {
- mp4mux_trackinfo_t *p_stream = pp_tracks[i];
+ for (unsigned int i = 0; i < vlc_array_count(&muxh->tracks); i++) {
+ mp4mux_trackinfo_t *p_stream = vlc_array_item_at_index(&muxh->tracks, i);
vlc_fourcc_t codec = p_stream->fmt.i_codec;
if (codec == VLC_CODEC_MP4V || codec == VLC_CODEC_MP4A) {
@@ -1219,7 +1328,7 @@ static bo_t *GetTextBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
return NULL;
}
-static int64_t GetScaledEntryDuration( const mp4mux_entry_t *p_entry, uint32_t i_timescale,
+static int64_t GetScaledEntryDuration( const mp4mux_sample_t *p_entry, uint32_t i_timescale,
vlc_tick_t *pi_total_mtime, int64_t *pi_total_scaled )
{
const vlc_tick_t i_totalscaledtototalmtime = vlc_tick_from_samples(*pi_total_scaled, i_timescale);
@@ -1276,8 +1385,8 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
unsigned i_chunk = 0;
unsigned i_stsc_last_val = 0, i_stsc_entries = 0;
- for (unsigned i = 0; i < p_track->i_entry_count; i_chunk++) {
- mp4mux_entry_t *entry = p_track->entry;
+ for (unsigned i = 0; i < p_track->i_samples_count; i_chunk++) {
+ mp4mux_sample_t *entry = p_track->samples;
int i_first = i;
if (b_stco64)
@@ -1285,8 +1394,8 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
else
bo_add_32be(stco, entry[i].i_pos);
- for (; i < p_track->i_entry_count; i++)
- if (i >= p_track->i_entry_count - 1 ||
+ for (; i < p_track->i_samples_count; i++)
+ if (i >= p_track->i_samples_count - 1 ||
entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
i++;
break;
@@ -1324,16 +1433,16 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
vlc_tick_t i_total_mtime = 0;
int64_t i_total_scaled = 0;
unsigned i_index = 0;
- for (unsigned i = 0; i < p_track->i_entry_count; i_index++) {
+ for (unsigned i = 0; i < p_track->i_samples_count; i_index++) {
int i_first = i;
- int64_t i_scaled = GetScaledEntryDuration(&p_track->entry[i], p_track->i_timescale,
+ int64_t i_scaled = GetScaledEntryDuration(&p_track->samples[i], p_track->i_timescale,
&i_total_mtime, &i_total_scaled);
- for (unsigned j=i+1; j < p_track->i_entry_count; j++)
+ for (unsigned j=i+1; j < p_track->i_samples_count; j++)
{
vlc_tick_t i_total_mtime_next = i_total_mtime;
int64_t i_total_scaled_next = i_total_scaled;
- int64_t i_scalednext = GetScaledEntryDuration(&p_track->entry[j], p_track->i_timescale,
+ int64_t i_scalednext = GetScaledEntryDuration(&p_track->samples[j], p_track->i_timescale,
&i_total_mtime_next, &i_total_scaled_next);
if( i_scalednext != i_scaled )
break;
@@ -1357,13 +1466,13 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
{
bo_add_32be(ctts, 0);
i_index = 0;
- for (unsigned i = 0; i < p_track->i_entry_count; i_index++)
+ for (unsigned i = 0; i < p_track->i_samples_count; i_index++)
{
int i_first = i;
- vlc_tick_t i_offset = p_track->entry[i].i_pts_dts;
+ vlc_tick_t i_offset = p_track->samples[i].i_pts_dts;
- for (; i < p_track->i_entry_count; ++i)
- if (i == p_track->i_entry_count || p_track->entry[i].i_pts_dts != i_offset)
+ for (; i < p_track->i_samples_count; ++i)
+ if (i == p_track->i_samples_count || p_track->samples[i].i_pts_dts != i_offset)
break;
bo_add_32be(ctts, i - i_first); // sample-count
@@ -1381,22 +1490,22 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
return NULL;
}
int i_size = 0;
- for (unsigned i = 0; i < p_track->i_entry_count; i++)
+ for (unsigned i = 0; i < p_track->i_samples_count; i++)
{
if ( i == 0 )
- i_size = p_track->entry[i].i_size;
- else if ( p_track->entry[i].i_size != i_size )
+ i_size = p_track->samples[i].i_size;
+ else if ( p_track->samples[i].i_size != i_size )
{
i_size = 0;
break;
}
}
bo_add_32be(stsz, i_size); // sample-size
- bo_add_32be(stsz, p_track->i_entry_count); // sample-count
+ bo_add_32be(stsz, p_track->i_samples_count); // sample-count
if ( i_size == 0 ) // all samples have different size
{
- for (unsigned i = 0; i < p_track->i_entry_count; i++)
- bo_add_32be(stsz, p_track->entry[i].i_size); // sample-size
+ for (unsigned i = 0; i < p_track->i_samples_count; i++)
+ bo_add_32be(stsz, p_track->samples[i].i_size); // sample-size
}
/* create stss table */
@@ -1405,16 +1514,16 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
if ( p_track->fmt.i_cat == VIDEO_ES || p_track->fmt.i_cat == AUDIO_ES )
{
vlc_tick_t i_interval = -1;
- for (unsigned i = 0; i < p_track->i_entry_count; i++)
+ for (unsigned i = 0; i < p_track->i_samples_count; i++)
{
if ( i_interval != -1 )
{
- i_interval += p_track->entry[i].i_length + p_track->entry[i].i_pts_dts;
+ i_interval += p_track->samples[i].i_length + p_track->samples[i].i_pts_dts;
if ( i_interval < VLC_TICK_FROM_SEC(2) )
continue;
}
- if (p_track->entry[i].i_flags & BLOCK_FLAG_TYPE_I) {
+ if (p_track->samples[i].i_flags & BLOCK_FLAG_TYPE_I) {
if (stss == NULL) {
stss = box_full_new("stss", 0, 0);
if(!stss)
@@ -1457,9 +1566,7 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
return stbl;
}
-bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, unsigned int i_tracks,
- vlc_tick_t i_duration,
- bool b_fragmented, bool b_mov, bool b_64_ext, bool b_stco64 )
+bo_t * mp4mux_GetMoov(mp4mux_handle_t *h, vlc_object_t *p_obj, vlc_tick_t i_duration)
{
bo_t *moov, *mvhd;
@@ -1468,17 +1575,17 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
/* Important for smooth streaming where its (not muxed here) media time offsets
* are in timescale == track timescale */
- if( i_tracks == 1 )
- i_movie_timescale = pp_tracks[0]->i_timescale;
+ if( vlc_array_count(&h->tracks) == 1 )
+ i_movie_timescale = ((mp4mux_trackinfo_t *)vlc_array_item_at_index(&h->tracks, 0))->i_timescale;
moov = box_new("moov");
if(!moov)
return NULL;
/* Create general info */
- if( i_duration == 0 && !b_fragmented )
+ if( i_duration == 0 && (h->options & FRAGMENTED) == 0 )
{
- for (unsigned int i = 0; i < i_tracks; i++) {
- mp4mux_trackinfo_t *p_stream = pp_tracks[i];
+ for (unsigned int i = 0; i < vlc_array_count(&h->tracks); i++) {
+ mp4mux_trackinfo_t *p_stream = vlc_array_item_at_index(&h->tracks, 0);
i_duration = __MAX(i_duration, p_stream->i_read_duration);
}
if(p_obj)
@@ -1487,7 +1594,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
int64_t i_movie_duration = samples_from_vlc_tick(i_duration, i_movie_timescale);
/* *** add /moov/mvhd *** */
- if (!b_64_ext) {
+ if ((h->options & USE64BITEXT) == 0) {
mvhd = box_full_new("mvhd", 0, 0);
if(!mvhd)
{
@@ -1524,15 +1631,18 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
bo_add_32be(mvhd, 0); // pre-defined
/* Next available track id */
- bo_add_32be(mvhd, (i_tracks) ? pp_tracks[i_tracks -1]->i_track_id + 1: 1); // next-track-id
+ const mp4mux_trackinfo_t *lasttrack = vlc_array_count(&h->tracks)
+ ? vlc_array_item_at_index(&h->tracks, vlc_array_count(&h->tracks) - 1)
+ : NULL;
+ bo_add_32be(mvhd, lasttrack ? lasttrack->i_track_id + 1: 1); // next-track-id
box_gather(moov, mvhd);
- for (unsigned int i_trak = 0; i_trak < i_tracks; i_trak++) {
- mp4mux_trackinfo_t *p_stream = pp_tracks[i_trak];
+ for (unsigned int i_trak = 0; i_trak < vlc_array_count(&h->tracks); i_trak++) {
+ mp4mux_trackinfo_t *p_stream = vlc_array_item_at_index(&h->tracks, i_trak);
int64_t i_stream_duration;
- if ( !b_fragmented )
+ if ( (h->options & FRAGMENTED) == 0 )
i_stream_duration = samples_from_vlc_tick(p_stream->i_read_duration, i_movie_timescale);
else
i_stream_duration = 0;
@@ -1544,8 +1654,8 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
/* *** add /moov/trak/tkhd *** */
bo_t *tkhd;
- if (!b_64_ext) {
- if (b_mov)
+ if ((h->options & USE64BITEXT) == 0) {
+ if (h->options & QUICKTIME)
tkhd = box_full_new("tkhd", 0, 0x0f);
else
tkhd = box_full_new("tkhd", 0, 1);
@@ -1560,7 +1670,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
bo_add_32be(tkhd, 0); // reserved 0
bo_add_32be(tkhd, i_stream_duration); // duration
} else {
- if (b_mov)
+ if (h->options & QUICKTIME)
tkhd = box_full_new("tkhd", 1, 0x0f);
else
tkhd = box_full_new("tkhd", 1, 1);
@@ -1603,8 +1713,8 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
} else {
int i_width = 320 << 16;
int i_height = 200;
- for (unsigned int i = 0; i < i_tracks; i++) {
- mp4mux_trackinfo_t *tk = pp_tracks[i];
+ for (unsigned int i = 0; i < vlc_array_count(&h->tracks); i++) {
+ const mp4mux_trackinfo_t *tk = vlc_array_item_at_index(&h->tracks, i);
if (tk->fmt.i_cat == VIDEO_ES) {
if (tk->fmt.video.i_sar_num > 0 &&
tk->fmt.video.i_sar_den > 0)
@@ -1624,7 +1734,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
box_gather(trak, tkhd);
/* *** add /moov/trak/edts and elst */
- bo_t *edts = GetEDTS(p_stream, i_movie_timescale, b_64_ext);
+ bo_t *edts = GetEDTS(p_stream, i_movie_timescale, h->options & USE64BITEXT);
if(edts)
box_gather(trak, edts);
@@ -1638,7 +1748,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
/* media header */
bo_t *mdhd;
- if (!b_64_ext) {
+ if ((h->options & USE64BITEXT) == 0) {
mdhd = box_full_new("mdhd", 0, 0);
if(!mdhd)
{
@@ -1696,7 +1806,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
continue;
}
- if (b_mov)
+ if (h->options & QUICKTIME)
bo_add_fourcc(hdlr, "mhlr"); // media handler
else
bo_add_32be(hdlr, 0);
@@ -1711,7 +1821,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
/* sbtl/tx3g Apple subs */
/* text/text Apple textmedia */
if(p_stream->fmt.i_codec == VLC_CODEC_TX3G)
- bo_add_fourcc(hdlr, (b_mov) ? "sbtl" : "text");
+ bo_add_fourcc(hdlr, (h->options & QUICKTIME) ? "sbtl" : "text");
else if(p_stream->fmt.i_codec == VLC_CODEC_TTML)
bo_add_fourcc(hdlr, "sbtl");
else
@@ -1722,7 +1832,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
bo_add_32be(hdlr, 0); // reserved
bo_add_32be(hdlr, 0); // reserved
- if (b_mov)
+ if (h->options & QUICKTIME)
bo_add_8(hdlr, 12); /* Pascal string for .mov */
if (p_stream->fmt.i_cat == AUDIO_ES)
@@ -1732,7 +1842,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
else
bo_add_mem(hdlr, 12, (uint8_t*)"Text Handler");
- if (!b_mov)
+ if ((h->options & QUICKTIME) == 0)
bo_add_8(hdlr, 0); /* asciiz string for .mp4, yes that's BRAIN DAMAGED F**K MP4 */
box_gather(mdia, hdlr);
@@ -1766,7 +1876,7 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
box_gather(minf, vmhd);
}
} else if (p_stream->fmt.i_cat == SPU_ES) {
- if(b_mov &&
+ if((h->options & QUICKTIME) &&
(p_stream->fmt.i_codec == VLC_CODEC_SUBT||
p_stream->fmt.i_codec == VLC_CODEC_TX3G||
p_stream->fmt.i_codec == VLC_CODEC_QTXT))
@@ -1814,15 +1924,15 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
/* add stbl */
bo_t *stbl;
- if ( b_fragmented )
+ if (h->options & FRAGMENTED)
{
- uint32_t i_backup = p_stream->i_entry_count;
- p_stream->i_entry_count = 0;
- stbl = GetStblBox(p_obj, p_stream, b_mov, b_stco64);
- p_stream->i_entry_count = i_backup;
+ uint32_t i_backup = p_stream->i_samples_count;
+ p_stream->i_samples_count = 0;
+ stbl = GetStblBox(p_obj, p_stream, h->options & QUICKTIME, h->options & USE64BITEXT);
+ p_stream->i_samples_count = i_backup;
}
else
- stbl = GetStblBox(p_obj, p_stream, b_mov, b_stco64);
+ stbl = GetStblBox(p_obj, p_stream, h->options & QUICKTIME, h->options & USE64BITEXT);
/* append stbl to minf */
p_stream->i_stco_pos += bo_size(minf);
@@ -1842,35 +1952,36 @@ bo_t * mp4mux_GetMoovBox(vlc_object_t *p_obj, mp4mux_trackinfo_t **pp_tracks, un
}
/* Add user data tags */
- box_gather(moov, GetUdtaTag(pp_tracks, i_tracks));
+ box_gather(moov, GetUdtaTag(h));
- if ( b_fragmented )
+ if ( h->options & FRAGMENTED )
{
bo_t *mvex = box_new("mvex");
if( mvex )
{
if( i_movie_duration )
{
- bo_t *mehd = box_full_new("mehd", b_64_ext ? 1 : 0, 0);
+ bo_t *mehd = box_full_new("mehd", (h->options & USE64BITEXT) ? 1 : 0, 0);
if(mehd)
{
- if(b_64_ext)
+ if((h->options & USE64BITEXT))
bo_add_64be(mehd, i_movie_duration);
else
bo_add_32be(mehd, i_movie_duration);
box_gather(mvex, mehd);
}
}
- for (unsigned int i_trak = 0; mvex && i_trak < i_tracks; i_trak++)
+
+ for (unsigned int i = 0; mvex && i < vlc_array_count(&h->tracks); i++)
{
- mp4mux_trackinfo_t *p_stream = pp_tracks[i_trak];
+ mp4mux_trackinfo_t *p_stream = vlc_array_item_at_index(&h->tracks, i);
/* Try to find some defaults */
- if ( p_stream->i_entry_count )
+ if ( p_stream->i_samples_count )
{
// FIXME: find highest occurence
- p_stream->i_trex_default_length = p_stream->entry[0].i_length;
- p_stream->i_trex_default_size = p_stream->entry[0].i_size;
+ p_stream->i_trex_default_length = p_stream->samples[0].i_length;
+ p_stream->i_trex_default_size = p_stream->samples[0].i_size;
}
/* *** add /mvex/trex *** */
diff --git a/modules/mux/mp4/libmp4mux.h b/modules/mux/mp4/libmp4mux.h
index 0a5d0ab452..6a45bc3fa2 100644
--- a/modules/mux/mp4/libmp4mux.h
+++ b/modules/mux/mp4/libmp4mux.h
@@ -24,6 +24,8 @@
#include <vlc_es.h>
#include <vlc_boxes.h>
+typedef struct mp4mux_handle_t mp4mux_handle_t;
+
typedef struct
{
uint64_t i_pos;
@@ -32,7 +34,7 @@ typedef struct
vlc_tick_t i_pts_dts;
vlc_tick_t i_length;
unsigned int i_flags;
-} mp4mux_entry_t;
+} mp4mux_sample_t;
typedef struct
{
@@ -47,9 +49,9 @@ typedef struct
es_format_t fmt;
/* index */
- unsigned int i_entry_count;
- unsigned int i_entry_max;
- mp4mux_entry_t *entry;
+ unsigned int i_samples_count;
+ unsigned int i_samples_max;
+ mp4mux_sample_t *samples;
/* XXX: needed for other codecs too, see lavf */
block_t *a52_frame;
@@ -74,8 +76,32 @@ typedef struct
} mp4mux_trackinfo_t;
-bool mp4mux_trackinfo_Init( mp4mux_trackinfo_t *, unsigned, uint32_t );
-void mp4mux_trackinfo_Clear( mp4mux_trackinfo_t * );
+enum mp4mux_options
+{
+ FRAGMENTED = 1 << 0,
+ QUICKTIME = 1 << 1,
+ USE64BITEXT = 1 << 2,
+};
+
+mp4mux_handle_t * mp4mux_New(enum mp4mux_options);
+void mp4mux_Delete(mp4mux_handle_t *);
+void mp4mux_Set64BitExt(mp4mux_handle_t *);
+bool mp4mux_Is(mp4mux_handle_t *, enum mp4mux_options);
+
+mp4mux_trackinfo_t * mp4mux_track_Add(mp4mux_handle_t *, unsigned id,
+ const es_format_t *fmt, uint32_t timescale);
+/* ELST */
+bool mp4mux_track_AddEdit(mp4mux_trackinfo_t *, const mp4mux_edit_t *);
+const mp4mux_edit_t *mp4mux_track_GetLastEdit(const mp4mux_trackinfo_t *);
+void mp4mux_track_DebugEdits(vlc_object_t *, const mp4mux_trackinfo_t *);
+/* Samples */
+bool mp4mux_track_AddSample(mp4mux_trackinfo_t *, const mp4mux_sample_t *);
+mp4mux_sample_t *mp4mux_track_GetLastSample(mp4mux_trackinfo_t *);
+
+
+bo_t *mp4mux_GetMoov(mp4mux_handle_t *, vlc_object_t *, vlc_tick_t i_movie_duration);
+
+/* old */
bo_t *box_new (const char *fcc);
bo_t *box_full_new(const char *fcc, uint8_t v, uint32_t f);
@@ -84,6 +110,4 @@ void box_gather (bo_t *box, bo_t *box2);
bool mp4mux_CanMux(vlc_object_t *, const es_format_t *, vlc_fourcc_t, bool);
bo_t *mp4mux_GetFtyp(vlc_fourcc_t, uint32_t, vlc_fourcc_t[], size_t i_fourcc);
-bo_t *mp4mux_GetMoovBox(vlc_object_t *, mp4mux_trackinfo_t **pp_tracks, unsigned int i_tracks,
- vlc_tick_t i_movie_duration,
- bool b_fragmented, bool b_mov, bool b_64ext, bool b_stco64);
+
diff --git a/modules/mux/mp4/mp4.c b/modules/mux/mp4/mp4.c
index 7e31a6fb1e..5799245486 100644
--- a/modules/mux/mp4/mp4.c
+++ b/modules/mux/mp4/mp4.c
@@ -127,7 +127,7 @@ typedef struct mp4_fragqueue_t
typedef struct
{
- mp4mux_trackinfo_t mux;
+ mp4mux_trackinfo_t *tinfo;
/* index */
vlc_tick_t i_length_neg;
@@ -153,9 +153,8 @@ typedef struct
typedef struct
{
- bool b_mov;
+ mp4mux_handle_t *muxh;
bool b_3gp;
- bool b_64_ext;
bool b_fast_start;
/* global */
@@ -171,17 +170,14 @@ typedef struct
/* mp4frag */
- bool b_fragmented;
vlc_tick_t i_written_duration;
uint32_t i_mfhd_sequence;
} sout_mux_sys_t;
static void box_send(sout_mux_t *p_mux, bo_t *box);
-static bo_t *BuildMoov(sout_mux_t *p_mux);
static block_t *ConvertSUBT(block_t *);
static bool CreateCurrentEdit(mp4_stream_t *, vlc_tick_t, bool);
-static void DebugEdits(sout_mux_t *, const mp4_stream_t *);
static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_stream);
static int WriteSlowStartHeader(sout_mux_t *p_mux)
@@ -189,7 +185,7 @@ static int WriteSlowStartHeader(sout_mux_t *p_mux)
sout_mux_sys_t *p_sys = p_mux->p_sys;
bo_t *box;
- if (!p_sys->b_mov) {
+ if (!mp4mux_Is(p_sys->muxh, QUICKTIME)) {
/* Now add ftyp header */
if(p_sys->b_3gp)
{
@@ -238,13 +234,18 @@ static int Open(vlc_object_t *p_this)
msg_Dbg(p_mux, "Mp4 muxer opened");
config_ChainParse(p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg);
- p_sys->b_mov = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "mov");
- p_sys->b_3gp = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "3gp");
- p_sys->b_fragmented = p_mux->psz_mux && (!strcmp(p_mux->psz_mux, "mp4frag") ||
- !strcmp(p_mux->psz_mux, "mp4stream"));
- /* FIXME FIXME
- * Quicktime actually doesn't like the 64 bits extensions !!! */
- p_sys->b_64_ext = false;
+ enum mp4mux_options options = 0;
+ if(p_mux->psz_mux)
+ {
+ if(!strcmp(p_mux->psz_mux, "mov"))
+ options |= QUICKTIME;
+ if(!strcmp(p_mux->psz_mux, "mp4frag") || !strcmp(p_mux->psz_mux, "mp4stream"))
+ options |= FRAGMENTED;
+ }
+
+ p_sys->b_3gp = p_mux->psz_mux && !strcmp(p_mux->psz_mux, "3gp");
+
+ p_sys->muxh = mp4mux_New(options);
p_sys->i_pos = 0;
p_sys->i_nb_streams = 0;
@@ -261,7 +262,7 @@ static int Open(vlc_object_t *p_this)
p_mux->pf_control = Control;
p_mux->pf_addstream = AddStream;
p_mux->pf_delstream = DelStream;
- p_mux->pf_mux = p_sys->b_fragmented ? MuxFrag : Mux;
+ p_mux->pf_mux = (options & FRAGMENTED) ? MuxFrag : Mux;
return VLC_SUCCESS;
}
@@ -296,9 +297,11 @@ static void Close(vlc_object_t *p_this)
sout_AccessOutWrite(p_mux->p_access, bo.b);
/* Create MOOV header */
- const bool b_stco64 = (p_sys->i_pos >= (((uint64_t)0x1) << 32));
+ const bool b_64bitext = (p_sys->i_pos >= (((uint64_t)0x1) << 32));
+ if(b_64bitext)
+ mp4mux_Set64BitExt(p_sys->muxh);
uint64_t i_moov_pos = p_sys->i_pos;
- bo_t *moov = BuildMoov(p_mux);
+ bo_t *moov = mp4mux_GetMoov(p_sys->muxh, VLC_OBJECT(p_mux), 0);
/* Check we need to create "fast start" files */
p_sys->b_fast_start = var_GetBool(p_this, SOUT_CFG_PREFIX "faststart");
@@ -337,15 +340,15 @@ static void Close(vlc_object_t *p_this)
for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
unsigned i_written = 0;
- for (unsigned i = 0; i < p_stream->mux.i_entry_count; ) {
- mp4mux_entry_t *entry = p_stream->mux.entry;
- if (b_stco64)
- bo_set_64be(moov, p_stream->mux.i_stco_pos + i_written++ * 8, entry[i].i_pos + p_sys->i_mdat_pos - i_moov_pos);
+ for (unsigned i = 0; i < p_stream->tinfo->i_samples_count; ) {
+ mp4mux_sample_t *entry = p_stream->tinfo->samples;
+ if (b_64bitext)
+ bo_set_64be(moov, p_stream->tinfo->i_stco_pos + i_written++ * 8, entry[i].i_pos + p_sys->i_mdat_pos - i_moov_pos);
else
- bo_set_32be(moov, p_stream->mux.i_stco_pos + i_written++ * 4, entry[i].i_pos + p_sys->i_mdat_pos - i_moov_pos);
+ bo_set_32be(moov, p_stream->tinfo->i_stco_pos + i_written++ * 4, entry[i].i_pos + p_sys->i_mdat_pos - i_moov_pos);
- for (; i < p_stream->mux.i_entry_count; i++)
- if (i >= p_stream->mux.i_entry_count - 1 ||
+ for (; i < p_stream->tinfo->i_samples_count; i++)
+ if (i >= p_stream->tinfo->i_samples_count - 1 ||
entry[i].i_pos + entry[i].i_size != entry[i+1].i_pos) {
i++;
break;
@@ -363,12 +366,10 @@ static void Close(vlc_object_t *p_this)
cleanup:
/* Clean-up */
- for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++) {
- mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
- mp4mux_trackinfo_Clear(&p_stream->mux);
- free(p_stream);
- }
+ for (unsigned int i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++)
+ free(p_sys->pp_streams[i_trak]);
TAB_CLEAN(p_sys->i_nb_streams, p_sys->pp_streams);
+ mp4mux_Delete(p_sys->muxh);
free(p_sys);
}
@@ -407,8 +408,8 @@ static int AddStream(sout_mux_t *p_mux, sout_input_t *p_input)
mp4_stream_t *p_stream;
if(!mp4mux_CanMux(VLC_OBJECT(p_mux), p_input->p_fmt,
- p_sys->b_mov ? MAJOR_qt__ : MAJOR_isom,
- p_sys->b_fragmented))
+ mp4mux_Is(p_sys->muxh, QUICKTIME) ? MAJOR_qt__ : MAJOR_isom,
+ mp4mux_Is(p_sys->muxh, FRAGMENTED)))
{
msg_Err(p_mux, "unsupported codec %4.4s in mp4",
(char*)&p_input->p_fmt->i_codec);
@@ -416,52 +417,57 @@ static int AddStream(sout_mux_t *p_mux, sout_input_t *p_input)
}
p_stream = malloc(sizeof(mp4_stream_t));
- if (!p_stream ||
- !mp4mux_trackinfo_Init(&p_stream->mux, p_sys->i_nb_streams + 1, CLOCK_FREQ))
- {
- free(p_stream);
+ if(!p_stream)
return VLC_ENOMEM;
- }
- es_format_Copy(&p_stream->mux.fmt, p_input->p_fmt);
- p_stream->i_length_neg = 0;
- p_stream->i_first_dts = VLC_TICK_INVALID;
- switch( p_stream->mux.fmt.i_cat )
+ uint32_t i_track_timescale = CLOCK_FREQ;
+ es_format_t trackfmt;
+ es_format_Init(&trackfmt, p_input->p_fmt->i_cat, p_input->p_fmt->i_codec);
+ es_format_Copy(&trackfmt, p_input->p_fmt);
+
+ switch( p_input->p_fmt->i_cat )
{
case AUDIO_ES:
- if(!p_stream->mux.fmt.audio.i_rate)
+ if(!trackfmt.audio.i_rate)
{
msg_Warn( p_mux, "no audio rate given for stream %d, assuming 48KHz",
p_sys->i_nb_streams );
- p_stream->mux.fmt.audio.i_rate = 48000;
+ trackfmt.audio.i_rate = 48000;
}
- p_stream->mux.i_timescale = p_stream->mux.fmt.audio.i_rate;
+ i_track_timescale = trackfmt.audio.i_rate;
break;
case VIDEO_ES:
- if( !p_stream->mux.fmt.video.i_frame_rate ||
- !p_stream->mux.fmt.video.i_frame_rate_base )
+ if( !trackfmt.video.i_frame_rate ||
+ !trackfmt.video.i_frame_rate_base )
{
msg_Warn( p_mux, "Missing frame rate for stream %d, assuming 25fps",
p_sys->i_nb_streams );
- p_stream->mux.fmt.video.i_frame_rate = 25;
- p_stream->mux.fmt.video.i_frame_rate_base = 1;
+ trackfmt.video.i_frame_rate = 25;
+ trackfmt.video.i_frame_rate_base = 1;
}
- p_stream->mux.i_timescale = p_stream->mux.fmt.video.i_frame_rate *
- p_stream->mux.fmt.video.i_frame_rate_base;
+ i_track_timescale = trackfmt.video.i_frame_rate *
+ trackfmt.video.i_frame_rate_base;
- if( p_stream->mux.i_timescale > CLOCK_FREQ )
- p_stream->mux.i_timescale = CLOCK_FREQ;
- else if( p_stream->mux.i_timescale < 90000 )
- p_stream->mux.i_timescale = 90000;
+ if( i_track_timescale > CLOCK_FREQ )
+ i_track_timescale = CLOCK_FREQ;
+ else if( i_track_timescale < 90000 )
+ i_track_timescale = 90000;
break;
default:
break;
}
- p_stream->mux.p_edits = NULL;
- p_stream->mux.i_edits_count = 0;
- p_stream->mux.i_firstdts = VLC_TICK_INVALID;
+ p_stream->tinfo = mp4mux_track_Add(p_sys->muxh, p_sys->i_nb_streams + 1,
+ &trackfmt, i_track_timescale);
+ es_format_Clean(&trackfmt);
+ if(!p_stream->tinfo)
+ {
+ free(p_stream);
+ return VLC_ENOMEM;
+ }
+
+ p_stream->i_length_neg = 0;
p_stream->i_last_dts = VLC_TICK_INVALID;
p_stream->i_last_pts = VLC_TICK_INVALID;
@@ -495,13 +501,13 @@ static void DelStream(sout_mux_t *p_mux, sout_input_t *p_input)
sout_mux_sys_t *p_sys = p_mux->p_sys;
mp4_stream_t *p_stream = (mp4_stream_t*)p_input->p_sys;
- if(!p_sys->b_fragmented)
+ if(!mp4mux_Is(p_sys->muxh, FRAGMENTED))
{
while(block_FifoCount(p_input->p_fifo) > 0 &&
MuxStream(p_mux, p_input, p_stream) == VLC_SUCCESS) {};
if(CreateCurrentEdit(p_stream, p_sys->i_start_dts, false))
- DebugEdits(p_mux, p_stream);
+ mp4mux_track_DebugEdits(VLC_OBJECT(p_mux), p_stream->tinfo);
}
msg_Dbg(p_mux, "removing input");
@@ -510,64 +516,46 @@ static void DelStream(sout_mux_t *p_mux, sout_input_t *p_input)
/*****************************************************************************
* Mux:
*****************************************************************************/
-static void DebugEdits(sout_mux_t *p_mux, const mp4_stream_t *p_stream)
-{
- for( unsigned i=0; i<p_stream->mux.i_edits_count; i++ )
- {
- msg_Dbg(p_mux, "tk %d elst media time %" PRId64 " duration %" PRIu64 " offset %" PRId64 ,
- p_stream->mux.i_track_id,
- p_stream->mux.p_edits[i].i_start_time,
- p_stream->mux.p_edits[i].i_duration,
- p_stream->mux.p_edits[i].i_start_offset);
- }
-}
-
static bool CreateCurrentEdit(mp4_stream_t *p_stream, vlc_tick_t i_mux_start_dts,
bool b_fragmented)
{
+ const mp4mux_edit_t *p_lastedit = mp4mux_track_GetLastEdit(p_stream->tinfo);
+
/* Never more than first empty edit for fragmented */
- if(p_stream->mux.i_edits_count && b_fragmented)
+ if(p_lastedit != NULL && b_fragmented)
return true;
- if(p_stream->mux.i_entry_count == 0)
+ if(p_stream->tinfo->i_samples_count == 0)
return true;
- mp4mux_edit_t *p_realloc = realloc( p_stream->mux.p_edits, sizeof(mp4mux_edit_t) *
- (p_stream->mux.i_edits_count + 1) );
- if(unlikely(!p_realloc))
- return false;
+ mp4mux_edit_t newedit;
- mp4mux_edit_t *p_newedit = &p_realloc[p_stream->mux.i_edits_count];
- if(p_stream->mux.i_edits_count == 0)
+ if(p_lastedit == NULL)
{
- p_newedit->i_start_time = 0;
- p_newedit->i_start_offset = __MAX(0, p_stream->i_first_dts - i_mux_start_dts);
+ newedit.i_start_time = 0;
+ newedit.i_start_offset = __MAX(0, p_stream->i_first_dts - i_mux_start_dts);
}
else
{
- const mp4mux_edit_t *p_lastedit = &p_realloc[p_stream->mux.i_edits_count - 1];
- p_newedit->i_start_time = __MAX(0, p_lastedit->i_start_time + p_lastedit->i_duration);
- p_newedit->i_start_offset = 0;
+ newedit.i_start_time = __MAX(0, p_lastedit->i_start_time + p_lastedit->i_duration);
+ newedit.i_start_offset = 0;
}
if(b_fragmented)
{
- p_newedit->i_duration = 0;
+ newedit.i_duration = 0;
}
else
{
if(p_stream->i_last_pts != VLC_TICK_INVALID)
- p_newedit->i_duration = p_stream->i_last_pts - p_stream->i_first_dts;
+ newedit.i_duration = p_stream->i_last_pts - p_stream->i_first_dts;
else
- p_newedit->i_duration = p_stream->i_last_dts - p_stream->i_first_dts;
- if(p_stream->mux.i_entry_count)
- p_newedit->i_duration += p_stream->mux.entry[p_stream->mux.i_entry_count - 1].i_length;
+ newedit.i_duration = p_stream->i_last_dts - p_stream->i_first_dts;
+ if(p_stream->tinfo->i_samples_count)
+ newedit.i_duration += p_stream->tinfo->samples[p_stream->tinfo->i_samples_count - 1].i_length;
}
- p_stream->mux.p_edits = p_realloc;
- p_stream->mux.i_edits_count++;
-
- return true;
+ return mp4mux_track_AddEdit(p_stream->tinfo, &newedit);
}
static block_t * BlockDequeue(sout_input_t *p_input, mp4_stream_t *p_stream)
@@ -576,7 +564,7 @@ static block_t * BlockDequeue(sout_input_t *p_input, mp4_stream_t *p_stream)
if(unlikely(!p_block))
return NULL;
- switch(p_stream->mux.fmt.i_codec)
+ switch(p_stream->tinfo->fmt.i_codec)
{
case VLC_CODEC_AV1:
p_block = AV1_Pack_Sample(p_block);
@@ -590,8 +578,8 @@ static block_t * BlockDequeue(sout_input_t *p_input, mp4_stream_t *p_stream)
break;
case VLC_CODEC_A52:
case VLC_CODEC_EAC3:
- if (p_stream->mux.a52_frame == NULL && p_block->i_buffer >= 8)
- p_stream->mux.a52_frame = block_Duplicate(p_block);
+ if (p_stream->tinfo->a52_frame == NULL && p_block->i_buffer >= 8)
+ p_stream->tinfo->a52_frame = block_Duplicate(p_block);
break;
default:
break;
@@ -614,11 +602,12 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
return VLC_SUCCESS;
/* Reset reference dts in case of discontinuity (ex: gather sout) */
- if (p_data->i_flags & BLOCK_FLAG_DISCONTINUITY && p_stream->mux.i_entry_count)
+ if (p_data->i_flags & BLOCK_FLAG_DISCONTINUITY && p_stream->tinfo->i_samples_count)
{
if(p_stream->i_first_dts != VLC_TICK_INVALID)
{
- if(!CreateCurrentEdit(p_stream, p_sys->i_start_dts, p_sys->b_fragmented))
+ if(!CreateCurrentEdit(p_stream, p_sys->i_start_dts,
+ mp4mux_Is(p_sys->muxh, FRAGMENTED)))
{
block_Release( p_data );
return VLC_ENOMEM;
@@ -631,13 +620,6 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
p_stream->i_last_pts = VLC_TICK_INVALID;
}
- /* XXX: -1 to always have 2 entry for easy adding of empty SPU */
- if (p_stream->mux.i_entry_count >= p_stream->mux.i_entry_max - 2) {
- p_stream->mux.i_entry_max += 1000;
- p_stream->mux.entry = xrealloc(p_stream->mux.entry,
- p_stream->mux.i_entry_max * sizeof(mp4mux_entry_t));
- }
-
/* Set current segment ranges */
if( p_stream->i_first_dts == VLC_TICK_INVALID )
{
@@ -646,7 +628,7 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
p_sys->i_start_dts = p_stream->i_first_dts;
}
- if (p_stream->mux.fmt.i_cat != SPU_ES)
+ if (p_stream->tinfo->fmt.i_cat != SPU_ES)
{
/* Fix length of the sample */
if (block_FifoCount(p_input->p_fifo) > 0)
@@ -654,29 +636,29 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
block_t *p_next = block_FifoShow(p_input->p_fifo);
if ( p_next->i_flags & BLOCK_FLAG_DISCONTINUITY )
{ /* we have no way to know real length except by decoding */
- if ( p_stream->mux.fmt.i_cat == VIDEO_ES )
+ if ( p_stream->tinfo->fmt.i_cat == VIDEO_ES )
{
p_data->i_length = vlc_tick_from_samples(
- p_stream->mux.fmt.video.i_frame_rate_base,
- p_stream->mux.fmt.video.i_frame_rate );
+ p_stream->tinfo->fmt.video.i_frame_rate_base,
+ p_stream->tinfo->fmt.video.i_frame_rate );
if( p_data->i_flags & BLOCK_FLAG_SINGLE_FIELD )
p_data->i_length >>= 1;
msg_Dbg( p_mux, "video track %u fixup to %"PRId64" for sample %u",
- p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count );
+ p_stream->tinfo->i_track_id, p_data->i_length, p_stream->tinfo->i_samples_count );
}
- else if ( p_stream->mux.fmt.i_cat == AUDIO_ES &&
- p_stream->mux.fmt.audio.i_rate &&
+ else if ( p_stream->tinfo->fmt.i_cat == AUDIO_ES &&
+ p_stream->tinfo->fmt.audio.i_rate &&
p_data->i_nb_samples )
{
p_data->i_length = vlc_tick_from_samples(p_data->i_nb_samples,
- p_stream->mux.fmt.audio.i_rate);
+ p_stream->tinfo->fmt.audio.i_rate);
msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u",
- p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count );
+ p_stream->tinfo->i_track_id, p_data->i_length, p_stream->tinfo->i_samples_count );
}
else if ( p_data->i_length <= 0 )
{
msg_Warn( p_mux, "unknown length for track %u sample %u",
- p_stream->mux.i_track_id, p_stream->mux.i_entry_count );
+ p_stream->tinfo->i_track_id, p_stream->tinfo->i_samples_count );
p_data->i_length = 1;
}
}
@@ -700,16 +682,16 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
}
else /* SPU_ES */
{
- if (p_stream->mux.i_entry_count > 0 &&
- p_stream->mux.entry[p_stream->mux.i_entry_count-1].i_length == 0)
+ mp4mux_sample_t *p_lastsample = mp4mux_track_GetLastSample(p_stream->tinfo);
+ if (p_lastsample != NULL && p_lastsample->i_length == 0)
{
/* length of previous spu, stored in spu clearer */
int64_t i_length = dts_fb_pts( p_data ) - p_stream->i_last_dts;
if(i_length < 0)
i_length = 0;
/* Fix entry */
- p_stream->mux.entry[p_stream->mux.i_entry_count-1].i_length = i_length;
- p_stream->mux.i_read_duration += i_length;
+ p_lastsample->i_length = i_length;
+ p_stream->tinfo->i_read_duration += i_length;
}
}
@@ -719,36 +701,39 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
p_stream->i_last_pts = p_data->i_pts;
/* add index entry */
- mp4mux_entry_t *e = &p_stream->mux.entry[p_stream->mux.i_entry_count++];
- e->i_pos = p_sys->i_pos;
- e->i_size = p_data->i_buffer;
+ mp4mux_sample_t sample;
+ sample.i_pos = p_sys->i_pos;
+ sample.i_size = p_data->i_buffer;
if ( p_data->i_dts != VLC_TICK_INVALID && p_data->i_pts > p_data->i_dts )
{
- e->i_pts_dts = p_data->i_pts - p_data->i_dts;
- if ( !p_stream->mux.b_hasbframes )
- p_stream->mux.b_hasbframes = true;
+ sample.i_pts_dts = p_data->i_pts - p_data->i_dts;
+ if ( !p_stream->tinfo->b_hasbframes )
+ p_stream->tinfo->b_hasbframes = true;
}
- else e->i_pts_dts = 0;
+ else sample.i_pts_dts = 0;
- e->i_length = p_data->i_length;
- e->i_flags = p_data->i_flags;
+ sample.i_length = p_data->i_length;
+ sample.i_flags = p_data->i_flags;
/* update */
- p_stream->mux.i_read_duration += __MAX( 0, p_data->i_length );
+ p_stream->tinfo->i_read_duration += __MAX( 0, p_data->i_length );
p_stream->i_last_dts = dts_fb_pts( p_data );
/* write data */
- p_sys->i_pos += p_data->i_buffer;
- sout_AccessOutWrite(p_mux->p_access, p_data);
+ if(mp4mux_track_AddSample(p_stream->tinfo, &sample))
+ {
+ p_sys->i_pos += p_data->i_buffer;
+ sout_AccessOutWrite(p_mux->p_access, p_data);
+ }
/* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/
- if ( p_stream->mux.fmt.i_cat == SPU_ES && e->i_length > 0 )
+ if ( p_stream->tinfo->fmt.i_cat == SPU_ES && sample.i_length > 0 )
{
block_t *p_empty = NULL;
- if(p_stream->mux.fmt.i_codec == VLC_CODEC_SUBT||
- p_stream->mux.fmt.i_codec == VLC_CODEC_QTXT||
- p_stream->mux.fmt.i_codec == VLC_CODEC_TX3G)
+ if(p_stream->tinfo->fmt.i_codec == VLC_CODEC_SUBT||
+ p_stream->tinfo->fmt.i_codec == VLC_CODEC_QTXT||
+ p_stream->tinfo->fmt.i_codec == VLC_CODEC_TX3G)
{
p_empty = block_Alloc(3);
if(p_empty)
@@ -759,13 +744,13 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
p_empty->p_buffer[2] = ' ';
}
}
- else if(p_stream->mux.fmt.i_codec == VLC_CODEC_TTML)
+ else if(p_stream->tinfo->fmt.i_codec == VLC_CODEC_TTML)
{
p_empty = block_Alloc(40);
if(p_empty)
memcpy(p_empty->p_buffer, "<tt><body><div><p></p></div></body></tt>", 40);
}
- else if(p_stream->mux.fmt.i_codec == VLC_CODEC_WEBVTT)
+ else if(p_stream->tinfo->fmt.i_codec == VLC_CODEC_WEBVTT)
{
p_empty = block_Alloc(8);
if(p_empty)
@@ -773,27 +758,30 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
}
/* point to start of our empty */
- p_stream->i_last_dts += e->i_length;
+ p_stream->i_last_dts += sample.i_length;
if(p_empty)
{
/* Append a idx entry */
/* XXX: No need to grow the entry here */
- mp4mux_entry_t *e_empty = &p_stream->mux.entry[p_stream->mux.i_entry_count++];
- e_empty->i_pos = p_sys->i_pos;
- e_empty->i_size = p_empty->i_buffer;
- e_empty->i_pts_dts= 0;
- e_empty->i_length = 0; /* will add dts diff later*/
- e_empty->i_flags = 0;
-
- p_sys->i_pos += p_empty->i_buffer;
- sout_AccessOutWrite(p_mux->p_access, p_empty);
+ mp4mux_sample_t closersample;
+ closersample.i_pos = p_sys->i_pos;
+ closersample.i_size = p_empty->i_buffer;
+ closersample.i_pts_dts= 0;
+ closersample.i_length = 0; /* will add dts diff later*/
+ closersample.i_flags = 0;
+
+ if(mp4mux_track_AddSample(p_stream->tinfo, &closersample))
+ {
+ p_sys->i_pos += p_empty->i_buffer;
+ sout_AccessOutWrite(p_mux->p_access, p_empty);
+ }
}
}
/* Update the global segment/media duration */
- if( p_stream->mux.i_read_duration > p_sys->i_read_duration )
- p_sys->i_read_duration = p_stream->mux.i_read_duration;
+ if( p_stream->tinfo->i_read_duration > p_sys->i_read_duration )
+ p_sys->i_read_duration = p_stream->tinfo->i_read_duration;
return VLC_SUCCESS;
}
@@ -969,13 +957,13 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
{
/* Current segment have all same duration value, different than trex's default */
if (b_allsamelength &&
- p_stream->read.p_first->p_block->i_length != p_stream->mux.i_trex_default_length &&
+ p_stream->read.p_first->p_block->i_length != p_stream->tinfo->i_trex_default_length &&
p_stream->read.p_first->p_block->i_length)
i_tfhd_flags |= MP4_TFHD_DFLT_SAMPLE_DURATION;
/* Current segment have all same size value, different than trex's default */
if (b_allsamesize &&
- p_stream->read.p_first->p_block->i_buffer != p_stream->mux.i_trex_default_size &&
+ p_stream->read.p_first->p_block->i_buffer != p_stream->tinfo->i_trex_default_size &&
p_stream->read.p_first->p_block->i_buffer)
i_tfhd_flags |= MP4_TFHD_DFLT_SAMPLE_SIZE;
}
@@ -992,11 +980,11 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
bo_free(traf);
continue;
}
- bo_add_32be(tfhd, p_stream->mux.i_track_id);
+ bo_add_32be(tfhd, p_stream->tinfo->i_track_id);
/* set the local sample duration default */
if (i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION)
- bo_add_32be(tfhd, samples_from_vlc_tick(p_stream->read.p_first->p_block->i_length, p_stream->mux.i_timescale));
+ bo_add_32be(tfhd, samples_from_vlc_tick(p_stream->read.p_first->p_block->i_length, p_stream->tinfo->i_timescale));
/* set the local sample size default */
if (i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE)
@@ -1011,7 +999,7 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
bo_free(traf);
continue;
}
- bo_add_64be(tfdt, samples_from_vlc_tick(p_stream->i_written_duration, p_stream->mux.i_timescale) );
+ bo_add_64be(tfdt, samples_from_vlc_tick(p_stream->i_written_duration, p_stream->tinfo->i_timescale) );
box_gather(traf, tfdt);
/* *** add /moof/traf/trun *** */
@@ -1023,14 +1011,14 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
i_trun_flags |= MP4_TRUN_FIRST_FLAGS;
if (!b_allsamelength ||
- ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION) && p_stream->mux.i_trex_default_length == 0 ))
+ ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION) && p_stream->tinfo->i_trex_default_length == 0 ))
i_trun_flags |= MP4_TRUN_SAMPLE_DURATION;
if (!b_allsamesize ||
- ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE) && p_stream->mux.i_trex_default_size == 0 ))
+ ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE) && p_stream->tinfo->i_trex_default_size == 0 ))
i_trun_flags |= MP4_TRUN_SAMPLE_SIZE;
- if (p_stream->mux.b_hasbframes)
+ if (p_stream->tinfo->b_hasbframes)
i_trun_flags |= MP4_TRUN_SAMPLE_TIME_OFFSET;
if (i_fixupoffset == 0)
@@ -1071,7 +1059,7 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
DEQUEUE_ENTRY(p_stream->read, p_entry);
if (i_trun_flags & MP4_TRUN_SAMPLE_DURATION)
- bo_add_32be(trun, samples_from_vlc_tick(p_entry->p_block->i_length, p_stream->mux.i_timescale)); // sample duration
+ bo_add_32be(trun, samples_from_vlc_tick(p_entry->p_block->i_length, p_stream->tinfo->i_timescale)); // sample duration
if (i_trun_flags & MP4_TRUN_SAMPLE_SIZE)
bo_add_32be(trun, p_entry->p_block->i_buffer); // sample size
@@ -1084,7 +1072,7 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
{
i_diff = p_entry->p_block->i_pts - p_entry->p_block->i_dts;
}
- bo_add_32be(trun, samples_from_vlc_tick(i_diff, p_stream->mux.i_timescale)); // ctts
+ bo_add_32be(trun, samples_from_vlc_tick(i_diff, p_stream->tinfo->i_timescale)); // ctts
}
*pi_mdat_total_size += p_entry->p_block->i_buffer;
@@ -1095,7 +1083,7 @@ static bo_t *GetMoofBox(sout_mux_t *p_mux, size_t *pi_mdat_total_size,
/* Add keyframe entry if needed */
if (p_stream->b_hasiframes && (p_entry->p_block->i_flags & BLOCK_FLAG_TYPE_I) &&
- (p_stream->mux.fmt.i_cat == VIDEO_ES || p_stream->mux.fmt.i_cat == AUDIO_ES))
+ (p_stream->tinfo->fmt.i_cat == VIDEO_ES || p_stream->tinfo->fmt.i_cat == AUDIO_ES))
{
AddKeyframeEntry(p_stream, i_write_pos, i_trak, i_sample, i_time);
}
@@ -1178,7 +1166,7 @@ static bo_t *GetMfraBox(sout_mux_t *p_mux)
{
bo_t *tfra = box_full_new("tfra", 0, 0x0);
if (!tfra) continue;
- bo_add_32be(tfra, p_stream->mux.i_track_id);
+ bo_add_32be(tfra, p_stream->tinfo->i_track_id);
bo_add_32be(tfra, 0x3); // reserved + lengths (1,1,4)=>(0,0,3)
bo_add_32be(tfra, p_stream->i_indexentries);
for(uint32_t i_index=0; i_index<p_stream->i_indexentries; i_index++)
@@ -1206,36 +1194,19 @@ static bo_t *GetMfraBox(sout_mux_t *p_mux)
return mfra;
}
-static bo_t *BuildMoov(sout_mux_t *p_mux)
-{
- sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
- const bool b_stco64 = (p_sys->i_pos >= (((uint64_t)0x1) << 32));
- /* map our structs */
- mp4mux_trackinfo_t **pp_infos = NULL;
- if(p_sys->i_nb_streams) /* Trackless moov ? */
- {
- pp_infos = vlc_alloc(p_sys->i_nb_streams, sizeof(mp4mux_trackinfo_t *));
- if(!pp_infos)
- return NULL;
- for(unsigned int i=0; i<p_sys->i_nb_streams; i++)
- pp_infos[i] = &p_sys->pp_streams[i]->mux;
- }
- bo_t *p_moov = mp4mux_GetMoovBox(VLC_OBJECT(p_mux), pp_infos, p_sys->i_nb_streams, 0,
- p_sys->b_fragmented, p_sys->b_mov, p_sys->b_64_ext, b_stco64);
- free(pp_infos);
- return p_moov;
-}
-
static void FlushHeader(sout_mux_t *p_mux)
{
sout_mux_sys_t *p_sys = (sout_mux_sys_t*) p_mux->p_sys;
+ if(p_sys->i_pos >= (((uint64_t)0x1) << 32))
+ mp4mux_Set64BitExt(p_sys->muxh);
+
/* Now add ftyp header */
bo_t *ftyp = mp4mux_GetFtyp(MAJOR_isom, 0, NULL, 0);
if(!ftyp)
return;
- bo_t *moov = BuildMoov(p_mux);
+ bo_t *moov = mp4mux_GetMoov(p_sys->muxh, VLC_OBJECT(p_mux), 0);
/* merge into a single block */
box_gather(ftyp, moov);
@@ -1261,7 +1232,7 @@ static void WriteFragments(sout_mux_t *p_mux, bool b_flush)
{
mp4_stream_t *p_stream = p_sys->pp_streams[j];
if(CreateCurrentEdit(p_stream, p_sys->i_start_dts, true))
- DebugEdits(p_mux, p_stream);
+ mp4mux_track_DebugEdits(VLC_OBJECT(p_mux), p_stream->tinfo);
}
}
@@ -1275,8 +1246,8 @@ static void WriteFragments(sout_mux_t *p_mux, bool b_flush)
/* set a barrier so we try to align to keyframe */
if (p_stream->b_hasiframes &&
p_stream->i_last_iframe_time > p_stream->i_written_duration &&
- (p_stream->mux.fmt.i_cat == VIDEO_ES ||
- p_stream->mux.fmt.i_cat == AUDIO_ES) )
+ (p_stream->tinfo->fmt.i_cat == VIDEO_ES ||
+ p_stream->tinfo->fmt.i_cat == AUDIO_ES) )
{
i_barrier_time = __MIN(i_barrier_time, p_stream->i_last_iframe_time);
}
@@ -1317,27 +1288,27 @@ static void WriteFragments(sout_mux_t *p_mux, bool b_flush)
* This is the end boundary case. */
static void LengthLocalFixup(sout_mux_t *p_mux, const mp4_stream_t *p_stream, block_t *p_entrydata)
{
- if ( p_stream->mux.fmt.i_cat == VIDEO_ES && p_stream->mux.fmt.video.i_frame_rate )
+ if ( p_stream->tinfo->fmt.i_cat == VIDEO_ES && p_stream->tinfo->fmt.video.i_frame_rate )
{
p_entrydata->i_length = vlc_tick_from_samples(
- p_stream->mux.fmt.video.i_frame_rate_base,
- p_stream->mux.fmt.video.i_frame_rate);
+ p_stream->tinfo->fmt.video.i_frame_rate_base,
+ p_stream->tinfo->fmt.video.i_frame_rate);
msg_Dbg(p_mux, "video track %d fixup to %"PRId64" for sample %u",
- p_stream->mux.i_track_id, p_entrydata->i_length, p_stream->mux.i_entry_count - 1);
+ p_stream->tinfo->i_track_id, p_entrydata->i_length, p_stream->tinfo->i_samples_count - 1);
}
- else if (p_stream->mux.fmt.i_cat == AUDIO_ES &&
- p_stream->mux.fmt.audio.i_rate &&
- p_entrydata->i_nb_samples && p_stream->mux.fmt.audio.i_rate)
+ else if (p_stream->tinfo->fmt.i_cat == AUDIO_ES &&
+ p_stream->tinfo->fmt.audio.i_rate &&
+ p_entrydata->i_nb_samples && p_stream->tinfo->fmt.audio.i_rate)
{
p_entrydata->i_length = vlc_tick_from_samples(p_entrydata->i_nb_samples,
- p_stream->mux.fmt.audio.i_rate);
+ p_stream->tinfo->fmt.audio.i_rate);
msg_Dbg(p_mux, "audio track %d fixup to %"PRId64" for sample %u",
- p_stream->mux.i_track_id, p_entrydata->i_length, p_stream->mux.i_entry_count - 1);
+ p_stream->tinfo->i_track_id, p_entrydata->i_length, p_stream->tinfo->i_samples_count - 1);
}
else
{
msg_Warn(p_mux, "unknown length for track %d sample %u",
- p_stream->mux.i_track_id, p_stream->mux.i_entry_count - 1);
+ p_stream->tinfo->i_track_id, p_stream->tinfo->i_samples_count - 1);
p_entrydata->i_length = 1;
}
}
@@ -1367,11 +1338,10 @@ static void CleanupFrag(sout_mux_sys_t *p_sys)
p_stream->towrite.p_first = p_next;
}
free(p_stream->p_indexentries);
-
- mp4mux_trackinfo_Clear(&p_stream->mux);
free(p_stream);
}
TAB_CLEAN(p_sys->i_nb_streams, p_sys->pp_streams);
+ mp4mux_Delete(p_sys->muxh);
free(p_sys);
}
@@ -1464,15 +1434,15 @@ static int MuxFrag(sout_mux_t *p_mux)
p_stream->p_held_entry = NULL;
if (p_stream->b_hasiframes && (p_heldblock->i_flags & BLOCK_FLAG_TYPE_I) &&
- p_stream->mux.i_read_duration - p_sys->i_written_duration < FRAGMENT_LENGTH)
+ p_stream->tinfo->i_read_duration - p_sys->i_written_duration < FRAGMENT_LENGTH)
{
/* Flag the last iframe time, we'll use it as boundary so it will start
next fragment */
- p_stream->i_last_iframe_time = p_stream->mux.i_read_duration;
+ p_stream->i_last_iframe_time = p_stream->tinfo->i_read_duration;
}
/* update buffered time */
- p_stream->mux.i_read_duration += __MAX(0, p_heldblock->i_length);
+ p_stream->tinfo->i_read_duration += __MAX(0, p_heldblock->i_length);
}
@@ -1485,26 +1455,26 @@ static int MuxFrag(sout_mux_t *p_mux)
p_stream->p_held_entry->i_run = p_stream->i_current_run;
p_stream->p_held_entry->p_next = NULL;
- if (p_stream->mux.fmt.i_cat == VIDEO_ES )
+ if (p_stream->tinfo->fmt.i_cat == VIDEO_ES )
{
if (!p_stream->b_hasiframes && (p_currentblock->i_flags & BLOCK_FLAG_TYPE_I))
p_stream->b_hasiframes = true;
- if (!p_stream->mux.b_hasbframes && p_currentblock->i_dts != VLC_TICK_INVALID &&
+ if (!p_stream->tinfo->b_hasbframes && p_currentblock->i_dts != VLC_TICK_INVALID &&
p_currentblock->i_pts > p_currentblock->i_dts)
- p_stream->mux.b_hasbframes = true;
+ p_stream->tinfo->b_hasbframes = true;
}
/* Update the global fragment/media duration */
- vlc_tick_t i_min_read_duration = p_stream->mux.i_read_duration;
+ vlc_tick_t i_min_read_duration = p_stream->tinfo->i_read_duration;
vlc_tick_t i_min_written_duration = p_stream->i_written_duration;
for (unsigned int i=0; i<p_sys->i_nb_streams; i++)
{
const mp4_stream_t *p_s = p_sys->pp_streams[i];
- if (p_s->mux.fmt.i_cat != VIDEO_ES && p_s->mux.fmt.i_cat != AUDIO_ES)
+ if (p_s->tinfo->fmt.i_cat != VIDEO_ES && p_s->tinfo->fmt.i_cat != AUDIO_ES)
continue;
- if (p_s->mux.i_read_duration < i_min_read_duration)
- i_min_read_duration = p_s->mux.i_read_duration;
+ if (p_s->tinfo->i_read_duration < i_min_read_duration)
+ i_min_read_duration = p_s->tinfo->i_read_duration;
if (p_s->i_written_duration < i_min_written_duration)
i_min_written_duration = p_s->i_written_duration;
More information about the vlc-commits
mailing list