]> git.sesse.net Git - vlc/blob - modules/demux/mpeg4_iod.c
demux: ts: parse SL config
[vlc] / modules / demux / mpeg4_iod.c
1 /*****************************************************************************
2  * mpeg4_iod.c: ISO 14496-1 IOD and parsers
3  *****************************************************************************
4  * Copyright (C) 2004-2015 VLC authors and VideoLAN
5  *
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.
10  *
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.
15  *
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  *****************************************************************************/
20
21 /*****************************************************************************
22  * Preamble
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <vlc_common.h>
30 #include <vlc_bits.h>
31
32 #include "mpeg4_iod.h"
33
34 //#define IOD_DEBUG 1
35 static void iod_debug( vlc_object_t *p_object, const char *format, ... )
36 {
37 #ifdef IOD_DEBUG
38     va_list ap;
39     va_start(ap, format);
40     msg_GenericVa( p_object, VLC_MSG_DBG, format, ap );
41     va_end(ap);
42 #else
43     VLC_UNUSED(format);
44     VLC_UNUSED(p_object);
45 #endif
46 }
47
48 /*****************************************************************************
49  * MP4 specific functions (IOD parser)
50  *****************************************************************************/
51 static unsigned IODDescriptorLength( unsigned *pi_data, const uint8_t **pp_data )
52 {
53     unsigned int i_b;
54     unsigned int i_len = 0;
55
56     if(*pi_data == 0)
57         return 0;
58
59     do
60     {
61         i_b = **pp_data;
62         (*pp_data)++;
63         (*pi_data)--;
64         i_len = ( i_len << 7 ) + ( i_b&0x7f );
65
66     } while( i_b&0x80 && *pi_data > 0 );
67
68     if (i_len > *pi_data)
69         i_len = *pi_data;
70
71     return i_len;
72 }
73
74 static unsigned IODGetBytes( unsigned *pi_data, const uint8_t **pp_data, size_t bytes )
75 {
76     unsigned res = 0;
77     while( *pi_data > 0 && bytes-- )
78     {
79         res <<= 8;
80         res |= **pp_data;
81         (*pp_data)++;
82         (*pi_data)--;
83     }
84
85     return res;
86 }
87
88 static char* IODGetURL( unsigned *pi_data, const uint8_t **pp_data )
89 {
90     unsigned len = IODGetBytes( pi_data, pp_data, 1 );
91     if (len > *pi_data)
92         len = *pi_data;
93     char *url = strndup( (char*)*pp_data, len );
94     *pp_data += len;
95     *pi_data -= len;
96     return url;
97 }
98
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
105
106 /* Unified pointer for read helper */
107 typedef union
108 {
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;
113 } iod_read_params_t;
114
115 static uint8_t IOD_Desc_Read( vlc_object_t *, unsigned *, const uint8_t **, uint8_t, uint8_t, iod_read_params_t params );
116
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 )
122 {
123     sl_config_descriptor_t *sl_descr = params.sl_descr;
124
125     uint8_t i_predefined = IODGetBytes( &i_data, &p_data, 1 );
126     switch( i_predefined )
127     {
128     case SL_Predefined_Custom:
129         if( i_data < 15 )
130             return false;
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;
142         break;
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;
147         break;
148     case SL_Predefined_MP4:
149         memset( sl_descr, 0, sizeof(*sl_descr) );
150         sl_descr->i_flags = USE_TIMESTAMPS_FLAG;
151         break;
152     default:
153         /* reserved */
154         return false;
155     }
156
157     if( sl_descr->i_flags & USE_DURATION_FLAG )
158     {
159         if( i_data < 8 )
160             return false;
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 );
164     }
165
166     if( (sl_descr->i_flags & USE_TIMESTAMPS_FLAG) == 0 )
167     {
168         bs_t s;
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 );
172     }
173
174     iod_debug( p_object, "   * read sl desc predefined: 0x%x", i_predefined );
175     return true;
176 }
177
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 )
180 {
181     VLC_UNUSED(p_object);
182     decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
183
184     p_dec_config->p_extra = malloc( i_data );
185     if( p_dec_config->p_extra )
186     {
187         p_dec_config->i_extra = i_data;
188         memcpy( p_dec_config->p_extra, p_data, p_dec_config->i_extra );
189     }
190
191     return !!p_dec_config->i_extra;
192 }
193
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 )
196 {
197     decoder_config_descriptor_t *p_dec_config = params.p_dec_config;
198
199     if( i_data < 13 )
200         return false;
201
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;
205
206     IODGetBytes( &i_data, &p_data, 3 ); /* bufferSizeDB */
207     IODGetBytes( &i_data, &p_data, 4 ); /* maxBitrate */
208     IODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */
209
210     /* DecoderSpecificDescr */
211     IOD_Desc_Read( p_object, &i_data, &p_data,
212                    IODTag_DecSpecificDescr, 1, params );
213
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] */
217     return true;
218 }
219
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 )
222 {
223     es_mpeg4_descriptor_t *es_descr = params.es_descr;
224
225     if ( i_data < 3 )
226         return false;
227     es_descr->i_es_id = IODGetBytes( &i_data, &p_data, 2 );
228     uint8_t i_flags = IODGetBytes( &i_data, &p_data, 1 );
229
230     if( ( i_flags >> 7 )&0x01 )
231     {
232         if ( i_data < 2 )
233             return false;
234         IODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */
235     }
236
237     if( (i_flags >> 6) & 0x01 )
238         es_descr->psz_url = IODGetURL( &i_data, &p_data );
239
240     if( ( i_flags >> 5 )&0x01 )
241     {
242         if ( i_data < 2 )
243             return false;
244         IODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */
245     }
246
247     iod_debug( p_object, "   * read ES Descriptor for es id %"PRIx16, es_descr->i_es_id );
248
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 ) )
253         return false;
254
255     /* SLDescr */
256     params.sl_descr = &es_descr->sl_descr;
257     IOD_Desc_Read( p_object, &i_data, &p_data, IODTag_SLDescr, 1, params );
258
259     /* IPI / IP / IPMP ... */
260
261     es_descr->b_ok = true;
262
263     return true;
264 }
265
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 )
268 {
269     iod_descriptor_t *p_iod = params.p_iod;
270     if( i_data < 3 + 5 + 2 )
271         return false;
272
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;
276
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 )
280     {
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 */
284     }
285
286     if( i_data < 5 + 2 ) /* at least one ES desc */
287         return false;
288
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 */
295
296     /* Now read */
297     /* 1..255 ESdescr */
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 )
301     {
302         iod_debug( p_object, "   * missing ES Descriptor" );
303         return false;
304     }
305
306     /* 0..255 OCIdescr */
307     /* 0..255 IPMPdescpointer */
308     /* 0..255 IPMPdesc */
309     /* 0..1   IPMPtoollistdesc */
310     /* 0..255 Extensiondescr */
311
312     return true;
313 }
314
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 )
317 {
318     uint8_t i_read_count = 0;
319
320     for (unsigned i = 0; *pi_data > 2 && i < i_max_desc; i++)
321     {
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 )
325             break;
326
327         unsigned i_descriptor_data = i_length;
328         const uint8_t *p_descriptor_data = *pp_data;
329
330         iod_debug( p_object, "  Reading descriptor 0x%"PRIx8": found tag 0x%"PRIx8" left %d",
331                    i_target_tag, i_tag, *pi_data );
332         switch( i_tag )
333         {
334             case IODTag_InitialObjectDescr:
335             {
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 ) )
339                 {};
340                 break;
341             }
342
343             case IODTag_ESDescr: /**/
344             {
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 ) )
349                 {};
350                 break;
351             }
352
353             case IODTag_DecConfigDescr:
354             {
355                 if ( !IOD_DecConfigDesc_Read( p_object, i_descriptor_data,
356                                               p_descriptor_data, params ) )
357                 {};
358                 break;
359             }
360
361             case IODTag_DecSpecificDescr:
362             {
363                 if ( !IOD_DecSpecificDesc_Read( p_object, i_descriptor_data,
364                                                 p_descriptor_data, params ) )
365                 {};
366                 break;
367             }
368
369             case IODTag_SLDescr:
370             {
371                 if ( !IOD_SLDesc_Read( p_object, i_descriptor_data,
372                                        p_descriptor_data, params ) )
373                 {};
374                 break;
375             }
376
377             default:
378                 iod_debug( p_object, "trying to read unsupported descriptor" );
379                 break;
380         }
381
382         *pp_data += i_length;
383         *pi_data -= i_length;
384
385         i_read_count++;
386     }
387
388     return i_read_count;
389 }
390
391 iod_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data )
392 {
393     if( i_data < 4 )
394         return NULL;
395
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 */
399     {
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 */
403     }
404
405     iod_debug( p_object, "  * iod label:0x%"PRIx8" scope:0x%"PRIx8,
406                i_iod_label, i_iod_scope );
407
408     if( i_iod_scope != 0x10 && i_iod_scope != 0x11 ) /* Uniqueness in program or transport */
409     {
410         iod_debug( p_object, "  * can't handle reserved scope 0x%"PRIx8, i_iod_scope );
411         return NULL;
412     }
413
414     /* Initial Object Descriptor must follow */
415     iod_descriptor_t *p_iod = calloc( 1, sizeof( iod_descriptor_t ) );
416     if( !p_iod )
417         return NULL;
418
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 ) )
424     {
425         iod_debug( p_object, "   cannot read InitialObjectDescr" );
426         free( p_iod );
427         return NULL;
428     }
429
430     return p_iod;
431 }
432
433 void IODFree( iod_descriptor_t *p_iod )
434 {
435     if( p_iod->psz_url )
436     {
437         free( p_iod->psz_url );
438         free( p_iod );
439         return;
440     }
441
442     for( int i = 0; i < 255; i++ )
443     {
444 #define es_descr p_iod->es_descr[i]
445         if( es_descr.b_ok )
446         {
447             if( es_descr.psz_url )
448                 free( es_descr.psz_url );
449             else
450                 free( es_descr.dec_descr.p_extra );
451         }
452 #undef  es_descr
453     }
454     free( p_iod );
455 }