]> git.sesse.net Git - vlc/blobdiff - modules/demux/ts.c
demux: ts: fix SL/FMC descriptors handling
[vlc] / modules / demux / ts.c
index d94ecc1a973e6a581a00a7526dedd98c2ec3c68d..051bdde1e3bbd0259099a1e887586964f5d7d719 100644 (file)
@@ -274,7 +274,7 @@ typedef struct
 {
     es_format_t  fmt;
     es_out_id_t *id;
-    es_mpeg4_descriptor_t *p_mpeg4desc;
+    const es_mpeg4_descriptor_t *p_mpeg4desc;
 } ts_pes_es_t;
 
 typedef enum
@@ -314,21 +314,6 @@ typedef enum
     TS_PMT_REGISTRATION_HDMV
 } ts_pmt_registration_type_t;
 
-typedef struct
-{
-    es_format_t  fmt;
-    es_out_id_t *id;
-    ts_es_data_type_t data_type;
-    int         i_data_size;
-    int         i_data_gathered;
-    block_t     *p_data;
-    block_t    **pp_last;
-
-    es_mpeg4_descriptor_t *p_mpeg4desc;
-
-    block_t *   p_prepcr_outqueue;
-} ts_es_t;
-
 typedef enum
 {
     TYPE_FREE = 0,
@@ -2251,7 +2236,7 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid, block_t *p_pes )
     else if( pid->u.p_pes->es.fmt.i_codec == VLC_CODEC_SUBT &&
              pid->u.p_pes->es.p_mpeg4desc )
     {
-        decoder_config_descriptor_t *dcd = &pid->u.p_pes->es.p_mpeg4desc->dec_descr;
+        const decoder_config_descriptor_t *dcd = &pid->u.p_pes->es.p_mpeg4desc->dec_descr;
 
         if( dcd->i_extra > 2 &&
             dcd->p_extra[0] == 0x10 &&
@@ -4230,35 +4215,75 @@ static bool PMTEsHasComponentTag( const dvbpsi_pmt_es_t *p_es,
     return p_si->i_component_tag == i_component_tag;
 }
 
+static const es_mpeg4_descriptor_t * GetMPEG4DescByEsId( const iod_descriptor_t *iod,
+                                                         uint16_t i_es_id )
+{
+    if( iod )
+    for( int i = 0; i < ES_DESCRIPTOR_COUNT; i++ )
+    {
+        if( iod->es_descr[i].i_es_id == i_es_id )
+        {
+            if ( iod->es_descr[i].b_ok )
+                return &iod->es_descr[i];
+        }
+    }
+    return NULL;
+}
+
 static void PMTSetupEsISO14496( demux_t *p_demux, ts_pes_es_t *p_es,
                                 const ts_pmt_t *p_pmt, const dvbpsi_pmt_es_t *p_dvbpsies )
 {
     es_format_t *p_fmt = &p_es->fmt;
 
-    /* MPEG-4 stream: search FMC_DESCRIPTOR (SL Packetized stream) */
-    dvbpsi_descriptor_t *p_dr = PMTEsFindDescriptor( p_dvbpsies, 0x1f );
-
-    if( p_dr && p_dr->i_length == 2 && p_pmt->iod )
+    const dvbpsi_descriptor_t *p_dr = p_dvbpsies->p_first_descriptor;
+    while( p_dr )
     {
-        const int i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1];
-
-        msg_Dbg( p_demux, "found FMC_descriptor declaring sl packetization on es_id=%d", i_es_id );
+        const es_mpeg4_descriptor_t *p_esdescr = NULL;
+        uint16_t i_es_id;
+        uint8_t i_length = p_dr->i_length;
 
-        p_es->p_mpeg4desc = NULL;
+        switch( p_dr->i_tag )
+        {
+            case 0x1f: /* FMC Descriptor */
+                while( i_length >= 3 && !p_esdescr )
+                {
+                    i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1];
+                    p_esdescr = GetMPEG4DescByEsId( p_pmt->iod, i_es_id );
+                    /* FIXME: add flexmux channel */
+                    i_length -= 3;
+                    if( p_esdescr )
+                        msg_Dbg( p_demux, "found FMC_descriptor declaring sl packetization on es_id=%"PRIu16, i_es_id );
+                }
+                break;
+            case 0x1e: /* SL Descriptor */
+                if( i_length == 2 )
+                {
+                    i_es_id = ( p_dr->p_data[0] << 8 ) | p_dr->p_data[1];
+                    p_esdescr = GetMPEG4DescByEsId( p_pmt->iod, i_es_id );
+                    if( p_esdescr )
+                        msg_Dbg( p_demux, "found SL_descriptor declaring sl packetization on es_id=%"PRIu16, i_es_id );
+                }
+                break;
+            default:
+                break;
+        }
 
-        for( int i = 0; i < ES_DESCRIPTOR_COUNT; i++ )
+        if( p_esdescr )
         {
-            iod_descriptor_t *iod = p_pmt->iod;
-            if( iod->es_descr[i].i_es_id == i_es_id )
+            if( !p_esdescr->b_ok )
             {
-                if ( iod->es_descr[i].b_ok )
-                    p_es->p_mpeg4desc = &iod->es_descr[i];
-                else
-                    msg_Dbg( p_demux, "MPEG-4 descriptor not yet available on es_id=%d", i_es_id );
+                msg_Dbg( p_demux, "MPEG-4 descriptor not yet available on es_id=%"PRIu16, i_es_id );
+            }
+            else
+            {
+                p_es->p_mpeg4desc = p_esdescr;
                 break;
             }
         }
+
+        p_dr = p_dr->p_next;
     }
+
     if( !p_es->p_mpeg4desc )
     {
         switch( p_dvbpsies->i_type )
@@ -5223,6 +5248,8 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt )
     {
         IODFree( p_pmt->iod );
         p_pmt->iod = NULL;
+        for( int i=0; i<old_es_rm.i_size; i++ )
+            old_es_rm.p_elems[i]->u.p_pes->es.p_mpeg4desc = NULL;
     }
 
     msg_Dbg( p_demux, "new PMT program number=%d version=%d pid_pcr=%d",
@@ -5849,7 +5876,6 @@ static void ts_pes_Del( demux_t *p_demux, ts_pes_t *pes )
         block_ChainRelease( pes->p_prepcr_outqueue );
 
     es_format_Clean( &pes->es.fmt );
-    free( pes->es.p_mpeg4desc );
 
     for( int i = 0; i < pes->extra_es.i_size; i++ )
     {