[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