[vlc-commits] demux: mp4: bind fragment on moof pos
Francois Cartegnie
git at videolan.org
Mon Feb 6 20:08:06 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Feb 1 18:47:30 2017 +0100| [b4bb0efbc976cdde3d961c7203f9c469637f5373] | committer: Francois Cartegnie
demux: mp4: bind fragment on moof pos
Rewrites handling of fragments in leafdemux.
refs #16832
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b4bb0efbc976cdde3d961c7203f9c469637f5373
---
modules/demux/mp4/fragments.c | 4 +-
modules/demux/mp4/fragments.h | 2 +-
modules/demux/mp4/libmp4.c | 20 +-----
modules/demux/mp4/mp4.c | 143 +++++++++++++++++-------------------------
4 files changed, 63 insertions(+), 106 deletions(-)
diff --git a/modules/demux/mp4/fragments.c b/modules/demux/mp4/fragments.c
index a446e91..9ad4204 100644
--- a/modules/demux/mp4/fragments.c
+++ b/modules/demux/mp4/fragments.c
@@ -61,11 +61,13 @@ void MP4_Fragments_Remove( mp4_fragments_t *p_frags, mp4_fragment_t *p_fragment
}
}
-void MP4_Fragments_Clean( mp4_fragments_t *p_frags )
+void MP4_Fragments_Clean( mp4_fragments_t *p_frags,
+ void (*pf_box_clean)(MP4_Box_t *) )
{
while( p_frags->moov.p_next )
{
mp4_fragment_t *p_fragment = p_frags->moov.p_next->p_next;
+ pf_box_clean( p_frags->moov.p_next->p_moox );
MP4_Fragment_Clean( p_frags->moov.p_next );
free( p_frags->moov.p_next );
p_frags->moov.p_next = p_fragment;
diff --git a/modules/demux/mp4/fragments.h b/modules/demux/mp4/fragments.h
index 9b2a3b0..5a53777 100644
--- a/modules/demux/mp4/fragments.h
+++ b/modules/demux/mp4/fragments.h
@@ -63,7 +63,7 @@ static inline void MP4_Fragment_Delete( mp4_fragment_t *p_fragment )
}
bool MP4_Fragments_Init(mp4_fragments_t *);
-void MP4_Fragments_Clean(mp4_fragments_t *);
+void MP4_Fragments_Clean(mp4_fragments_t *, void (*pf_box_clean)(MP4_Box_t *));
void MP4_Fragments_Insert(mp4_fragments_t *, mp4_fragment_t *);
void MP4_Fragments_Remove( mp4_fragments_t *, mp4_fragment_t * );
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index 1ef0fcf..0edf687 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -4643,30 +4643,14 @@ MP4_Box_t *MP4_BoxGetNextChunk( stream_t *s )
{
/* p_chunk is a virtual root container for the moof and mdat boxes */
MP4_Box_t *p_fakeroot;
- MP4_Box_t *p_tmp_box = MP4_BoxNew( 0 );
- if( unlikely( p_tmp_box == NULL ) )
- return NULL;
-
- /* We might get a ftyp box or a SmooBox */
- if( MP4_PeekBoxHeader( s, p_tmp_box ) == 0 )
- {
- free( p_tmp_box );
- return NULL;
- }
-
- if( p_tmp_box->i_type == ATOM_ftyp )
- {
- MP4_BoxFree( p_tmp_box );
- return MP4_BoxGetRoot( s );
- }
- MP4_BoxFree( p_tmp_box );
+ MP4_Box_t *p_tmp_box;
p_fakeroot = MP4_BoxNew( ATOM_root );
if( unlikely( p_fakeroot == NULL ) )
return NULL;
p_fakeroot->i_shortsize = 1;
- const uint32_t stoplist[] = { ATOM_moof, 0 };
+ const uint32_t stoplist[] = { ATOM_moov, ATOM_moof, 0 };
MP4_ReadBoxContainerChildren( s, p_fakeroot, stoplist );
p_tmp_box = p_fakeroot->p_first;
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 546d141..02e5bec 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -741,25 +741,27 @@ static int Open( vlc_object_t * p_this )
if( MP4_BoxCount( p_sys->p_root, "/moov/mvex" ) > 0 )
{
+ const MP4_Box_t *p_moov = MP4_BoxGet( p_sys->p_root, "/moov" );
if ( p_sys->b_seekable )
{
/* Probe remaining to check if there's really fragments
or if that file is just ready to append fragments */
ProbeFragments( p_demux, false );
- p_sys->b_fragmented = !!MP4_BoxCount( p_sys->p_root, "/moof" );
+ const MP4_Box_t *p_moof = MP4_BoxGet( p_sys->p_root, "/moof" );
+ p_sys->b_fragmented = !!p_moof;
if ( p_sys->b_fragmented && !p_sys->i_overall_duration )
ProbeFragments( p_demux, true );
- MP4_Box_t *p_mdat = MP4_BoxGet( p_sys->p_root, "mdat" );
- if ( p_mdat )
- {
- vlc_stream_Seek( p_demux->s, p_mdat->i_pos );
- msg_Dbg( p_demux, "rewinding to mdat %"PRId64, p_mdat->i_pos );
- }
+ if( vlc_stream_Seek( p_demux->s, p_moov->i_pos ) != VLC_SUCCESS )
+ goto error;
}
- else
+ else /* Handle as fragmented by default as we can't see moof */
+ {
+ p_sys->context.p_fragment = &p_sys->fragments.moov;
+ p_sys->context.i_current_box_type = ATOM_moov;
p_sys->b_fragmented = true;
+ }
}
if ( !MP4_Fragment_Moov(&p_sys->fragments)->p_moox )
@@ -1951,7 +1953,7 @@ static void Close ( vlc_object_t * p_this )
if( p_sys->p_title )
vlc_input_title_Delete( p_sys->p_title );
- MP4_Fragments_Clean( &p_sys->fragments );
+ MP4_Fragments_Clean( &p_sys->fragments, MP4_BoxFree );
free( p_sys );
}
@@ -4218,20 +4220,6 @@ int DemuxFrg( demux_t *p_demux )
return VLC_DEMUXER_SUCCESS;
}
-static bool BoxExistsInRootTree( MP4_Box_t *p_root, uint32_t i_type, uint64_t i_pos )
-{
- while ( p_root )
- {
- if ( p_root->i_pos == i_pos )
- {
- assert( i_type == p_root->i_type );
- break;
- }
- p_root = p_root->p_next;
- }
- return (p_root != NULL);
-}
-
static mtime_t SumFragmentsDurations( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
@@ -4550,8 +4538,8 @@ static int ProbeFragments( demux_t *p_demux, bool b_force )
{
/* We stop at first moof, which validates our fragmentation condition
* and we'll find others while reading. */
- const uint32_t stoplist[] = { ATOM_moof, 0 };
- MP4_ReadBoxContainerChildren( p_demux->s, p_sys->p_root, stoplist );
+ const uint32_t excllist[] = { ATOM_moof, 0 };
+ MP4_ReadBoxContainerRestricted( p_demux->s, p_sys->p_root, NULL, excllist );
}
if ( !MP4_Fragment_Moov( &p_sys->fragments )->p_moox )
@@ -4566,14 +4554,6 @@ static int ProbeFragments( demux_t *p_demux, bool b_force )
AddFragment( p_demux, p_moov );
}
- MP4_Box_t *p_moof = MP4_BoxGet( p_sys->p_root, "moof" );
- while ( p_moof )
- {
- if ( p_moof->i_type == ATOM_moof )
- AddFragment( p_demux, p_moof );
- p_moof = p_moof->p_next;
- }
-
return VLC_SUCCESS;
}
@@ -5197,14 +5177,20 @@ static int LeafParseMDATwithMOOF( demux_t *p_demux, MP4_Box_t *p_moof )
uint8_t mdat[8];
int i_read = vlc_stream_Read( p_demux->s, &mdat, 8 );
p_sys->context.i_mdatbytesleft = GetDWBE( mdat );
+ i_pos = vlc_stream_Tell( p_demux->s );
if ( i_read < 8 || p_sys->context.i_mdatbytesleft < 8 ||
VLC_FOURCC( mdat[4], mdat[5], mdat[6], mdat[7] ) != ATOM_mdat )
{
- i_pos = vlc_stream_Tell( p_demux->s );
msg_Err(p_demux, "No mdat atom at %"PRIu64, i_pos - i_read );
return VLC_EGENERIC;
}
p_sys->context.i_mdatbytesleft -= 8;
+
+ if( p_sys->context.p_fragment->i_chunk_range_min_offset > i_pos )
+ {
+ uint64_t i_diff = p_sys->context.p_fragment->i_chunk_range_min_offset - i_pos;
+ p_sys->context.i_mdatbytesleft -= vlc_stream_Read( p_demux->s, NULL, i_diff );
+ }
}
i_pos = vlc_stream_Tell( p_demux->s );
@@ -5253,20 +5239,6 @@ end:
return VLC_SUCCESS;
}
-static void RestartAllTracks( demux_t *p_demux, const MP4_Box_t *p_root )
-{
- demux_sys_t *p_sys = p_demux->p_sys;
-
- for( unsigned i_track = 0; i_track < p_sys->i_tracks; i_track++ )
- {
- mp4_track_t *tk = &p_sys->track[i_track];
- if( !tk->b_ok || tk->b_chapters_source )
- continue;
-
- ReInitDecoder( p_demux, p_root, tk );
- }
-}
-
static int DemuxAsLeaf( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
@@ -5305,66 +5277,65 @@ static int DemuxAsLeaf( demux_t *p_demux )
{
/* Othewise mdat is skipped. FIXME: mdat reading ! */
const uint8_t *p_peek;
- int i_read = vlc_stream_Peek( p_demux->s, &p_peek, 8 );
- if ( i_read < 8 )
+ if( vlc_stream_Peek( p_demux->s, &p_peek, 8 ) != 8 )
return VLC_DEMUXER_EOF;
p_sys->context.i_current_box_type = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
-
if ( p_sys->context.i_current_box_type != ATOM_mdat )
{
- if ( !BoxExistsInRootTree( p_sys->p_root, p_sys->context.i_current_box_type, vlc_stream_Tell( p_demux->s ) ) )
- {// only if !b_probed ??
- MP4_Box_t *p_vroot = MP4_BoxGetNextChunk( p_demux->s );
- if(!p_vroot)
- return VLC_DEMUXER_SUCCESS;
+ MP4_Box_t *p_vroot = MP4_BoxGetNextChunk( p_demux->s );
+ if(!p_vroot)
+ return VLC_DEMUXER_SUCCESS;
+
+ MP4_Box_t *p_box = NULL;
+ mp4_fragment_t *p_fragment = NULL;
+ for( p_box = p_vroot->p_first; p_box; p_box = p_box->p_next )
+ {
+ if( p_box->i_type == ATOM_moof ||
+ p_box->i_type == ATOM_moov )
+ break;
+ }
- MP4_Box_t *p_mooxbox = MP4_BoxExtract( &p_vroot->p_first, ATOM_moof );
- if( !p_mooxbox )
+ if( p_box )
+ {
+ if( p_sys->context.p_fragment && !p_sys->b_seekable )
{
- RestartAllTracks( p_demux, p_vroot );
- p_mooxbox = MP4_BoxExtract( &p_vroot->p_first, ATOM_moov );
+ if( p_sys->context.p_fragment != &p_sys->fragments.moov )
+ {
+ MP4_BoxFree( p_sys->context.p_fragment->p_moox );
+ MP4_Fragments_Remove( &p_sys->fragments, p_sys->context.p_fragment );
+ MP4_Fragment_Delete( p_sys->context.p_fragment );
+ }
+ p_sys->context.p_fragment = NULL;
}
- if(!p_mooxbox)
+ p_fragment = GetFragmentByAtomPos( &p_sys->fragments, p_box->i_pos );
+ if( p_fragment == NULL && p_box->i_type != ATOM_moov )
{
- MP4_BoxFree( p_vroot );
- msg_Info(p_demux, "no moof or moov in current chunk");
- return VLC_DEMUXER_SUCCESS;
+ p_box = MP4_BoxExtract( &p_vroot->p_first, p_box->i_type );
+ /* create fragment */
+ AddFragment( p_demux, p_box );
+ p_fragment = GetFragmentByAtomPos( &p_sys->fragments, p_box->i_pos );
}
+ p_sys->context.p_fragment = p_fragment;
+ p_sys->context.i_current_box_type = p_box->i_type;
+ }
- /* create fragment */
- AddFragment( p_demux, p_mooxbox );
+ MP4_BoxFree( p_vroot );
- /* Append to root */
- p_sys->p_root->p_last->p_next = p_mooxbox;
- p_sys->p_root->p_last = p_mooxbox;
- MP4_BoxFree( p_vroot );
- }
- else
+ if( p_fragment == NULL )
{
- /* Skip */
- msg_Err( p_demux, "skipping known chunk type %4.4s size %"PRIu32, (char*)& p_sys->context.i_current_box_type, GetDWBE( p_peek ) );
- vlc_stream_Read( p_demux->s, NULL, GetDWBE( p_peek ) );
+ msg_Info(p_demux, "no moof or moov in current chunk");
+ return VLC_DEMUXER_SUCCESS;
}
}
- else
- {
- if( p_sys->context.p_fragment && !p_sys->b_seekable )
- {
- MP4_Fragments_Remove( &p_sys->fragments, p_sys->context.p_fragment );
- MP4_Fragment_Delete( p_sys->context.p_fragment );
- }
- /* skip mdat header */
- p_sys->context.p_fragment = GetFragmentByPos( &p_sys->fragments, vlc_stream_Tell( p_demux->s ) + 8, true );
- }
-
}
if ( p_sys->context.i_current_box_type == ATOM_mdat )
{
assert(p_sys->context.p_fragment);
+
if ( p_sys->context.p_fragment )
switch( p_sys->context.p_fragment->p_moox->i_type )
{
More information about the vlc-commits
mailing list