Commit 3c91c68a authored by Francois Cartegnie's avatar Francois Cartegnie

demux: mp4: check if fragments exists when seekable

Fixes the false positive and fallback on avcodec with
files having a mvex/trex but no fragments, and conforms
to the spec.
parent 7905fe6a
...@@ -226,7 +226,7 @@ static int MP4_ReadBoxContainerChildren( stream_t *p_stream, ...@@ -226,7 +226,7 @@ static int MP4_ReadBoxContainerChildren( stream_t *p_stream,
return 1; return 1;
} }
static int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container ) int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container )
{ {
return MP4_ReadBoxContainerChildren( p_stream, p_container, 0 ); return MP4_ReadBoxContainerChildren( p_stream, p_container, 0 );
} }
......
...@@ -1562,6 +1562,7 @@ int MP4_BoxCount( MP4_Box_t *p_box, const char *psz_fmt, ... ); ...@@ -1562,6 +1562,7 @@ int MP4_BoxCount( MP4_Box_t *p_box, const char *psz_fmt, ... );
/* Internal functions exposed for MKV demux */ /* Internal functions exposed for MKV demux */
int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box ); int MP4_ReadBoxCommon( stream_t *p_stream, MP4_Box_t *p_box );
int MP4_ReadBoxContainerRaw( stream_t *p_stream, MP4_Box_t *p_container );
int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box ); int MP4_ReadBox_sample_vide( stream_t *p_stream, MP4_Box_t *p_box );
void MP4_FreeBox_sample_vide( MP4_Box_t *p_box ); void MP4_FreeBox_sample_vide( MP4_Box_t *p_box );
......
...@@ -79,6 +79,8 @@ struct demux_sys_t ...@@ -79,6 +79,8 @@ struct demux_sys_t
float f_fps; /* number of frame per seconds */ float f_fps; /* number of frame per seconds */
bool b_fragmented; /* fMP4 */ bool b_fragmented; /* fMP4 */
bool b_seekable;
bool b_fastseekable;
/* */ /* */
MP4_Box_t *p_tref_chap; MP4_Box_t *p_tref_chap;
...@@ -259,6 +261,18 @@ LoadInitFragError: ...@@ -259,6 +261,18 @@ LoadInitFragError:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Does lookup for remaining boxes */
static int ProbeFragments( demux_t *p_demux )
{
demux_sys_t *p_sys = p_demux->p_sys;
msg_Dbg( p_demux, "probing fragments from %"PRId64, stream_Tell( p_demux->s ) );
MP4_ReadBoxContainerRaw( p_demux->s, p_sys->p_root );
return VLC_SUCCESS;
}
static int InitTracks( demux_t *p_demux ) static int InitTracks( demux_t *p_demux )
{ {
demux_sys_t *p_sys = p_demux->p_sys; demux_sys_t *p_sys = p_demux->p_sys;
...@@ -321,7 +335,6 @@ static int Open( vlc_object_t * p_this ) ...@@ -321,7 +335,6 @@ static int Open( vlc_object_t * p_this )
MP4_Box_t *p_trak; MP4_Box_t *p_trak;
unsigned int i; unsigned int i;
bool b_seekable;
bool b_enabled_es; bool b_enabled_es;
/* A little test to see if it could be a mp4 */ /* A little test to see if it could be a mp4 */
...@@ -349,20 +362,26 @@ static int Open( vlc_object_t * p_this ) ...@@ -349,20 +362,26 @@ static int Open( vlc_object_t * p_this )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* create our structure that will contains all data */
p_sys = calloc( 1, sizeof( demux_sys_t ) );
if ( !p_sys )
return VLC_EGENERIC;
/* I need to seek */ /* I need to seek */
stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable ); stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
if( !b_seekable ) if( !p_sys->b_seekable )
{ {
msg_Warn( p_demux, "MP4 plugin discarded (not seekable)" ); msg_Warn( p_demux, "MP4 plugin discarded (not seekable)" );
free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &p_sys->b_fastseekable );
/*Set exported functions */ /*Set exported functions */
p_demux->pf_demux = Demux; p_demux->pf_demux = Demux;
p_demux->pf_control = Control; p_demux->pf_control = Control;
/* create our structure that will contains all data */ p_demux->p_sys = p_sys;
p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
/* Is it Smooth Streaming? */ /* Is it Smooth Streaming? */
bool b_smooth = false; bool b_smooth = false;
...@@ -376,16 +395,25 @@ static int Open( vlc_object_t * p_this ) ...@@ -376,16 +395,25 @@ static int Open( vlc_object_t * p_this )
if( LoadInitFrag( p_demux, b_smooth ) != VLC_SUCCESS ) if( LoadInitFrag( p_demux, b_smooth ) != VLC_SUCCESS )
goto error; goto error;
/* LoadInitFrag early failed */
if( MP4_BoxCount( p_sys->p_root, "/moov/mvex" ) > 0 ) if( MP4_BoxCount( p_sys->p_root, "/moov/mvex" ) > 0 )
{ {
p_sys->b_fragmented = true; 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 );
p_sys->b_fragmented = !!MP4_BoxCount( p_sys->p_root, "/moof" );
}
else
p_sys->b_fragmented = true;
} }
if( p_sys->b_fragmented ) if( p_sys->b_fragmented )
{ {
p_demux->pf_demux = DemuxFrg; p_demux->pf_demux = DemuxFrg;
} }
stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
if( b_smooth ) if( b_smooth )
{ {
if( InitTracks( p_demux ) != VLC_SUCCESS ) if( InitTracks( p_demux ) != VLC_SUCCESS )
...@@ -393,17 +421,16 @@ static int Open( vlc_object_t * p_this ) ...@@ -393,17 +421,16 @@ static int Open( vlc_object_t * p_this )
CreateTracksFromSmooBox( p_demux ); CreateTracksFromSmooBox( p_demux );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
else if( p_sys->b_fragmented && b_seekable ) else if( p_sys->b_fragmented )
{ {
/* We are not yet able to demux a fragmented MP4 file, using the 'mfra' /* We are not yet able to demux a fragmented MP4 file, using the 'mfra'
* box. So if STREAM_CAN_FASTSEEK is true, we're assuming we've got such
* a file, and we let avformat do the job. */ * a file, and we let avformat do the job. */
msg_Warn( p_demux, "MP4 plugin discarded "\ msg_Warn( p_demux, "MP4 plugin discarded "\
"(fast-seekable and fragmented, let avformat demux it)" ); "(fragmented, let avformat demux it)" );
stream_Seek( p_demux->s, 0 ); /* rewind, for other demux */ stream_Seek( p_demux->s, 0 ); /* rewind, for other demux */
goto error; goto error;
} }
else if( !p_sys->b_fragmented && !b_seekable ) else if( !p_sys->b_fastseekable )
{ {
msg_Warn( p_demux, "MP4 plugin discarded (not fast-seekable)" ); msg_Warn( p_demux, "MP4 plugin discarded (not fast-seekable)" );
stream_Seek( p_demux->s, 0 ); /* rewind, for other demux */ stream_Seek( p_demux->s, 0 ); /* rewind, for other demux */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment