1 /*****************************************************************************
2 * mpeg4_iod.c: ISO 14496-1 IOD and parsers
3 *****************************************************************************
4 * Copyright (C) 2004-2015 VLC authors and VideoLAN
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 /*****************************************************************************
23 *****************************************************************************/
29 #include <vlc_common.h>
32 #include "mpeg4_iod.h"
35 static void iod_debug( vlc_object_t *p_object, const char *format, ... )
40 msg_GenericVa( p_object, VLC_MSG_DBG, format, ap );
48 /*****************************************************************************
49 * MP4 specific functions (IOD parser)
50 *****************************************************************************/
51 static unsigned IODDescriptorLength( unsigned *pi_data, const uint8_t **pp_data )
54 unsigned int i_len = 0;
64 i_len = ( i_len << 7 ) + ( i_b&0x7f );
66 } while( i_b&0x80 && *pi_data > 0 );
74 static unsigned IODGetBytes( unsigned *pi_data, const uint8_t **pp_data, size_t bytes )
77 while( *pi_data > 0 && bytes-- )
88 static char* IODGetURL( unsigned *pi_data, const uint8_t **pp_data )
90 unsigned len = IODGetBytes( pi_data, pp_data, 1 );
93 char *url = strndup( (char*)*pp_data, len );
99 #define IODTag_ObjectDescr 0x01
100 #define IODTag_InitialObjectDescr 0x02
101 #define IODTag_ESDescr 0x03
102 #define IODTag_DecConfigDescr 0x04
103 #define IODTag_DecSpecificDescr 0x05
104 #define IODTag_SLDescr 0x06
106 /* Unified pointer for read helper */
109 iod_descriptor_t *p_iod;
110 es_mpeg4_descriptor_t *es_descr;
111 decoder_config_descriptor_t *p_dec_config;
112 sl_config_descriptor_t *sl_descr;
115 static uint8_t IOD_Desc_Read( vlc_object_t *, unsigned *, const uint8_t **, uint8_t, uint8_t, iod_read_params_t params );
117 #define SL_Predefined_Custom 0x00
118 #define SL_Predefined_NULL 0x01
119 #define SL_Predefined_MP4 0x02
120 static bool IOD_SLDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
121 iod_read_params_t params )
123 sl_config_descriptor_t *sl_descr = params.sl_descr;
125 uint8_t i_predefined = IODGetBytes( &i_data, &p_data, 1 );
126 switch( i_predefined )
128 case SL_Predefined_Custom:
131 sl_descr->i_flags = IODGetBytes( &i_data, &p_data, 1 );
132 sl_descr->i_timestamp_resolution = IODGetBytes( &i_data, &p_data, 4 );
133 sl_descr->i_OCR_resolution = IODGetBytes( &i_data, &p_data, 4 );
134 sl_descr->i_timestamp_length = IODGetBytes( &i_data, &p_data, 4 );
135 sl_descr->i_OCR_length = IODGetBytes( &i_data, &p_data, 1 );
136 sl_descr->i_AU_length = IODGetBytes( &i_data, &p_data, 1 );
137 sl_descr->i_instant_bitrate_length = IODGetBytes( &i_data, &p_data, 1 );
138 uint16_t i16 = IODGetBytes( &i_data, &p_data, 2 );
139 sl_descr->i_degradation_priority_length = i16 >> 12;
140 sl_descr->i_AU_seqnum_length = (i16 >> 7) & 0x1f;
141 sl_descr->i_packet_seqnum_length = (i16 >> 2) & 0x1f;
143 case SL_Predefined_NULL:
144 memset( sl_descr, 0, sizeof(*sl_descr) );
145 sl_descr->i_timestamp_resolution = 1000;
146 sl_descr->i_timestamp_length = 32;
148 case SL_Predefined_MP4:
149 memset( sl_descr, 0, sizeof(*sl_descr) );
150 sl_descr->i_flags = USE_TIMESTAMPS_FLAG;
157 if( sl_descr->i_flags & USE_DURATION_FLAG )
161 sl_descr->i_timescale = IODGetBytes( &i_data, &p_data, 4 );
162 sl_descr->i_accessunit_duration = IODGetBytes( &i_data, &p_data, 2 );
163 sl_descr->i_compositionunit_duration = IODGetBytes( &i_data, &p_data, 2 );
166 if( (sl_descr->i_flags & USE_TIMESTAMPS_FLAG) == 0 )
169 bs_init( &s, p_data, i_data );
170 sl_descr->i_startdecoding_timestamp = bs_read( &s, sl_descr->i_timestamp_length );
171 sl_descr->i_startcomposition_timestamp = bs_read( &s, sl_descr->i_timestamp_length );
174 iod_debug( p_object, " * read sl desc predefined: 0x%x", i_predefined );
178 static bool IOD_DecSpecificDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
179 iod_read_params_t params )
181 VLC_UNUSED(p_object);
182 decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
184 p_dec_config->p_extra = malloc( i_data );
185 if( p_dec_config->p_extra )
187 p_dec_config->i_extra = i_data;
188 memcpy( p_dec_config->p_extra, p_data, p_dec_config->i_extra );
191 return !!p_dec_config->i_extra;
194 static bool IOD_DecConfigDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
195 iod_read_params_t params )
197 decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
202 p_dec_config->i_objectTypeIndication = IODGetBytes( &i_data, &p_data, 1 );
203 uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
204 p_dec_config->i_streamType = i_flags >> 2;
206 IODGetBytes( &i_data, &p_data, 3 ); /* bufferSizeDB */
207 IODGetBytes( &i_data, &p_data, 4 ); /* maxBitrate */
208 IODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */
210 /* DecoderSpecificDescr */
211 IOD_Desc_Read( p_object, &i_data, &p_data,
212 IODTag_DecSpecificDescr, 1, params );
214 iod_debug( p_object, " * read decoder objecttype: %x streamtype:%x extra: %u",
215 p_dec_config->i_objectTypeIndication, p_dec_config->i_streamType, p_dec_config->i_extra );
216 /* ProfileLevelIndicator [0..255] */
220 static bool IOD_ESDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data,
221 iod_read_params_t params )
223 es_mpeg4_descriptor_t *es_descr = params.es_descr;
227 es_descr->i_es_id = IODGetBytes( &i_data, &p_data, 2 );
228 uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
230 if( ( i_flags >> 7 )&0x01 )
234 IODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */
237 if( (i_flags >> 6) & 0x01 )
238 es_descr->psz_url = IODGetURL( &i_data, &p_data );
240 if( ( i_flags >> 5 )&0x01 )
244 IODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */
247 iod_debug( p_object, " * read ES Descriptor for es id %"PRIx16, es_descr->i_es_id );
249 /* DecoderConfigDescr */
250 params.p_dec_config = &es_descr->dec_descr;
251 if ( 1 != IOD_Desc_Read( p_object, &i_data, &p_data,
252 IODTag_DecConfigDescr, 1, params ) )
256 params.sl_descr = &es_descr->sl_descr;
257 IOD_Desc_Read( p_object, &i_data, &p_data, IODTag_SLDescr, 1, params );
259 /* IPI / IP / IPMP ... */
261 es_descr->b_ok = true;
266 static bool IOD_InitialObjectDesc_Read( vlc_object_t *p_object, unsigned i_data,
267 const uint8_t *p_data, iod_read_params_t params )
269 iod_descriptor_t *p_iod = params.p_iod;
270 if( i_data < 3 + 5 + 2 )
273 uint16_t i_object_descriptor_id = ( IODGetBytes( &i_data, &p_data, 1 ) << 2 );
274 uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
275 i_object_descriptor_id |= i_flags >> 6;
277 iod_debug( p_object, " * ObjectDescriptorID: %"PRIu16, i_object_descriptor_id );
278 iod_debug( p_object, " * includeInlineProfileLevel flag: 0x%"PRIx8, ( i_flags >> 4 )&0x01 );
279 if ( (i_flags >> 5) & 0x01 )
281 p_iod->psz_url = IODGetURL( &i_data, &p_data );
282 iod_debug( p_object, " * URL: %s", p_iod->psz_url );
283 return true; /* leaves out unparsed remaining extdescr */
286 if( i_data < 5 + 2 ) /* at least one ES desc */
289 /* Profile Level Indication */
290 IODGetBytes( &i_data, &p_data, 1 ); /* OD */
291 IODGetBytes( &i_data, &p_data, 1 ); /* scene */
292 IODGetBytes( &i_data, &p_data, 1 ); /* audio */
293 IODGetBytes( &i_data, &p_data, 1 ); /* visual */
294 IODGetBytes( &i_data, &p_data, 1 ); /* graphics */
298 uint8_t i_desc_count = IOD_Desc_Read( p_object, &i_data, &p_data,
299 IODTag_ESDescr, ES_DESCRIPTOR_COUNT, params );
300 if( i_desc_count == 0 )
302 iod_debug( p_object, " * missing ES Descriptor" );
306 /* 0..255 OCIdescr */
307 /* 0..255 IPMPdescpointer */
308 /* 0..255 IPMPdesc */
309 /* 0..1 IPMPtoollistdesc */
310 /* 0..255 Extensiondescr */
315 static uint8_t IOD_Desc_Read( vlc_object_t *p_object, unsigned *pi_data, const uint8_t **pp_data,
316 uint8_t i_target_tag, uint8_t i_max_desc, iod_read_params_t params )
318 uint8_t i_read_count = 0;
320 for (unsigned i = 0; *pi_data > 2 && i < i_max_desc; i++)
322 const uint8_t i_tag = IODGetBytes( pi_data, pp_data, 1 );
323 const unsigned i_length = IODDescriptorLength( pi_data, pp_data );
324 if( i_target_tag != i_tag || i_length > *pi_data )
327 unsigned i_descriptor_data = i_length;
328 const uint8_t *p_descriptor_data = *pp_data;
330 iod_debug( p_object, " Reading descriptor 0x%"PRIx8": found tag 0x%"PRIx8" left %d",
331 i_target_tag, i_tag, *pi_data );
334 case IODTag_InitialObjectDescr:
336 /* iod_descriptor_t *p_iod = (iod_descriptor_t *) param; */
337 if ( !IOD_InitialObjectDesc_Read( p_object, i_descriptor_data,
338 p_descriptor_data, params ) )
343 case IODTag_ESDescr: /**/
345 iod_descriptor_t *p_iod = params.p_iod;
346 params.es_descr = &p_iod->es_descr[i_read_count];
347 if ( !IOD_ESDesc_Read( p_object, i_descriptor_data,
348 p_descriptor_data, params ) )
353 case IODTag_DecConfigDescr:
355 if ( !IOD_DecConfigDesc_Read( p_object, i_descriptor_data,
356 p_descriptor_data, params ) )
361 case IODTag_DecSpecificDescr:
363 if ( !IOD_DecSpecificDesc_Read( p_object, i_descriptor_data,
364 p_descriptor_data, params ) )
371 if ( !IOD_SLDesc_Read( p_object, i_descriptor_data,
372 p_descriptor_data, params ) )
378 iod_debug( p_object, "trying to read unsupported descriptor" );
382 *pp_data += i_length;
383 *pi_data -= i_length;
391 iod_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data )
396 uint8_t i_iod_scope = IODGetBytes( &i_data, &p_data, 1 ); /* scope */
397 uint8_t i_iod_label = IODGetBytes( &i_data, &p_data, 1 );
398 if( i_iod_label == 0x02 ) /* old vlc's buggy implementation of the IOD_descriptor */
400 i_iod_label = i_iod_scope;
401 i_iod_scope = 0x10; /* Add the missing front iod scope byte */
402 i_data++; p_data--; /* next byte must be tag */
405 iod_debug( p_object, " * iod label:0x%"PRIx8" scope:0x%"PRIx8,
406 i_iod_label, i_iod_scope );
408 if( i_iod_scope != 0x10 && i_iod_scope != 0x11 ) /* Uniqueness in program or transport */
410 iod_debug( p_object, " * can't handle reserved scope 0x%"PRIx8, i_iod_scope );
414 /* Initial Object Descriptor must follow */
415 iod_descriptor_t *p_iod = calloc( 1, sizeof( iod_descriptor_t ) );
419 /* IOD_InitialObjectDescrTag Parsing */
420 iod_read_params_t params;
421 params.p_iod = p_iod;
422 if ( 1 != IOD_Desc_Read( p_object, &i_data, &p_data,
423 IODTag_InitialObjectDescr, 1, params ) )
425 iod_debug( p_object, " cannot read InitialObjectDescr" );
433 void IODFree( iod_descriptor_t *p_iod )
437 free( p_iod->psz_url );
442 for( int i = 0; i < 255; i++ )
444 #define es_descr p_iod->es_descr[i]
447 if( es_descr.psz_url )
448 free( es_descr.psz_url );
450 free( es_descr.dec_descr.p_extra );