[vlc-commits] mux: mp4: rework fast start

Francois Cartegnie git at videolan.org
Fri Oct 26 17:53:15 CEST 2018


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct 26 17:19:57 2018 +0200| [2c31eec409b72c9e54c4dab86b19fb37f993d446] | committer: Francois Cartegnie

mux: mp4: rework fast start

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

 modules/mux/mp4/libmp4mux.c | 18 ++++++++---
 modules/mux/mp4/libmp4mux.h |  6 +---
 modules/mux/mp4/mp4.c       | 79 ++++++++++++++++++++++++++-------------------
 3 files changed, 60 insertions(+), 43 deletions(-)

diff --git a/modules/mux/mp4/libmp4mux.c b/modules/mux/mp4/libmp4mux.c
index 7cfea5dde3..88dfaa348c 100644
--- a/modules/mux/mp4/libmp4mux.c
+++ b/modules/mux/mp4/libmp4mux.c
@@ -139,6 +139,19 @@ mp4mux_sample_t *mp4mux_track_GetLastSample(mp4mux_trackinfo_t *t)
     else return NULL;
 }
 
+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++)
+    {
+        mp4mux_trackinfo_t *t = vlc_array_item_at_index(&h->tracks, i_track);
+        for (unsigned i = 0; i < t->i_samples_count; i++)
+        {
+            mp4mux_sample_t *sample = t->samples;
+            sample[i].i_pos += offset;
+        }
+    }
+}
+
 mp4mux_handle_t * mp4mux_New(enum mp4mux_options options)
 {
     mp4mux_handle_t *h = malloc(sizeof(*h));
@@ -1560,7 +1573,6 @@ static bo_t *GetStblBox(vlc_object_t *p_obj, mp4mux_trackinfo_t *p_track, bool b
         box_gather(stbl, ctts);
     box_gather(stbl, stsc);
     box_gather(stbl, stsz);
-    p_track->i_stco_pos = bo_size(stbl) + 16;
     box_gather(stbl, stco);
 
     return stbl;
@@ -1935,19 +1947,15 @@ bo_t * mp4mux_GetMoov(mp4mux_handle_t *h, vlc_object_t *p_obj, vlc_tick_t i_dura
             stbl = GetStblBox(p_obj, p_stream, h->options & QUICKTIME, h->options & USE64BITEXT);
 
         /* append stbl to minf */
-        p_stream->i_stco_pos += bo_size(minf);
         box_gather(minf, stbl);
 
         /* append minf to mdia */
-        p_stream->i_stco_pos += bo_size(mdia);
         box_gather(mdia, minf);
 
         /* append mdia to trak */
-        p_stream->i_stco_pos += bo_size(trak);
         box_gather(trak, mdia);
 
         /* append trak to moov */
-        p_stream->i_stco_pos += bo_size(moov);
         box_gather(moov, trak);
     }
 
diff --git a/modules/mux/mp4/libmp4mux.h b/modules/mux/mp4/libmp4mux.h
index 6a45bc3fa2..1da7e88e1b 100644
--- a/modules/mux/mp4/libmp4mux.h
+++ b/modules/mux/mp4/libmp4mux.h
@@ -62,10 +62,6 @@ typedef struct
     vlc_tick_t   i_firstdts; /* the really first packet */
     bool         b_hasbframes;
 
-    /* temp stuff */
-    /* for later stco fix-up (fast start files) */
-    uint64_t     i_stco_pos;
-
     /* frags */
     vlc_tick_t   i_trex_default_length;
     uint32_t     i_trex_default_size;
@@ -98,8 +94,8 @@ void mp4mux_track_DebugEdits(vlc_object_t *, const mp4mux_trackinfo_t *);
 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);
+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 5799245486..1961cc7ca4 100644
--- a/modules/mux/mp4/mp4.c
+++ b/modules/mux/mp4/mp4.c
@@ -297,65 +297,78 @@ static void Close(vlc_object_t *p_this)
     sout_AccessOutWrite(p_mux->p_access, bo.b);
 
     /* Create MOOV header */
-    const bool b_64bitext = (p_sys->i_pos >= (((uint64_t)0x1) << 32));
+    bool b_64bitext = (p_sys->i_pos > UINT32_MAX);
     if(b_64bitext)
         mp4mux_Set64BitExt(p_sys->muxh);
+
     uint64_t i_moov_pos = p_sys->i_pos;
     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");
-    while (p_sys->b_fast_start && moov && moov->b) {
+    while (p_sys->b_fast_start && moov && moov->b)
+    {
         /* Move data to the end of the file so we can fit the moov header
          * at the start */
-        int64_t i_size = p_sys->i_pos - p_sys->i_mdat_pos;
-        int i_moov_size = bo_size(moov);
+        uint64_t i_mdatsize = p_sys->i_pos - p_sys->i_mdat_pos;
+
+        /* moving samples will need new moov with 64bit atoms ? */
+        if(!b_64bitext && p_sys->i_pos + bo_size(moov) > UINT32_MAX)
+        {
+            mp4mux_Set64BitExt(p_sys->muxh);
+            b_64bitext = true;
+            /* generate a new moov */
+            bo_t *moov64 = mp4mux_GetMoov(p_sys->muxh, VLC_OBJECT(p_mux), 0);
+            if(moov64)
+            {
+                bo_free(moov);
+                moov = moov64;
+            }
+        }
+        /* We now know our final MOOV size */
+
+        /* Fix-up samples to chunks table in MOOV header to they point to next MDAT location */
+        mp4mux_ShiftSamples(p_sys->muxh, bo_size(moov));
+        msg_Dbg(p_this,"Moving data by %"PRIu64, (uint64_t)bo_size(moov));
+        bo_t *shifted = mp4mux_GetMoov(p_sys->muxh, VLC_OBJECT(p_mux), 0);
+        if(!shifted)
+        {
+            /* fail */
+            p_sys->b_fast_start = false;
+            continue;
+        }
+        assert(bo_size(shifted) == bo_size(moov));
+        bo_free(moov);
+        moov = shifted;
 
-        while (i_size > 0) {
-            int64_t i_chunk = __MIN(32768, i_size);
+        /* Make space, move MDAT data by moov size towards the end */
+        while (i_mdatsize > 0)
+        {
+            size_t i_chunk = __MIN(32768, i_mdatsize);
             block_t *p_buf = block_Alloc(i_chunk);
             sout_AccessOutSeek(p_mux->p_access,
-                                p_sys->i_mdat_pos + i_size - i_chunk);
-            if (sout_AccessOutRead(p_mux->p_access, p_buf) < i_chunk) {
+                                p_sys->i_mdat_pos + i_mdatsize - i_chunk);
+            ssize_t i_read = sout_AccessOutRead(p_mux->p_access, p_buf);
+            if (i_read < 0 || (size_t) i_read < i_chunk) {
                 msg_Warn(p_this, "read() not supported by access output, "
                           "won't create a fast start file");
                 p_sys->b_fast_start = false;
                 block_Release(p_buf);
                 break;
             }
-            sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos + i_size +
-                                i_moov_size - i_chunk);
+            sout_AccessOutSeek(p_mux->p_access, p_sys->i_mdat_pos + i_mdatsize +
+                               bo_size(moov) - i_chunk);
             sout_AccessOutWrite(p_mux->p_access, p_buf);
-            i_size -= i_chunk;
+            i_mdatsize -= i_chunk;
         }
 
-        if (!p_sys->b_fast_start)
-            break;
+        if (!p_sys->b_fast_start) /* failed above */
+            continue;
 
         /* Update pos pointers */
         i_moov_pos = p_sys->i_mdat_pos;
         p_sys->i_mdat_pos += bo_size(moov);
 
-        /* Fix-up samples to chunks table in MOOV header */
-        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->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->tinfo->i_stco_pos + i_written++ * 4, entry[i].i_pos + p_sys->i_mdat_pos - i_moov_pos);
-
-                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;
-                    }
-            }
-        }
-
         p_sys->b_fast_start = false;
     }
 



More information about the vlc-commits mailing list