Commit febea593 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: ts: rewrite/split IOD parsing

Fixes read overflows.
parent 762ddf5b
...@@ -227,6 +227,7 @@ libplaylist_plugin_la_SOURCES = \ ...@@ -227,6 +227,7 @@ libplaylist_plugin_la_SOURCES = \
demux_LTLIBRARIES += libplaylist_plugin.la demux_LTLIBRARIES += libplaylist_plugin.la
libts_plugin_la_SOURCES = demux/ts.c \ libts_plugin_la_SOURCES = demux/ts.c \
demux/mpeg4_iod.c demux/mpeg4_iod.h \
mux/mpeg/csa.c mux/mpeg/dvbpsi_compat.h \ mux/mpeg/csa.c mux/mpeg/dvbpsi_compat.h \
mux/mpeg/streams.h mux/mpeg/tables.c mux/mpeg/tables.h \ mux/mpeg/streams.h mux/mpeg/tables.c mux/mpeg/tables.h \
mux/mpeg/tsutil.c mux/mpeg/tsutil.h \ mux/mpeg/tsutil.c mux/mpeg/tsutil.h \
......
/*****************************************************************************
* mpeg4_iod.c: ISO 14496-1 IOD and parsers
*****************************************************************************
* Copyright (C) 2004-2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include "mpeg4_iod.h"
//#define IOD_DEBUG 1
static void iod_debug( vlc_object_t *p_object, const char *format, ... )
{
#ifdef IOD_DEBUG
va_list ap;
va_start(ap, format);
msg_GenericVa( p_object, VLC_MSG_DBG, format, ap );
va_end(ap);
#else
VLC_UNUSED(format);
VLC_UNUSED(p_object);
#endif
}
/*****************************************************************************
* MP4 specific functions (IOD parser)
*****************************************************************************/
static unsigned IODDescriptorLength( unsigned *pi_data, const uint8_t **pp_data )
{
unsigned int i_b;
unsigned int i_len = 0;
if(*pi_data == 0)
return 0;
do
{
i_b = **pp_data;
(*pp_data)++;
(*pi_data)--;
i_len = ( i_len << 7 ) + ( i_b&0x7f );
} while( i_b&0x80 && *pi_data > 0 );
if (i_len > *pi_data)
i_len = *pi_data;
return i_len;
}
static unsigned IODGetBytes( unsigned *pi_data, const uint8_t **pp_data, size_t bytes )
{
unsigned res = 0;
while( *pi_data > 0 && bytes-- )
{
res <<= 8;
res |= **pp_data;
(*pp_data)++;
(*pi_data)--;
}
return res;
}
static char* IODGetURL( unsigned *pi_data, const uint8_t **pp_data )
{
unsigned len = IODGetBytes( pi_data, pp_data, 1 );
if (len > *pi_data)
len = *pi_data;
char *url = strndup( (char*)*pp_data, len );
*pp_data += len;
*pi_data -= len;
return url;
}
#define IODTag_ObjectDescr 0x01
#define IODTag_InitialObjectDescr 0x02
#define IODTag_ESDescr 0x03
#define IODTag_DecConfigDescr 0x04
#define IODTag_DecSpecificDescr 0x05
#define IODTag_SLDescr 0x06
/* Unified pointer for read helper */
typedef union
{
iod_descriptor_t *p_iod;
es_mpeg4_descriptor_t *es_descr;
decoder_config_descriptor_t *p_dec_config;
} iod_read_params_t;
static uint8_t IOD_Desc_Read( vlc_object_t *, unsigned *, const uint8_t **, uint8_t, uint8_t, iod_read_params_t params );
static bool IOD_SLDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
iod_read_params_t params )
{
VLC_UNUSED(p_object);
VLC_UNUSED(i_data);
VLC_UNUSED(p_data);
VLC_UNUSED(params);
return true;
}
static bool IOD_DecSpecificDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
iod_read_params_t params )
{
VLC_UNUSED(p_object);
decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
p_dec_config->p_extra = malloc( i_data );
if( p_dec_config->p_extra )
{
p_dec_config->i_extra = i_data;
memcpy( p_dec_config->p_extra, p_data, p_dec_config->i_extra );
}
return !!p_dec_config->i_extra;
}
static bool IOD_DecConfigDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
iod_read_params_t params )
{
decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
if( i_data < 13 )
return false;
p_dec_config->i_objectTypeIndication = IODGetBytes( &i_data, &p_data, 1 );
uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
p_dec_config->i_streamType = i_flags >> 2;
IODGetBytes( &i_data, &p_data, 3 ); /* bufferSizeDB */
IODGetBytes( &i_data, &p_data, 4 ); /* maxBitrate */
IODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */
/* DecoderSpecificDescr */
IOD_Desc_Read( p_object, &i_data, &p_data,
IODTag_DecSpecificDescr, 1, params );
iod_debug( p_object, " * read decoder objecttype: %x streamtype:%x extra: %u",
p_dec_config->i_objectTypeIndication, p_dec_config->i_streamType, p_dec_config->i_extra );
/* ProfileLevelIndicator [0..255] */
return true;
}
static bool IOD_ESDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
iod_read_params_t params )
{
es_mpeg4_descriptor_t *es_descr = params.es_descr;
if ( i_data < 3 )
return false;
es_descr->i_es_id = IODGetBytes( &i_data, &p_data, 2 );
uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
if( ( i_flags >> 7 )&0x01 )
{
if ( i_data < 2 )
return false;
IODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */
}
if( (i_flags >> 6) & 0x01 )
es_descr->psz_url = IODGetURL( &i_data, &p_data );
if( ( i_flags >> 5 )&0x01 )
{
if ( i_data < 2 )
return false;
IODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */
}
iod_debug( p_object, " * read ES Descriptor for es id %"PRIx16, es_descr->i_es_id );
/* DecoderConfigDescr */
params.p_dec_config = &es_descr->dec_descr;
if ( 1 != IOD_Desc_Read( p_object, &i_data, &p_data,
IODTag_DecConfigDescr, 1, params ) )
return false;
/* SLDescr */
IOD_Desc_Read( p_object, &i_data, &p_data, IODTag_SLDescr, 1, params );
/* IPI / IP / IPMP ... */
es_descr->b_ok = true;
return true;
}
static bool IOD_InitialObjectDesc_Read( vlc_object_t *p_object, unsigned i_data,
const uint8_t *p_data, iod_read_params_t params )
{
iod_descriptor_t *p_iod = params.p_iod;
if( i_data < 3 + 5 + 2 )
return false;
uint16_t i_object_descriptor_id = ( IODGetBytes( &i_data, &p_data, 1 ) << 2 );
uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
i_object_descriptor_id |= i_flags >> 6;
iod_debug( p_object, " * ObjectDescriptorID: %"PRIu16, i_object_descriptor_id );
iod_debug( p_object, " * includeInlineProfileLevel flag: 0x%"PRIx8, ( i_flags >> 4 )&0x01 );
if ( (i_flags >> 5) & 0x01 )
{
p_iod->psz_url = IODGetURL( &i_data, &p_data );
iod_debug( p_object, " * URL: %s", p_iod->psz_url );
return true; /* leaves out unparsed remaining extdescr */
}
if( i_data < 5 + 2 ) /* at least one ES desc */
return false;
/* Profile Level Indication */
IODGetBytes( &i_data, &p_data, 1 ); /* OD */
IODGetBytes( &i_data, &p_data, 1 ); /* scene */
IODGetBytes( &i_data, &p_data, 1 ); /* audio */
IODGetBytes( &i_data, &p_data, 1 ); /* visual */
IODGetBytes( &i_data, &p_data, 1 ); /* graphics */
/* Now read */
/* 1..255 ESdescr */
uint8_t i_desc_count = IOD_Desc_Read( p_object, &i_data, &p_data,
IODTag_ESDescr, ES_DESCRIPTOR_COUNT, params );
if( i_desc_count == 0 )
{
iod_debug( p_object, " * missing ES Descriptor" );
return false;
}
/* 0..255 OCIdescr */
/* 0..255 IPMPdescpointer */
/* 0..255 IPMPdesc */
/* 0..1 IPMPtoollistdesc */
/* 0..255 Extensiondescr */
return true;
}
static uint8_t IOD_Desc_Read( vlc_object_t *p_object, unsigned *pi_data, const uint8_t **pp_data,
uint8_t i_target_tag, uint8_t i_max_desc, iod_read_params_t params )
{
uint8_t i_read_count = 0;
for (unsigned i = 0; *pi_data > 2 && i < i_max_desc; i++)
{
const uint8_t i_tag = IODGetBytes( pi_data, pp_data, 1 );
const unsigned i_length = IODDescriptorLength( pi_data, pp_data );
if( i_target_tag != i_tag || i_length > *pi_data )
break;
unsigned i_descriptor_data = i_length;
const uint8_t *p_descriptor_data = *pp_data;
iod_debug( p_object, " Reading descriptor 0x%"PRIx8": found tag 0x%"PRIx8" left %d",
i_target_tag, i_tag, *pi_data );
switch( i_tag )
{
case IODTag_InitialObjectDescr:
{
/* iod_descriptor_t *p_iod = (iod_descriptor_t *) param; */
if ( !IOD_InitialObjectDesc_Read( p_object, i_descriptor_data,
p_descriptor_data, params ) )
{};
break;
}
case IODTag_ESDescr: /**/
{
iod_descriptor_t *p_iod = params.p_iod;
params.es_descr = &p_iod->es_descr[i_read_count];
if ( !IOD_ESDesc_Read( p_object, i_descriptor_data,
p_descriptor_data, params ) )
{};
break;
}
case IODTag_DecConfigDescr:
{
if ( !IOD_DecConfigDesc_Read( p_object, i_descriptor_data,
p_descriptor_data, params ) )
{};
break;
}
case IODTag_DecSpecificDescr:
{
if ( !IOD_DecSpecificDesc_Read( p_object, i_descriptor_data,
p_descriptor_data, params ) )
{};
break;
}
case IODTag_SLDescr:
{
if ( !IOD_SLDesc_Read( p_object, i_descriptor_data,
p_descriptor_data, params ) )
{};
break;
}
default:
iod_debug( p_object, "trying to read unsupported descriptor" );
break;
}
*pp_data += i_length;
*pi_data -= i_length;
i_read_count++;
}
return i_read_count;
}
iod_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data )
{
if( i_data < 4 )
return NULL;
uint8_t i_iod_scope = IODGetBytes( &i_data, &p_data, 1 ); /* scope */
uint8_t i_iod_label = IODGetBytes( &i_data, &p_data, 1 );
if( i_iod_label == 0x02 ) /* old vlc's buggy implementation of the IOD_descriptor */
{
i_iod_label = i_iod_scope;
i_iod_scope = 0x10; /* Add the missing front iod scope byte */
i_data++; p_data--; /* next byte must be tag */
}
iod_debug( p_object, " * iod label:0x%"PRIx8" scope:0x%"PRIx8,
i_iod_label, i_iod_scope );
if( i_iod_scope != 0x10 && i_iod_scope != 0x11 ) /* Uniqueness in program or transport */
{
iod_debug( p_object, " * can't handle reserved scope 0x%"PRIx8, i_iod_scope );
return NULL;
}
/* Initial Object Descriptor must follow */
iod_descriptor_t *p_iod = calloc( 1, sizeof( iod_descriptor_t ) );
if( !p_iod )
return NULL;
/* IOD_InitialObjectDescrTag Parsing */
iod_read_params_t params;
params.p_iod = p_iod;
if ( 1 != IOD_Desc_Read( p_object, &i_data, &p_data,
IODTag_InitialObjectDescr, 1, params ) )
{
iod_debug( p_object, " cannot read InitialObjectDescr" );
free( p_iod );
return NULL;
}
return p_iod;
}
void IODFree( iod_descriptor_t *p_iod )
{
if( p_iod->psz_url )
{
free( p_iod->psz_url );
free( p_iod );
return;
}
for( int i = 0; i < 255; i++ )
{
#define es_descr p_iod->es_descr[i]
if( es_descr.b_ok )
{
if( es_descr.psz_url )
free( es_descr.psz_url );
else
free( es_descr.dec_descr.p_extra );
}
#undef es_descr
}
free( p_iod );
}
/*****************************************************************************
* mpeg4_iod.h: ISO 14496-1 IOD and parsers
*****************************************************************************
* Copyright (C) 2004-2015 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#define ES_DESCRIPTOR_COUNT 255
typedef struct
{
uint8_t i_objectTypeIndication;
uint8_t i_streamType;
unsigned i_extra;
uint8_t *p_extra;
} decoder_config_descriptor_t;
typedef struct
{
bool b_ok;
uint16_t i_es_id;
char *psz_url;
decoder_config_descriptor_t dec_descr;
} es_mpeg4_descriptor_t;
typedef struct
{
/* IOD */
char *psz_url;
es_mpeg4_descriptor_t es_descr[ES_DESCRIPTOR_COUNT];
} iod_descriptor_t;
iod_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data );
void IODFree( iod_descriptor_t *p_iod );
...@@ -70,18 +70,7 @@ ...@@ -70,18 +70,7 @@
#include "opus.h" #include "opus.h"
#undef TS_DEBUG #include "mpeg4_iod.h"
VLC_FORMAT(1, 2) static void ts_debug(const char *format, ...)
{
#ifdef TS_DEBUG
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
#else
(void)format;
#endif
}
#ifdef HAVE_ARIBB24 #ifdef HAVE_ARIBB24
#include <aribb24/aribb24.h> #include <aribb24/aribb24.h>
...@@ -204,37 +193,6 @@ static const char *const ppsz_teletext_type[] = { ...@@ -204,37 +193,6 @@ static const char *const ppsz_teletext_type[] = {
typedef struct ts_pid_t ts_pid_t; typedef struct ts_pid_t ts_pid_t;
typedef struct
{
uint8_t i_objectTypeIndication;
uint8_t i_streamType;
unsigned i_extra;
uint8_t *p_extra;
} decoder_config_descriptor_t;
typedef struct
{
bool b_ok;
uint16_t i_es_id;
char *psz_url;
decoder_config_descriptor_t dec_descr;
} es_mpeg4_descriptor_t;
#define ES_DESCRIPTOR_COUNT 255
typedef struct
{
/* IOD */
char *psz_url;
es_mpeg4_descriptor_t es_descr[ES_DESCRIPTOR_COUNT];
} iod_descriptor_t;
typedef struct typedef struct
{ {
int i_version; int i_version;
...@@ -521,8 +479,6 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *, block_t * ); ...@@ -521,8 +479,6 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *, block_t * );
static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * ); static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
static int64_t TimeStampWrapAround( ts_pmt_t *, int64_t ); static int64_t TimeStampWrapAround( ts_pmt_t *, int64_t );
static void IODFree( iod_descriptor_t * );
#define TS_USER_PMT_NUMBER (0) #define TS_USER_PMT_NUMBER (0)
static int UserPmt( demux_t *p_demux, const char * ); static int UserPmt( demux_t *p_demux, const char * );
...@@ -3400,227 +3356,6 @@ static void PIDFillFormat( es_format_t *fmt, int i_stream_type ) ...@@ -3400,227 +3356,6 @@ static void PIDFillFormat( es_format_t *fmt, int i_stream_type )
fmt->b_packetized = false; fmt->b_packetized = false;
} }
/*****************************************************************************
* MP4 specific functions (IOD parser)
*****************************************************************************/
static unsigned IODDescriptorLength( unsigned *pi_data, uint8_t **pp_data )
{
unsigned int i_b;
unsigned int i_len = 0;
do
{
i_b = **pp_data;
(*pp_data)++;
(*pi_data)--;
i_len = ( i_len << 7 ) + ( i_b&0x7f );
} while( i_b&0x80 && *pi_data > 0 );
if (i_len > *pi_data)
i_len = *pi_data;
return i_len;
}
static unsigned IODGetBytes( unsigned *pi_data, uint8_t **pp_data, size_t bytes )
{
unsigned res = 0;
while( *pi_data > 0 && bytes-- )
{
res <<= 8;
res |= **pp_data;
(*pp_data)++;
(*pi_data)--;
}
return res;
}
static char* IODGetURL( unsigned *pi_data, uint8_t **pp_data )
{
unsigned len = IODGetBytes( pi_data, pp_data, 1 );
if (len > *pi_data)
len = *pi_data;
char *url = strndup( (char*)*pp_data, len );
*pp_data += len;
*pi_data -= len;
return url;
}
static iod_descriptor_t *IODNew( unsigned i_data, uint8_t *p_data )
{
uint8_t i_iod_tag, i_iod_label, byte1, byte2, byte3;
iod_descriptor_t *p_iod = calloc( 1, sizeof( iod_descriptor_t ) );
if( !p_iod )
return NULL;
if( i_data < 3 )
{
return p_iod;
}
byte1 = IODGetBytes( &i_data, &p_data, 1 );
byte2 = IODGetBytes( &i_data, &p_data, 1 );
byte3 = IODGetBytes( &i_data, &p_data, 1 );
if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor
{
i_iod_label = byte1;
i_iod_tag = byte2;
}
else //correct implementation of the IOD_descriptor
{
i_iod_label = byte2;
i_iod_tag = byte3;
}
ts_debug( "\n* iod label:%d tag:0x%x", i_iod_label, i_iod_tag );
if( i_iod_tag != 0x02 )
{
ts_debug( "\n ERR: tag %02x != 0x02", i_iod_tag );
return p_iod;
}
IODDescriptorLength( &i_data, &p_data );
uint16_t i_od_id = ( IODGetBytes( &i_data, &p_data, 1 ) << 2 );
uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
i_od_id |= i_flags >> 6;
ts_debug( "\n* od_id:%d", i_od_id );
ts_debug( "\n* includeInlineProfileLevel flag:%d", ( i_flags >> 4 )&0x01 );
if ((i_flags >> 5) & 0x01)
{
p_iod->psz_url = IODGetURL( &i_data, &p_data );
ts_debug( "\n* url string:%s", p_iod->psz_url );
ts_debug( "\n*****************************\n" );
return p_iod;
}
else
{
p_iod->psz_url = NULL;
}
/* Profile Level Indication */
IODGetBytes( &i_data, &p_data, 1 ); /* OD */
IODGetBytes( &i_data, &p_data, 1 ); /* scene */
IODGetBytes( &i_data, &p_data, 1 ); /* audio */
IODGetBytes( &i_data, &p_data, 1 ); /* visual */
IODGetBytes( &i_data, &p_data, 1 ); /* graphics */
unsigned i_length = 0;
unsigned i_data_sav = i_data;
uint8_t *p_data_sav = p_data;
for (unsigned i = 0; i_data > 0 && i < ES_DESCRIPTOR_COUNT; i++)
{
es_mpeg4_descriptor_t *es_descr = &p_iod->es_descr[i];
p_data = p_data_sav + i_length;
i_data = i_data_sav - i_length;
uint8_t i_tag = IODGetBytes( &i_data, &p_data, 1 );
i_length = IODDescriptorLength( &i_data, &p_data );
i_data_sav = i_data;
p_data_sav = p_data;
i_data = i_length;
if ( i_tag != 0x03 )
{
ts_debug( "\n* - OD tag:0x%x Unsupported", i_tag );
continue;
}
es_descr->i_es_id = IODGetBytes( &i_data, &p_data, 2 );
uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
bool b_streamDependenceFlag = ( i_flags >> 7 )&0x01;
if( b_streamDependenceFlag )
IODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */
if( (i_flags >> 6) & 0x01 )
es_descr->psz_url = IODGetURL( &i_data, &p_data );
bool b_OCRStreamFlag = ( i_flags >> 5 )&0x01;
if( b_OCRStreamFlag )
IODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */
if( IODGetBytes( &i_data, &p_data, 1 ) != 0x04 )
{
ts_debug( "\n* ERR missing DecoderConfigDescr" );
continue;
}
unsigned i_config_desc_length = IODDescriptorLength( &i_data, &p_data ); /* DecoderConfigDescr_length */
decoder_config_descriptor_t *dec_descr = &es_descr->dec_descr;
dec_descr->i_objectTypeIndication = IODGetBytes( &i_data, &p_data, 1 );
i_flags = IODGetBytes( &i_data, &p_data, 1 );
dec_descr->i_streamType = i_flags >> 2;
IODGetBytes( &i_data, &p_data, 3); /* bufferSizeDB */
IODGetBytes( &i_data, &p_data, 4); /* maxBitrate */
IODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */
if( i_config_desc_length > 13 && IODGetBytes( &i_data, &p_data, 1 ) == 0x05 )
{
dec_descr->i_extra = IODDescriptorLength( &i_data, &p_data );
if( dec_descr->i_extra > 0 )
{
dec_descr->p_extra = xmalloc( dec_descr->i_extra );
memcpy(dec_descr->p_extra, p_data, dec_descr->i_extra);
p_data += dec_descr->i_extra;
i_data -= dec_descr->i_extra;
}
}
else
{
dec_descr->i_extra = 0;
dec_descr->p_extra = NULL;
}
if( IODGetBytes( &i_data, &p_data, 1 ) != 0x06 )
{
ts_debug( "\n* ERR missing SLConfigDescr" );
continue;
}
IODDescriptorLength( &i_data, &p_data ); /* SLConfigDescr_length */
switch( IODGetBytes( &i_data, &p_data, 1 ) /* predefined */ )
{
default:
ts_debug( "\n* ERR unsupported SLConfigDescr predefined" );
case 0x01:
// FIXME
break;
}
es_descr->b_ok = true;
}
return p_iod;
}
static void IODFree( iod_descriptor_t *p_iod )
{
if( p_iod->psz_url )
{
free( p_iod->psz_url );
free( p_iod );
return;
}
for( int i = 0; i < 255; i++ )
{
#define es_descr p_iod->es_descr[i]
if( es_descr.b_ok )
{
if( es_descr.psz_url )
free( es_descr.psz_url );
else
free( es_descr.dec_descr.p_extra );
}
#undef es_descr
}
free( p_iod );
}
/**************************************************************************** /****************************************************************************
**************************************************************************** ****************************************************************************
** libdvbpsi callbacks ** libdvbpsi callbacks
...@@ -5301,7 +5036,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt ) ...@@ -5301,7 +5036,7 @@ static void PMTCallBack( void *data, dvbpsi_pmt_t *p_dvbpsipmt )
{ {
case 0x1d: /* We have found an IOD descriptor */ case 0x1d: /* We have found an IOD descriptor */
msg_Dbg( p_demux, " * PMT descriptor : IOD (0x1d)" ); msg_Dbg( p_demux, " * PMT descriptor : IOD (0x1d)" );
p_pmt->iod = IODNew( p_dr->i_length, p_dr->p_data ); p_pmt->iod = IODNew( VLC_OBJECT(p_demux), p_dr->i_length, p_dr->p_data );
break; break;
case 0x9: case 0x9:
......
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