[vlc-commits] demux: mp4: try to recycle ES on sample desc change
Francois Cartegnie
git at videolan.org
Thu Apr 16 15:50:52 CEST 2020
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Apr 9 15:21:36 2020 +0200| [3f02c7cd9404b99386d63cced89ac024c4e95d0e] | committer: Francois Cartegnie
demux: mp4: try to recycle ES on sample desc change
ref #24576
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3f02c7cd9404b99386d63cced89ac024c4e95d0e
---
modules/demux/mp4/mp4.c | 157 +++++++++++++++++++++++-------------------------
1 file changed, 74 insertions(+), 83 deletions(-)
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 629eb4552a..9d577ace8b 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -3144,11 +3144,32 @@ static int TrackTimeToSampleChunk( demux_t *p_demux, mp4_track_t *p_track,
return VLC_SUCCESS;
}
-static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
- unsigned int i_chunk, unsigned int i_sample )
+static bool FormatIsCompatible( const es_format_t *p_fmt1, const es_format_t *p_fmt2 )
{
- bool b_reselect = false;
+ if( p_fmt1->i_original_fourcc != p_fmt2->i_original_fourcc )
+ return false;
+ if( (p_fmt1->i_extra > 0) ^ (p_fmt2->i_extra > 0) )
+ return false;
+
+ if( p_fmt1->i_codec == p_fmt2->i_codec &&
+ p_fmt1->i_extra && p_fmt2->i_extra &&
+ p_fmt1->i_extra == p_fmt2->i_extra )
+ {
+ return !!memcmp( p_fmt1->p_extra, p_fmt2->p_extra, p_fmt1->i_extra );
+ }
+ if( p_fmt1->i_cat == AUDIO_ES )
+ {
+ /* Reject audio streams with different or unknown rates */
+ if( p_fmt1->audio.i_rate != p_fmt2->audio.i_rate || !p_fmt1->audio.i_rate )
+ return false;
+ }
+
+ return es_format_IsSimilar( p_fmt1, p_fmt2 );
+}
+
+static int TrackUpdateFormat( demux_t *p_demux, mp4_track_t *p_track, uint32_t i_chunk )
+{
/* now see if actual es is ok */
if( p_track->i_chunk >= p_track->i_chunk_count ||
(p_track->chunk[p_track->i_chunk].i_sample_description_index !=
@@ -3157,103 +3178,73 @@ static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
msg_Warn( p_demux, "recreate ES for track[Id 0x%x]",
p_track->i_track_ID );
- es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
- p_track->p_es, &b_reselect );
-
- es_out_Del( p_demux->out, p_track->p_es );
-
- p_track->p_es = NULL;
-
- if( TrackCreateES( p_demux, p_track, i_chunk, &p_track->p_es ) )
+ const MP4_Box_t *p_newsample = MP4_BoxGet( p_track->p_stsd, "[%d]",
+ p_track->chunk[i_chunk].i_sample_description_index - 1 );
+ if( p_newsample == NULL )
{
- msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
- p_track->i_track_ID );
-
- p_track->b_ok = false;
+ msg_Err( p_demux, "Can't change track[Id 0x%x] format for sample desc %" PRIu32,
+ p_track->i_track_ID, p_track->chunk[i_chunk].i_sample_description_index );
+ p_track->b_ok = false;
p_track->b_selected = false;
return VLC_EGENERIC;
}
- }
-
- /* select again the new decoder */
- if( b_reselect )
- {
- es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
- }
-
- p_track->i_chunk = i_chunk;
- p_track->chunk[i_chunk].i_sample = i_sample - p_track->chunk[i_chunk].i_sample_first;
- p_track->i_sample = i_sample;
-
- return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
-}
-#if 0
-static void MP4_TrackRestart( demux_t *p_demux, mp4_track_t *p_track,
- MP4_Box_t *p_params_box )
-{
- bool b_reselect = false;
- if( p_track->p_es )
- {
- es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
- p_track->p_es, &b_reselect );
- }
- /* Save previous fragmented pos */
- uint32_t i_sample_pos_backup = p_track->i_sample;
- vlc_tick_t time_backup = p_track->i_time;
- uint32_t timescale_backup = p_track->i_timescale;
+ track_config_t cfg;
+ TrackConfigInit( &cfg );
+ es_format_t tmpfmt;
+ es_format_Init( &tmpfmt, p_track->fmt.i_cat, 0 );
+ tmpfmt.i_id = p_track->i_track_ID;
+ if( TrackFillConfig( p_demux, p_track, p_newsample, i_chunk, &tmpfmt, &cfg ) == VLC_SUCCESS &&
+ !FormatIsCompatible( &p_track->fmt, &tmpfmt ) )
+ {
+ bool b_reselect = false;
- /* Save previous format and ES */
- es_format_t fmtbackup;
- es_out_id_t *p_es_backup = p_track->p_es;
- p_track->p_es = NULL;
- es_format_Copy( &fmtbackup, &p_track->fmt );
- es_format_Clean( &p_track->fmt );
+ es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
+ p_track->p_es, &b_reselect );
+ es_out_Del( p_demux->out, p_track->p_es );
- /* do the cleanup and recycle track / restart */
- MP4_TrackDestroy( p_demux, p_track );
- memset( p_track, 0, sizeof(*p_track) );
+ p_track->p_es = MP4_CreateES( p_demux->out, &tmpfmt, cfg.b_forced_spu );
+ if( !p_track->p_es )
+ {
+ msg_Err( p_demux, "cannot create es for track[Id 0x%x]",
+ p_track->i_track_ID );
- assert(p_params_box->i_type == ATOM_trak);
- MP4_TrackCreate( p_demux, p_track, p_params_box, false, true );
+ p_track->b_ok = false;
+ p_track->b_selected = false;
+ es_format_Clean( &tmpfmt );
+ return VLC_EGENERIC;
+ }
- if( p_track->b_ok )
- {
- if( !es_format_IsSimilar( &fmtbackup, &p_track->fmt ) ||
- fmtbackup.i_extra != p_track->fmt.i_extra ||
- memcmp( fmtbackup.p_extra, p_track->fmt.p_extra, fmtbackup.i_extra ) )
- {
- if( p_es_backup )
- es_out_Del( p_demux->out, p_es_backup );
+ /* select again the new decoder */
+ if( b_reselect )
+ es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
- if( !p_track->b_chapters_source )
- {
- p_track->p_es = MP4_AddTrackES( p_demux->out, p_track );
- p_track->b_ok = !!p_track->p_es;
- }
- }
- else
- {
- p_track->p_es = p_es_backup;
+ TrackConfigApply( &cfg, p_track );
+ es_format_Clean( &p_track->fmt );
+ es_format_Init( &p_track->fmt, tmpfmt.i_cat, tmpfmt.i_codec );
+ es_format_Copy( &p_track->fmt, &tmpfmt );
+ p_track->p_sample = p_newsample;
}
- }
- else if( p_es_backup )
- {
- es_out_Del( p_demux->out, p_es_backup );
+ es_format_Clean( &tmpfmt );
}
- /* select again the new decoder */
- if( b_reselect && p_track->p_es )
- es_out_Control( p_demux->out, ES_OUT_SET_ES, p_track->p_es );
+ return VLC_SUCCESS;
+}
+
+static int TrackGotoChunkSample( demux_t *p_demux, mp4_track_t *p_track,
+ uint32_t i_chunk, uint32_t i_sample )
+{
+ if( TrackUpdateFormat( p_demux, p_track, i_chunk ) != VLC_SUCCESS )
+ return VLC_EGENERIC;
- es_format_Clean( &fmtbackup );
+ p_track->i_chunk = i_chunk;
+ p_track->chunk[i_chunk].i_sample = i_sample - p_track->chunk[i_chunk].i_sample_first;
+ p_track->i_sample = i_sample;
- /* Restore fragmented pos */
- p_track->i_sample = i_sample_pos_backup;
- p_track->i_time = MP4_rescale( time_backup, timescale_backup, p_track->i_timescale );
+ return p_track->b_selected ? VLC_SUCCESS : VLC_EGENERIC;
}
-#endif
+
/****************************************************************************
* MP4_TrackSetup:
****************************************************************************
More information about the vlc-commits
mailing list