[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