[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