[vlc-commits] mux: mp4: privatize track info

Francois Cartegnie git at videolan.org
Mon Oct 29 16:44:09 CET 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Oct 29 10:23:11 2018 +0100| [41c2da8107d591080c66ab1aeb82adc9ae621328] | committer: Francois Cartegnie

mux: mp4: privatize track info

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=41c2da8107d591080c66ab1aeb82adc9ae621328
---

 .../demux/smooth/playlist/ForgedInitSegment.cpp    |   6 +-
 modules/mux/mp4/libmp4mux.c                        | 150 ++++++++++++++++++--
 modules/mux/mp4/libmp4mux.h                        |  87 +++++-------
 modules/mux/mp4/mp4.c                              | 157 ++++++++++++---------
 4 files changed, 262 insertions(+), 138 deletions(-)

diff --git a/modules/demux/smooth/playlist/ForgedInitSegment.cpp b/modules/demux/smooth/playlist/ForgedInitSegment.cpp
index 8375e0a243..a4fa11e258 100644
--- a/modules/demux/smooth/playlist/ForgedInitSegment.cpp
+++ b/modules/demux/smooth/playlist/ForgedInitSegment.cpp
@@ -283,11 +283,7 @@ block_t * ForgedInitSegment::buildMoovBox()
                                      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;
-            }
+                mp4mux_track_ForceDuration(p_track, duration.Get());
         }
 
         box = mp4mux_GetMoov(muxh, NULL, trackTimescale.ToTime(duration.Get()));
diff --git a/modules/mux/mp4/libmp4mux.c b/modules/mux/mp4/libmp4mux.c
index 88dfaa348c..d4cc8218c1 100644
--- a/modules/mux/mp4/libmp4mux.c
+++ b/modules/mux/mp4/libmp4mux.c
@@ -39,6 +39,38 @@
 #include <assert.h>
 #include <time.h>
 
+struct mp4mux_trackinfo_t
+{
+    unsigned i_track_id;
+    es_format_t   fmt;
+
+    /* index */
+    unsigned int i_samples_count;
+    unsigned int i_samples_max;
+    mp4mux_sample_t *samples;
+
+    /* XXX: needed for other codecs too, see lavf */
+    struct
+    {
+        size_t   i_data;
+        uint8_t *p_data;
+    } sample_priv;
+
+    /* stats */
+    vlc_tick_t   i_read_duration;
+    uint32_t     i_timescale;
+    bool         b_hasbframes;
+
+    /* frags */
+    vlc_tick_t   i_trex_default_length;
+    uint32_t     i_trex_default_size;
+
+    /* edit list */
+    unsigned int i_edits_count;
+    mp4mux_edit_t *p_edits;
+
+};
+
 struct mp4mux_handle_t
 {
     unsigned options;
@@ -60,8 +92,7 @@ static bool mp4mux_trackinfo_Init(mp4mux_trackinfo_t *p_stream, unsigned i_id,
 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);
+    mp4mux_track_SetSamplePriv(p_stream, NULL, 0);
     free(p_stream->samples);
     free(p_stream->p_edits);
 }
@@ -77,7 +108,6 @@ mp4mux_trackinfo_t * mp4mux_track_Add(mp4mux_handle_t *h, unsigned id,
     }
     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);
@@ -129,16 +159,102 @@ bool mp4mux_track_AddSample(mp4mux_trackinfo_t *t, const mp4mux_sample_t *entry)
         t->i_samples_max += 1000;
     }
     t->samples[t->i_samples_count++] = *entry;
+    if(!t->b_hasbframes && entry->i_pts_dts != 0)
+        t->b_hasbframes = true;
+    t->i_read_duration += __MAX(0, entry->i_length);
     return true;
 }
 
-mp4mux_sample_t *mp4mux_track_GetLastSample(mp4mux_trackinfo_t *t)
+const mp4mux_sample_t *mp4mux_track_GetLastSample(const mp4mux_trackinfo_t *t)
 {
     if(t->i_samples_count)
         return &t->samples[t->i_samples_count - 1];
     else return NULL;
 }
 
+unsigned mp4mux_track_GetSampleCount(const mp4mux_trackinfo_t *t)
+{
+    return t->i_samples_count;
+}
+
+void mp4mux_track_UpdateLastSample(mp4mux_trackinfo_t *t,
+                                   const mp4mux_sample_t *entry)
+{
+    if(t->i_samples_count)
+    {
+        mp4mux_sample_t *e = &t->samples[t->i_samples_count - 1];
+        t->i_read_duration -= e->i_length;
+        t->i_read_duration += entry->i_length;
+        *e = *entry;
+    }
+}
+
+vlc_tick_t mp4mux_track_GetDefaultSampleDuration(const mp4mux_trackinfo_t *t)
+{
+    return t->i_trex_default_length;
+}
+
+uint32_t mp4mux_track_GetDefaultSampleSize(const mp4mux_trackinfo_t *t)
+{
+    return t->i_trex_default_size;
+}
+
+bool mp4mux_track_HasBFrames(const mp4mux_trackinfo_t *t)
+{
+    return t->b_hasbframes;
+}
+
+void mp4mux_track_SetHasBFrames(mp4mux_trackinfo_t *t)
+{
+    t->b_hasbframes = true;
+}
+
+uint32_t mp4mux_track_GetTimescale(const mp4mux_trackinfo_t *t)
+{
+    return t->i_timescale;
+}
+
+vlc_tick_t mp4mux_track_GetDuration(const mp4mux_trackinfo_t *t)
+{
+    return t->i_read_duration;
+}
+
+void mp4mux_track_ForceDuration(mp4mux_trackinfo_t *t, vlc_tick_t d)
+{
+    t->i_read_duration = d;
+}
+
+uint32_t mp4mux_track_GetID(const mp4mux_trackinfo_t *t)
+{
+    return t->i_track_id;
+}
+
+void mp4mux_track_SetSamplePriv(mp4mux_trackinfo_t *t,
+                                const uint8_t *p_data, size_t i_data)
+{
+    if(t->sample_priv.p_data)
+    {
+        free(t->sample_priv.p_data);
+        t->sample_priv.p_data = NULL;
+        t->sample_priv.i_data = 0;
+    }
+
+    if(p_data && i_data)
+    {
+        t->sample_priv.p_data = malloc(i_data);
+        if(i_data)
+        {
+            memcpy(t->sample_priv.p_data, p_data, i_data);
+            t->sample_priv.i_data = i_data;
+        }
+    }
+}
+
+bool mp4mux_track_HasSamplePriv(const mp4mux_trackinfo_t *t)
+{
+    return t->sample_priv.i_data != 0;
+}
+
 void mp4mux_ShiftSamples(mp4mux_handle_t *h, int64_t offset)
 {
     for(size_t i_track = 0; i_track < vlc_array_count(&h->tracks); i_track++)
@@ -495,13 +611,14 @@ static bo_t *GetWaveTag(mp4mux_trackinfo_t *p_track)
     return wave;
 }
 
-static bo_t *GetDec3Tag(es_format_t *p_fmt, block_t *a52_frame)
+static bo_t *GetDec3Tag(es_format_t *p_fmt,
+                        const uint8_t *p_data, size_t i_data)
 {
-    if (!a52_frame)
+    if (!i_data)
         return NULL;
 
     bs_t s;
-    bs_write_init(&s, a52_frame->p_buffer, sizeof(a52_frame->i_buffer));
+    bs_init(&s, p_data, i_data);
     bs_skip(&s, 16); // syncword
 
     uint8_t fscod, bsid, bsmod, acmod, lfeon, strmtyp;
@@ -596,7 +713,7 @@ static bo_t *GetDec3Tag(es_format_t *p_fmt, block_t *a52_frame)
         bsmod = bs_read(&s, 3);
 
     uint8_t mp4_eac3_header[5] = {0};
-    bs_init(&s, mp4_eac3_header, sizeof(mp4_eac3_header));
+    bs_write_init(&s, mp4_eac3_header, sizeof(mp4_eac3_header));
 
     int data_rate = p_fmt->i_bitrate / 1000;
     bs_write(&s, 13, data_rate);
@@ -617,9 +734,9 @@ static bo_t *GetDec3Tag(es_format_t *p_fmt, block_t *a52_frame)
     return dec3;
 }
 
-static bo_t *GetDac3Tag(block_t *a52_frame)
+static bo_t *GetDac3Tag(const uint8_t *p_data, size_t i_data)
 {
-    if (!a52_frame)
+    if (!i_data)
         return NULL;
 
     bo_t *dac3 = box_new("dac3");
@@ -627,7 +744,7 @@ static bo_t *GetDac3Tag(block_t *a52_frame)
         return NULL;
 
     bs_t s;
-    bs_init(&s, a52_frame->p_buffer, sizeof(a52_frame->i_buffer));
+    bs_init(&s, p_data, i_data);
 
     uint8_t fscod, bsid, bsmod, acmod, lfeon, frmsizecod;
 
@@ -650,7 +767,7 @@ static bo_t *GetDac3Tag(block_t *a52_frame)
     lfeon = bs_read1(&s);
 
     uint8_t mp4_a52_header[3];
-    bs_init(&s, mp4_a52_header, sizeof(mp4_a52_header));
+    bs_write_init(&s, mp4_a52_header, sizeof(mp4_a52_header));
 
     bs_write(&s, 2, fscod);
     bs_write(&s, 5, bsid);
@@ -1085,9 +1202,9 @@ static bo_t *GetSounBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
         else if (codec == VLC_CODEC_AMR_NB)
             box = GetDamrTag(&p_track->fmt);
         else if (codec == VLC_CODEC_A52)
-            box = GetDac3Tag(p_track->a52_frame);
+            box = GetDac3Tag(p_track->sample_priv.p_data, p_track->sample_priv.i_data);
         else if (codec == VLC_CODEC_EAC3)
-            box = GetDec3Tag(&p_track->fmt, p_track->a52_frame);
+            box = GetDec3Tag(&p_track->fmt, p_track->sample_priv.p_data, p_track->sample_priv.i_data);
         else if (codec == VLC_CODEC_WMAP)
             box = GetWaveFormatExTag(&p_track->fmt, "wfex");
         else
@@ -1991,6 +2108,11 @@ bo_t * mp4mux_GetMoov(mp4mux_handle_t *h, vlc_object_t *p_obj, vlc_tick_t i_dura
                     p_stream->i_trex_default_length = p_stream->samples[0].i_length;
                     p_stream->i_trex_default_size = p_stream->samples[0].i_size;
                 }
+                else
+                {
+                    p_stream->i_trex_default_length = 1;
+                    p_stream->i_trex_default_size = 1;
+                }
 
                 /* *** add /mvex/trex *** */
                 bo_t *trex = box_full_new("trex", 0, 0);
diff --git a/modules/mux/mp4/libmp4mux.h b/modules/mux/mp4/libmp4mux.h
index 1da7e88e1b..025bc8e8a8 100644
--- a/modules/mux/mp4/libmp4mux.h
+++ b/modules/mux/mp4/libmp4mux.h
@@ -25,52 +25,7 @@
 #include <vlc_boxes.h>
 
 typedef struct mp4mux_handle_t mp4mux_handle_t;
-
-typedef struct
-{
-    uint64_t i_pos;
-    int      i_size;
-
-    vlc_tick_t  i_pts_dts;
-    vlc_tick_t  i_length;
-    unsigned int i_flags;
-} mp4mux_sample_t;
-
-typedef struct
-{
-    vlc_tick_t i_duration;
-    vlc_tick_t i_start_time;
-    vlc_tick_t i_start_offset;
-} mp4mux_edit_t;
-
-typedef struct
-{
-    unsigned i_track_id;
-    es_format_t   fmt;
-
-    /* index */
-    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;
-
-    /* stats */
-    vlc_tick_t   i_read_duration;
-    uint32_t     i_timescale;
-    vlc_tick_t   i_firstdts; /* the really first packet */
-    bool         b_hasbframes;
-
-    /* frags */
-    vlc_tick_t   i_trex_default_length;
-    uint32_t     i_trex_default_size;
-
-    /* edit list */
-    unsigned int i_edits_count;
-    mp4mux_edit_t *p_edits;
-
-} mp4mux_trackinfo_t;
+typedef struct mp4mux_trackinfo_t mp4mux_trackinfo_t;
 
 enum mp4mux_options
 {
@@ -86,16 +41,46 @@ 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);
+/* Track properties */
+uint32_t   mp4mux_track_GetID(const mp4mux_trackinfo_t *);
+uint32_t   mp4mux_track_GetTimescale(const mp4mux_trackinfo_t *);
+vlc_tick_t mp4mux_track_GetDuration(const mp4mux_trackinfo_t *);
+void       mp4mux_track_ForceDuration(mp4mux_trackinfo_t *, vlc_tick_t); /* Used by frag */
+bool       mp4mux_track_HasBFrames(const mp4mux_trackinfo_t *);
+void       mp4mux_track_SetHasBFrames(mp4mux_trackinfo_t *);
+void       mp4mux_track_SetSamplePriv(mp4mux_trackinfo_t *, const uint8_t *, size_t);
+bool       mp4mux_track_HasSamplePriv(const mp4mux_trackinfo_t *);
+vlc_tick_t mp4mux_track_GetDefaultSampleDuration(const mp4mux_trackinfo_t *);
+uint32_t   mp4mux_track_GetDefaultSampleSize(const mp4mux_trackinfo_t *);
+
 /* ELST */
-bool mp4mux_track_AddEdit(mp4mux_trackinfo_t *, const mp4mux_edit_t *);
+typedef struct
+{
+    vlc_tick_t i_duration;
+    vlc_tick_t i_start_time;
+    vlc_tick_t i_start_offset;
+} mp4mux_edit_t;
+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 *);
+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 *);
+typedef struct
+{
+    uint64_t i_pos;
+    int      i_size;
+
+    vlc_tick_t  i_pts_dts;
+    vlc_tick_t  i_length;
+    unsigned int i_flags;
+} mp4mux_sample_t;
+bool       mp4mux_track_AddSample(mp4mux_trackinfo_t *, const mp4mux_sample_t *);
+const      mp4mux_sample_t *mp4mux_track_GetLastSample(const mp4mux_trackinfo_t *);
+unsigned   mp4mux_track_GetSampleCount(const mp4mux_trackinfo_t *);
+void       mp4mux_track_UpdateLastSample(mp4mux_trackinfo_t *, const mp4mux_sample_t *);
 
 bo_t *mp4mux_GetMoov(mp4mux_handle_t *, vlc_object_t *, vlc_tick_t i_movie_duration);
-void mp4mux_ShiftSamples(mp4mux_handle_t *, int64_t offset);
+void  mp4mux_ShiftSamples(mp4mux_handle_t *, int64_t offset);
 
 /* old */
 
diff --git a/modules/mux/mp4/mp4.c b/modules/mux/mp4/mp4.c
index 1961cc7ca4..b64f430881 100644
--- a/modules/mux/mp4/mp4.c
+++ b/modules/mux/mp4/mp4.c
@@ -128,6 +128,7 @@ typedef struct mp4_fragqueue_t
 typedef struct
 {
     mp4mux_trackinfo_t *tinfo;
+    const es_format_t *p_fmt;
 
     /* index */
     vlc_tick_t   i_length_neg;
@@ -480,6 +481,7 @@ static int AddStream(sout_mux_t *p_mux, sout_input_t *p_input)
         return VLC_ENOMEM;
     }
 
+    p_stream->p_fmt = p_input->p_fmt;
     p_stream->i_length_neg  = 0;
     p_stream->i_last_dts    = VLC_TICK_INVALID;
     p_stream->i_last_pts    = VLC_TICK_INVALID;
@@ -538,7 +540,8 @@ static bool CreateCurrentEdit(mp4_stream_t *p_stream, vlc_tick_t i_mux_start_dts
     if(p_lastedit != NULL && b_fragmented)
         return true;
 
-    if(p_stream->tinfo->i_samples_count == 0)
+    const mp4mux_sample_t *p_lastsample = mp4mux_track_GetLastSample(p_stream->tinfo);
+    if(p_lastsample == NULL)
         return true;
 
     mp4mux_edit_t newedit;
@@ -564,8 +567,8 @@ static bool CreateCurrentEdit(mp4_stream_t *p_stream, vlc_tick_t i_mux_start_dts
             newedit.i_duration = p_stream->i_last_pts - p_stream->i_first_dts;
         else
             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;
+
+        newedit.i_duration += p_lastsample->i_length;
     }
 
     return mp4mux_track_AddEdit(p_stream->tinfo, &newedit);
@@ -577,7 +580,7 @@ static block_t * BlockDequeue(sout_input_t *p_input, mp4_stream_t *p_stream)
     if(unlikely(!p_block))
         return NULL;
 
-    switch(p_stream->tinfo->fmt.i_codec)
+    switch(p_stream->p_fmt->i_codec)
     {
         case VLC_CODEC_AV1:
             p_block = AV1_Pack_Sample(p_block);
@@ -591,8 +594,12 @@ 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->tinfo->a52_frame == NULL && p_block->i_buffer >= 8)
-                p_stream->tinfo->a52_frame = block_Duplicate(p_block);
+            if(!mp4mux_track_HasSamplePriv(p_stream->tinfo) &&
+               p_block->i_buffer >= 8)
+            {
+                mp4mux_track_SetSamplePriv(p_stream->tinfo,
+                                           p_block->p_buffer, p_block->i_buffer);
+            }
             break;
         default:
             break;
@@ -615,7 +622,8 @@ 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->tinfo->i_samples_count)
+    if (p_data->i_flags & BLOCK_FLAG_DISCONTINUITY &&
+        mp4mux_track_GetLastSample(p_stream->tinfo) != NULL)
     {
         if(p_stream->i_first_dts != VLC_TICK_INVALID)
         {
@@ -641,7 +649,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->tinfo->fmt.i_cat != SPU_ES)
+    if (p_stream->p_fmt->i_cat != SPU_ES)
     {
         /* Fix length of the sample */
         if (block_FifoCount(p_input->p_fifo) > 0)
@@ -649,29 +657,32 @@ 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->tinfo->fmt.i_cat == VIDEO_ES )
+                if ( p_stream->p_fmt->i_cat == VIDEO_ES )
                 {
                     p_data->i_length = vlc_tick_from_samples(
-                            p_stream->tinfo->fmt.video.i_frame_rate_base,
-                            p_stream->tinfo->fmt.video.i_frame_rate );
+                            p_stream->p_fmt->video.i_frame_rate_base,
+                            p_stream->p_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->tinfo->i_track_id, p_data->i_length, p_stream->tinfo->i_samples_count );
+                             mp4mux_track_GetID(p_stream->tinfo), p_data->i_length,
+                             mp4mux_track_GetSampleCount(p_stream->tinfo) );
                 }
-                else if ( p_stream->tinfo->fmt.i_cat == AUDIO_ES &&
-                          p_stream->tinfo->fmt.audio.i_rate &&
+                else if ( p_stream->p_fmt->i_cat == AUDIO_ES &&
+                          p_stream->p_fmt->audio.i_rate &&
                           p_data->i_nb_samples )
                 {
                     p_data->i_length = vlc_tick_from_samples(p_data->i_nb_samples,
-                            p_stream->tinfo->fmt.audio.i_rate);
+                            p_stream->p_fmt->audio.i_rate);
                     msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u",
-                             p_stream->tinfo->i_track_id, p_data->i_length, p_stream->tinfo->i_samples_count );
+                             mp4mux_track_GetID(p_stream->tinfo), p_data->i_length,
+                             mp4mux_track_GetSampleCount(p_stream->tinfo) );
                 }
                 else if ( p_data->i_length <= 0 )
                 {
                     msg_Warn( p_mux, "unknown length for track %u sample %u",
-                              p_stream->tinfo->i_track_id, p_stream->tinfo->i_samples_count );
+                              mp4mux_track_GetID(p_stream->tinfo),
+                              mp4mux_track_GetSampleCount(p_stream->tinfo) );
                     p_data->i_length = 1;
                 }
             }
@@ -695,16 +706,17 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
     }
     else /* SPU_ES */
     {
-        mp4mux_sample_t *p_lastsample = mp4mux_track_GetLastSample(p_stream->tinfo);
+        const mp4mux_sample_t *p_lastsample = mp4mux_track_GetLastSample(p_stream->tinfo);
         if (p_lastsample != NULL && p_lastsample->i_length == 0)
         {
+            mp4mux_sample_t updated = *p_lastsample;
             /* 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_lastsample->i_length = i_length;
-            p_stream->tinfo->i_read_duration += i_length;
+            updated.i_length = i_length;
+            mp4mux_track_UpdateLastSample(p_stream->tinfo, &updated);
         }
     }
 
@@ -719,18 +731,14 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
     sample.i_size   = p_data->i_buffer;
 
     if ( p_data->i_dts != VLC_TICK_INVALID && p_data->i_pts > p_data->i_dts )
-    {
         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 sample.i_pts_dts = 0;
+    else
+        sample.i_pts_dts = 0;
 
     sample.i_length = p_data->i_length;
     sample.i_flags  = p_data->i_flags;
 
     /* update */
-    p_stream->tinfo->i_read_duration += __MAX( 0, p_data->i_length );
     p_stream->i_last_dts = dts_fb_pts( p_data );
 
     /* write data */
@@ -741,12 +749,12 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
     }
 
     /* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/
-    if ( p_stream->tinfo->fmt.i_cat == SPU_ES && sample.i_length > 0 )
+    if ( p_stream->p_fmt->i_cat == SPU_ES && sample.i_length > 0 )
     {
         block_t *p_empty = NULL;
-        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)
+        if(p_stream->p_fmt->i_codec == VLC_CODEC_SUBT||
+           p_stream->p_fmt->i_codec == VLC_CODEC_QTXT||
+           p_stream->p_fmt->i_codec == VLC_CODEC_TX3G)
         {
             p_empty = block_Alloc(3);
             if(p_empty)
@@ -757,13 +765,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->tinfo->fmt.i_codec == VLC_CODEC_TTML)
+        else if(p_stream->p_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->tinfo->fmt.i_codec == VLC_CODEC_WEBVTT)
+        else if(p_stream->p_fmt->i_codec == VLC_CODEC_WEBVTT)
         {
             p_empty = block_Alloc(8);
             if(p_empty)
@@ -793,8 +801,8 @@ static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_s
     }
 
     /* Update the global segment/media duration */
-    if( p_stream->tinfo->i_read_duration > p_sys->i_read_duration )
-        p_sys->i_read_duration = p_stream->tinfo->i_read_duration;
+    if( mp4mux_track_GetDuration(p_stream->tinfo) > p_sys->i_read_duration )
+        p_sys->i_read_duration = mp4mux_track_GetDuration(p_stream->tinfo);
 
     return VLC_SUCCESS;
 }
@@ -970,13 +978,15 @@ 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->tinfo->i_trex_default_length &&
+                p_stream->read.p_first->p_block->i_length !=
+                    mp4mux_track_GetDefaultSampleDuration(p_stream->tinfo) &&
                 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->tinfo->i_trex_default_size &&
+                p_stream->read.p_first->p_block->i_buffer !=
+                    mp4mux_track_GetDefaultSampleSize(p_stream->tinfo) &&
                 p_stream->read.p_first->p_block->i_buffer)
                     i_tfhd_flags |= MP4_TFHD_DFLT_SAMPLE_SIZE;
         }
@@ -993,11 +1003,12 @@ 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->tinfo->i_track_id);
+        bo_add_32be(tfhd, mp4mux_track_GetID(p_stream->tinfo));
 
         /* 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->tinfo->i_timescale));
+            bo_add_32be(tfhd, samples_from_vlc_tick(p_stream->read.p_first->p_block->i_length,
+                                                    mp4mux_track_GetTimescale(p_stream->tinfo)));
 
         /* set the local sample size default */
         if (i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE)
@@ -1012,7 +1023,8 @@ 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->tinfo->i_timescale) );
+        bo_add_64be(tfdt, samples_from_vlc_tick(p_stream->i_written_duration,
+                                                mp4mux_track_GetTimescale(p_stream->tinfo)) );
         box_gather(traf, tfdt);
 
         /* *** add /moof/traf/trun *** */
@@ -1024,14 +1036,16 @@ 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->tinfo->i_trex_default_length == 0 ))
+                ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_DURATION) &&
+                    mp4mux_track_GetDefaultSampleDuration(p_stream->tinfo) == 0 ))
                 i_trun_flags |= MP4_TRUN_SAMPLE_DURATION;
 
             if (!b_allsamesize ||
-                ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE) && p_stream->tinfo->i_trex_default_size == 0 ))
+                ( !(i_tfhd_flags & MP4_TFHD_DFLT_SAMPLE_SIZE) &&
+                  mp4mux_track_GetDefaultSampleSize(p_stream->tinfo) == 0 ))
                 i_trun_flags |= MP4_TRUN_SAMPLE_SIZE;
 
-            if (p_stream->tinfo->b_hasbframes)
+            if (mp4mux_track_HasBFrames(p_stream->tinfo))
                 i_trun_flags |= MP4_TRUN_SAMPLE_TIME_OFFSET;
 
             if (i_fixupoffset == 0)
@@ -1072,7 +1086,8 @@ 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->tinfo->i_timescale)); // sample duration
+                    bo_add_32be(trun, samples_from_vlc_tick(p_entry->p_block->i_length,
+                                                            mp4mux_track_GetTimescale(p_stream->tinfo))); // sample duration
 
                 if (i_trun_flags & MP4_TRUN_SAMPLE_SIZE)
                     bo_add_32be(trun, p_entry->p_block->i_buffer); // sample size
@@ -1085,7 +1100,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->tinfo->i_timescale)); // ctts
+                    bo_add_32be(trun, samples_from_vlc_tick(i_diff, mp4mux_track_GetTimescale(p_stream->tinfo))); // ctts
                 }
 
                 *pi_mdat_total_size += p_entry->p_block->i_buffer;
@@ -1096,7 +1111,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->tinfo->fmt.i_cat == VIDEO_ES || p_stream->tinfo->fmt.i_cat == AUDIO_ES))
+                    (p_stream->p_fmt->i_cat == VIDEO_ES || p_stream->p_fmt->i_cat == AUDIO_ES))
                 {
                     AddKeyframeEntry(p_stream, i_write_pos, i_trak, i_sample, i_time);
                 }
@@ -1179,7 +1194,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->tinfo->i_track_id);
+            bo_add_32be(tfra, mp4mux_track_GetID(p_stream->tinfo));
             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++)
@@ -1259,8 +1274,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->tinfo->fmt.i_cat == VIDEO_ES ||
-                     p_stream->tinfo->fmt.i_cat == AUDIO_ES) )
+                    (p_stream->p_fmt->i_cat == VIDEO_ES ||
+                     p_stream->p_fmt->i_cat == AUDIO_ES) )
             {
                 i_barrier_time = __MIN(i_barrier_time, p_stream->i_last_iframe_time);
             }
@@ -1301,27 +1316,30 @@ 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->tinfo->fmt.i_cat == VIDEO_ES && p_stream->tinfo->fmt.video.i_frame_rate )
+    if ( p_stream->p_fmt->i_cat == VIDEO_ES && p_stream->p_fmt->video.i_frame_rate )
     {
         p_entrydata->i_length = vlc_tick_from_samples(
-                p_stream->tinfo->fmt.video.i_frame_rate_base,
-                p_stream->tinfo->fmt.video.i_frame_rate);
+                p_stream->p_fmt->video.i_frame_rate_base,
+                p_stream->p_fmt->video.i_frame_rate);
         msg_Dbg(p_mux, "video track %d fixup to %"PRId64" for sample %u",
-                p_stream->tinfo->i_track_id, p_entrydata->i_length, p_stream->tinfo->i_samples_count - 1);
+                mp4mux_track_GetID(p_stream->tinfo), p_entrydata->i_length,
+                mp4mux_track_GetSampleCount(p_stream->tinfo) - 1);
     }
-    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)
+    else if (p_stream->p_fmt->i_cat == AUDIO_ES &&
+             p_stream->p_fmt->audio.i_rate &&
+             p_entrydata->i_nb_samples && p_stream->p_fmt->audio.i_rate)
     {
         p_entrydata->i_length = vlc_tick_from_samples(p_entrydata->i_nb_samples,
-                p_stream->tinfo->fmt.audio.i_rate);
+                p_stream->p_fmt->audio.i_rate);
         msg_Dbg(p_mux, "audio track %d fixup to %"PRId64" for sample %u",
-                p_stream->tinfo->i_track_id, p_entrydata->i_length, p_stream->tinfo->i_samples_count - 1);
+                mp4mux_track_GetID(p_stream->tinfo), p_entrydata->i_length,
+                mp4mux_track_GetSampleCount(p_stream->tinfo) - 1);
     }
     else
     {
         msg_Warn(p_mux, "unknown length for track %d sample %u",
-                 p_stream->tinfo->i_track_id, p_stream->tinfo->i_samples_count - 1);
+                 mp4mux_track_GetID(p_stream->tinfo),
+                 mp4mux_track_GetSampleCount(p_stream->tinfo) - 1);
         p_entrydata->i_length = 1;
     }
 }
@@ -1447,15 +1465,17 @@ 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->tinfo->i_read_duration - p_sys->i_written_duration < FRAGMENT_LENGTH)
+            mp4mux_track_GetDuration(p_stream->tinfo) - 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->tinfo->i_read_duration;
+            p_stream->i_last_iframe_time = mp4mux_track_GetDuration(p_stream->tinfo);
         }
 
         /* update buffered time */
-        p_stream->tinfo->i_read_duration += __MAX(0, p_heldblock->i_length);
+        mp4mux_track_ForceDuration(p_stream->tinfo,
+                                 mp4mux_track_GetDuration(p_stream->tinfo) +
+                                 __MAX(0, p_heldblock->i_length));
     }
 
 
@@ -1468,26 +1488,27 @@ 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->tinfo->fmt.i_cat == VIDEO_ES )
+    if (p_stream->p_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->tinfo->b_hasbframes && p_currentblock->i_dts != VLC_TICK_INVALID &&
+        if (!mp4mux_track_HasBFrames(p_stream->tinfo) &&
+            p_currentblock->i_dts != VLC_TICK_INVALID &&
             p_currentblock->i_pts > p_currentblock->i_dts)
-            p_stream->tinfo->b_hasbframes = true;
+                mp4mux_track_SetHasBFrames(p_stream->tinfo);
     }
 
     /* Update the global fragment/media duration */
-    vlc_tick_t i_min_read_duration = p_stream->tinfo->i_read_duration;
+    vlc_tick_t i_min_read_duration = mp4mux_track_GetDuration(p_stream->tinfo);
     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->tinfo->fmt.i_cat != VIDEO_ES && p_s->tinfo->fmt.i_cat != AUDIO_ES)
+        if (p_s->p_fmt->i_cat != VIDEO_ES && p_s->p_fmt->i_cat != AUDIO_ES)
             continue;
-        if (p_s->tinfo->i_read_duration < i_min_read_duration)
-            i_min_read_duration = p_s->tinfo->i_read_duration;
+        if (mp4mux_track_GetDuration(p_s->tinfo) < i_min_read_duration)
+            i_min_read_duration = mp4mux_track_GetDuration(p_s->tinfo);
 
         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