/src/vlc/modules/demux/mpeg/mpeg4_iod.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * mpeg4_iod.c: ISO 14496-1 IOD and OD 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 | | #include <stdlib.h> |
35 | | #include <assert.h> |
36 | | |
37 | | //#define OD_DEBUG 1 |
38 | | static void od_debug( vlc_object_t *p_object, const char *format, ... ) |
39 | 1.74M | { |
40 | | #ifdef OD_DEBUG |
41 | | va_list ap; |
42 | | va_start(ap, format); |
43 | | msg_GenericVa( p_object, VLC_MSG_DBG, format, ap ); |
44 | | va_end(ap); |
45 | | #else |
46 | 1.74M | VLC_UNUSED(format); |
47 | 1.74M | VLC_UNUSED(p_object); |
48 | 1.74M | #endif |
49 | 1.74M | } |
50 | | |
51 | | /***************************************************************************** |
52 | | * MP4 specific functions (OD parser) |
53 | | *****************************************************************************/ |
54 | | static unsigned ODDescriptorLength( unsigned *pi_data, const uint8_t **pp_data ) |
55 | 1.15M | { |
56 | 1.15M | unsigned int i_b = 0x80; |
57 | 1.15M | unsigned int i_len = 0; |
58 | | |
59 | 1.15M | unsigned bytes = __MIN(*pi_data, 4); |
60 | 2.50M | for(unsigned i=0; i<bytes && (i_b&0x80); i++) |
61 | 1.34M | { |
62 | 1.34M | i_b = **pp_data; |
63 | 1.34M | (*pp_data)++; |
64 | 1.34M | (*pi_data)--; |
65 | 1.34M | i_len = ( i_len << 7 ) + ( i_b&0x7f ); |
66 | 1.34M | } |
67 | | |
68 | 1.15M | return __MIN(i_len, *pi_data); |
69 | 1.15M | } |
70 | | |
71 | | static unsigned ODGetBytes( unsigned *pi_data, const uint8_t **pp_data, size_t bytes ) |
72 | 4.12M | { |
73 | 4.12M | unsigned res = 0; |
74 | 10.8M | while( *pi_data > 0 && bytes-- ) |
75 | 6.72M | { |
76 | 6.72M | res <<= 8; |
77 | 6.72M | res |= **pp_data; |
78 | 6.72M | (*pp_data)++; |
79 | 6.72M | (*pi_data)--; |
80 | 6.72M | } |
81 | | |
82 | 4.12M | return res; |
83 | 4.12M | } |
84 | | |
85 | | static char* ODGetURL( unsigned *pi_data, const uint8_t **pp_data ) |
86 | 4.29k | { |
87 | 4.29k | unsigned len = ODGetBytes( pi_data, pp_data, 1 ); |
88 | 4.29k | if (len > *pi_data) |
89 | 3.74k | len = *pi_data; |
90 | 4.29k | char *url = strndup( (char*)*pp_data, len ); |
91 | 4.29k | *pp_data += len; |
92 | 4.29k | *pi_data -= len; |
93 | 4.29k | return url; |
94 | 4.29k | } |
95 | | |
96 | 267k | #define ODTag_ObjectDescr 0x01 |
97 | 51.1k | #define ODTag_InitialObjectDescr 0x02 |
98 | 349k | #define ODTag_ESDescr 0x03 |
99 | 351k | #define ODTag_DecConfigDescr 0x04 |
100 | 259k | #define ODTag_DecSpecificDescr 0x05 |
101 | 301k | #define ODTag_SLDescr 0x06 |
102 | | |
103 | | /* Unified pointer for read helper */ |
104 | | typedef union |
105 | | { |
106 | | od_descriptor_t *p_od; |
107 | | od_descriptor_t **pp_ods; |
108 | | es_mpeg4_descriptor_t *es_descr; |
109 | | decoder_config_descriptor_t *p_dec_config; |
110 | | sl_config_descriptor_t *sl_descr; |
111 | | } od_read_params_t; |
112 | | |
113 | | static uint8_t OD_Desc_Read( vlc_object_t *, unsigned *, const uint8_t **, uint8_t, uint8_t, od_read_params_t params ); |
114 | | |
115 | 126k | #define SL_Predefined_Custom 0x00 |
116 | 4 | #define SL_Predefined_NULL 0x01 |
117 | 88 | #define SL_Predefined_MP4 0x02 |
118 | | static bool OD_SLDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
119 | | od_read_params_t params ) |
120 | 127k | { |
121 | 127k | sl_config_descriptor_t *sl_descr = params.sl_descr; |
122 | | |
123 | 127k | uint8_t i_predefined = ODGetBytes( &i_data, &p_data, 1 ); |
124 | 127k | switch( i_predefined ) |
125 | 127k | { |
126 | 126k | case SL_Predefined_Custom: |
127 | 126k | if( i_data < 15 ) |
128 | 108 | return false; |
129 | 126k | sl_descr->i_flags = ODGetBytes( &i_data, &p_data, 1 ); |
130 | 126k | sl_descr->i_timestamp_resolution = ODGetBytes( &i_data, &p_data, 4 ); |
131 | 126k | sl_descr->i_OCR_resolution = ODGetBytes( &i_data, &p_data, 4 ); |
132 | 126k | sl_descr->i_timestamp_length = ODGetBytes( &i_data, &p_data, 1 ); |
133 | 126k | if( sl_descr->i_timestamp_length > 64 ) |
134 | 457 | return false; |
135 | 126k | sl_descr->i_OCR_length = ODGetBytes( &i_data, &p_data, 1 ); |
136 | 126k | if( sl_descr->i_OCR_length > 32 ) |
137 | 37.3k | return false; |
138 | 89.0k | sl_descr->i_AU_length = ODGetBytes( &i_data, &p_data, 1 ); |
139 | 89.0k | if( sl_descr->i_AU_length > 32 ) |
140 | 58 | return false; |
141 | 88.9k | sl_descr->i_instant_bitrate_length = ODGetBytes( &i_data, &p_data, 1 ); |
142 | 88.9k | if( sl_descr->i_instant_bitrate_length > 64 ) |
143 | 66 | return false; |
144 | 88.9k | uint16_t i16 = ODGetBytes( &i_data, &p_data, 2 ); |
145 | 88.9k | sl_descr->i_degradation_priority_length = i16 >> 12; |
146 | 88.9k | sl_descr->i_AU_seqnum_length = (i16 >> 7) & 0x1f; |
147 | 88.9k | if( sl_descr->i_AU_seqnum_length > 16 ) |
148 | 145 | return false; |
149 | 88.7k | sl_descr->i_packet_seqnum_length = (i16 >> 2) & 0x1f; |
150 | 88.7k | if( sl_descr->i_packet_seqnum_length > 16 ) |
151 | 25 | return false; |
152 | 88.7k | break; |
153 | 88.7k | case SL_Predefined_NULL: |
154 | 4 | memset( sl_descr, 0, sizeof(*sl_descr) ); |
155 | 4 | sl_descr->i_timestamp_resolution = 1000; |
156 | 4 | sl_descr->i_timestamp_length = 32; |
157 | 4 | break; |
158 | 88 | case SL_Predefined_MP4: |
159 | 88 | memset( sl_descr, 0, sizeof(*sl_descr) ); |
160 | 88 | sl_descr->i_flags = USE_TIMESTAMPS_FLAG; |
161 | 88 | break; |
162 | 79 | default: |
163 | | /* reserved */ |
164 | 79 | return false; |
165 | 127k | } |
166 | | |
167 | 88.8k | if( sl_descr->i_flags & USE_DURATION_FLAG ) |
168 | 436 | { |
169 | 436 | if( i_data < 8 ) |
170 | 271 | return false; |
171 | 165 | sl_descr->i_timescale = ODGetBytes( &i_data, &p_data, 4 ); |
172 | 165 | sl_descr->i_accessunit_duration = ODGetBytes( &i_data, &p_data, 2 ); |
173 | 165 | sl_descr->i_compositionunit_duration = ODGetBytes( &i_data, &p_data, 2 ); |
174 | 165 | } |
175 | | |
176 | 88.5k | if( (sl_descr->i_flags & USE_TIMESTAMPS_FLAG) == 0 ) |
177 | 158 | { |
178 | 158 | bs_t s; |
179 | 158 | bs_init( &s, p_data, i_data ); |
180 | 158 | sl_descr->i_startdecoding_timestamp = bs_read( &s, sl_descr->i_timestamp_length ); |
181 | 158 | sl_descr->i_startcomposition_timestamp = bs_read( &s, sl_descr->i_timestamp_length ); |
182 | 158 | } |
183 | | |
184 | 88.5k | od_debug( p_object, " * read sl desc predefined: 0x%x", i_predefined ); |
185 | 88.5k | return true; |
186 | 88.8k | } |
187 | | |
188 | | static bool OD_DecSpecificDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
189 | | od_read_params_t params ) |
190 | 84.3k | { |
191 | 84.3k | VLC_UNUSED(p_object); |
192 | 84.3k | decoder_config_descriptor_t *p_dec_config = params.p_dec_config; |
193 | | |
194 | 84.3k | p_dec_config->p_extra = malloc( i_data ); |
195 | 84.3k | if( p_dec_config->p_extra ) |
196 | 84.3k | { |
197 | 84.3k | p_dec_config->i_extra = i_data; |
198 | 84.3k | memcpy( p_dec_config->p_extra, p_data, p_dec_config->i_extra ); |
199 | 84.3k | } |
200 | 0 | else p_dec_config->i_extra = 0; |
201 | | |
202 | 84.3k | return !!p_dec_config->i_extra; |
203 | 84.3k | } |
204 | | |
205 | | static bool OD_DecConfigDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
206 | | od_read_params_t params ) |
207 | 175k | { |
208 | 175k | decoder_config_descriptor_t *p_dec_config = params.p_dec_config; |
209 | | |
210 | 175k | if( i_data < 13 ) |
211 | 350 | return false; |
212 | | |
213 | 174k | p_dec_config->i_objectTypeIndication = ODGetBytes( &i_data, &p_data, 1 ); |
214 | 174k | uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 ); |
215 | 174k | p_dec_config->i_streamType = i_flags >> 2; |
216 | | |
217 | 174k | ODGetBytes( &i_data, &p_data, 3 ); /* bufferSizeDB */ |
218 | 174k | ODGetBytes( &i_data, &p_data, 4 ); /* maxBitrate */ |
219 | 174k | ODGetBytes( &i_data, &p_data, 4 ); /* avgBitrate */ |
220 | | |
221 | | /* DecoderSpecificDescr */ |
222 | 174k | OD_Desc_Read( p_object, &i_data, &p_data, |
223 | 174k | ODTag_DecSpecificDescr, 1, params ); |
224 | | |
225 | 174k | od_debug( p_object, " * read decoder objecttype: %x streamtype:%x extra: %u", |
226 | 174k | p_dec_config->i_objectTypeIndication, p_dec_config->i_streamType, p_dec_config->i_extra ); |
227 | | /* ProfileLevelIndicator [0..255] */ |
228 | 174k | return true; |
229 | 175k | } |
230 | | |
231 | | static bool OD_ESDesc_Read( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
232 | | od_read_params_t params ) |
233 | 177k | { |
234 | 177k | es_mpeg4_descriptor_t *es_descr = params.es_descr; |
235 | | |
236 | 177k | if ( i_data < 3 ) |
237 | 398 | return false; |
238 | 176k | es_descr->i_es_id = ODGetBytes( &i_data, &p_data, 2 ); |
239 | 176k | uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 ); |
240 | | |
241 | 176k | if( ( i_flags >> 7 )&0x01 ) |
242 | 725 | { |
243 | 725 | if ( i_data < 2 ) |
244 | 35 | return false; |
245 | 690 | ODGetBytes( &i_data, &p_data, 2 ); /* dependOn_es_id */ |
246 | 690 | } |
247 | | |
248 | 176k | if( (i_flags >> 6) & 0x01 ) |
249 | 1.11k | es_descr->psz_url = ODGetURL( &i_data, &p_data ); |
250 | | |
251 | 176k | if( ( i_flags >> 5 )&0x01 ) |
252 | 175k | { |
253 | 175k | if ( i_data < 2 ) |
254 | 468 | return false; |
255 | 174k | ODGetBytes( &i_data, &p_data, 2 ); /* OCR_es_id */ |
256 | 174k | } |
257 | | |
258 | 176k | od_debug( p_object, " * read ES Descriptor for es id %"PRIx16, es_descr->i_es_id ); |
259 | | |
260 | | /* DecoderConfigDescr */ |
261 | 176k | params.p_dec_config = &es_descr->dec_descr; |
262 | 176k | if ( 1 != OD_Desc_Read( p_object, &i_data, &p_data, |
263 | 176k | ODTag_DecConfigDescr, 1, params ) ) |
264 | 1.41k | return false; |
265 | | |
266 | | /* SLDescr */ |
267 | 174k | params.sl_descr = &es_descr->sl_descr; |
268 | 174k | OD_Desc_Read( p_object, &i_data, &p_data, ODTag_SLDescr, 1, params ); |
269 | | |
270 | | /* IPI / IP / IPMP ... */ |
271 | | |
272 | 174k | es_descr->b_ok = true; |
273 | | |
274 | 174k | return true; |
275 | 176k | } |
276 | | |
277 | | static bool OD_InitialObjectDesc_Read( vlc_object_t *p_object, unsigned i_data, |
278 | | const uint8_t *p_data, od_read_params_t params ) |
279 | 25.5k | { |
280 | 25.5k | od_descriptor_t *p_iod = params.p_od; |
281 | 25.5k | if( i_data < 3 + 5 + 2 ) |
282 | 0 | return false; |
283 | | |
284 | 25.5k | p_iod->i_ID = ( ODGetBytes( &i_data, &p_data, 1 ) << 2 ); |
285 | 25.5k | uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 ); |
286 | 25.5k | p_iod->i_ID |= i_flags >> 6; |
287 | | |
288 | 25.5k | od_debug( p_object, " * ObjectDescriptorID: %"PRIu16, p_iod->i_ID ); |
289 | 25.5k | od_debug( p_object, " * includeInlineProfileLevel flag: 0x%"PRIx8, ( i_flags >> 4 )&0x01 ); |
290 | 25.5k | if ( (i_flags >> 5) & 0x01 ) |
291 | 0 | { |
292 | 0 | p_iod->psz_url = ODGetURL( &i_data, &p_data ); |
293 | 0 | od_debug( p_object, " * URL: %s", p_iod->psz_url ); |
294 | 0 | return true; /* leaves out unparsed remaining extdescr */ |
295 | 0 | } |
296 | | |
297 | 25.5k | if( i_data < 5 + 2 ) /* at least one ES desc */ |
298 | 0 | return false; |
299 | | |
300 | | /* Profile Level Indication */ |
301 | 25.5k | ODGetBytes( &i_data, &p_data, 1 ); /* OD */ |
302 | 25.5k | ODGetBytes( &i_data, &p_data, 1 ); /* scene */ |
303 | 25.5k | ODGetBytes( &i_data, &p_data, 1 ); /* audio */ |
304 | 25.5k | ODGetBytes( &i_data, &p_data, 1 ); /* visual */ |
305 | 25.5k | ODGetBytes( &i_data, &p_data, 1 ); /* graphics */ |
306 | | |
307 | | /* Now read */ |
308 | | /* 1..255 ESdescr */ |
309 | 25.5k | uint8_t i_desc_count = OD_Desc_Read( p_object, &i_data, &p_data, |
310 | 25.5k | ODTag_ESDescr, ES_DESCRIPTOR_COUNT, params ); |
311 | 25.5k | if( i_desc_count == 0 ) |
312 | 0 | { |
313 | 0 | od_debug( p_object, " * missing ES Descriptor" ); |
314 | 0 | return false; |
315 | 0 | } |
316 | | |
317 | | /* 0..255 OCIdescr */ |
318 | | /* 0..255 IPMPdescpointer */ |
319 | | /* 0..255 IPMPdesc */ |
320 | | /* 0..1 IPMPtoollistdesc */ |
321 | | /* 0..255 Extensiondescr */ |
322 | | |
323 | 25.5k | return true; |
324 | 25.5k | } |
325 | | |
326 | | static bool ODObjectDescriptorRead( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
327 | | od_read_params_t params ) |
328 | 151k | { |
329 | 151k | od_descriptor_t *p_iod = params.p_od; |
330 | 151k | if( i_data < 3 + 2 ) |
331 | 1.60k | return false; |
332 | | |
333 | 149k | p_iod->i_ID = ( ODGetBytes( &i_data, &p_data, 1 ) << 2 ); |
334 | 149k | uint8_t i_flags = ODGetBytes( &i_data, &p_data, 1 ); |
335 | 149k | p_iod->i_ID |= i_flags >> 6; |
336 | | |
337 | 149k | od_debug( p_object, " * ObjectDescriptorID: %"PRIu16, p_iod->i_ID ); |
338 | 149k | if ( (i_flags >> 5) & 0x01 ) |
339 | 3.18k | { |
340 | 3.18k | p_iod->psz_url = ODGetURL( &i_data, &p_data ); |
341 | 3.18k | od_debug( p_object, " * URL: %s", p_iod->psz_url ); |
342 | 3.18k | return true; |
343 | 3.18k | } |
344 | | |
345 | 146k | if( i_data < 2 ) /* at least one ES desc */ |
346 | 0 | return false; |
347 | | |
348 | | /* 1..255 ESdescr */ |
349 | 146k | uint8_t i_desc_count = OD_Desc_Read( p_object, &i_data, &p_data, |
350 | 146k | ODTag_ESDescr, ES_DESCRIPTOR_COUNT, params ); |
351 | 146k | if( i_desc_count == 0 ) |
352 | 23.0k | { |
353 | 23.0k | od_debug( p_object, " * missing ES Descriptor" ); |
354 | 23.0k | return false; |
355 | 23.0k | } |
356 | | |
357 | | /* 0..255 OCIdescr */ |
358 | | /* 0..255 IPMPdescpointer */ |
359 | | /* 0..255 IPMPdesc */ |
360 | | /* 0..1 IPMPtoollistdesc */ |
361 | | /* 0..255 Extensiondescr */ |
362 | | |
363 | 123k | return true; |
364 | 146k | } |
365 | | |
366 | | static uint8_t OD_Desc_Read( vlc_object_t *p_object, unsigned *pi_data, const uint8_t **pp_data, |
367 | | uint8_t i_target_tag, uint8_t i_max_desc, od_read_params_t params ) |
368 | 839k | { |
369 | 839k | uint8_t i_read_count = 0; |
370 | | |
371 | 1.51M | for (unsigned i = 0; *pi_data > 2 && i < i_max_desc; i++) |
372 | 867k | { |
373 | 867k | const uint8_t i_tag = ODGetBytes( pi_data, pp_data, 1 ); |
374 | 867k | const unsigned i_length = ODDescriptorLength( pi_data, pp_data ); |
375 | 867k | if( i_target_tag != i_tag || i_length > *pi_data ) |
376 | 127k | break; |
377 | | |
378 | 740k | unsigned i_descriptor_data = i_length; |
379 | 740k | const uint8_t *p_descriptor_data = *pp_data; |
380 | | |
381 | 740k | od_debug( p_object, " Reading descriptor 0x%"PRIx8": found tag 0x%"PRIx8" left %d", |
382 | 740k | i_target_tag, i_tag, *pi_data ); |
383 | 740k | switch( i_tag ) |
384 | 740k | { |
385 | 151k | case ODTag_ObjectDescr: |
386 | 151k | { |
387 | 151k | od_descriptor_t *p_od = calloc( 1, sizeof( od_descriptor_t ) ); |
388 | 151k | if( !p_od ) |
389 | 0 | break; |
390 | 151k | od_read_params_t childparams; |
391 | 151k | childparams.p_od = params.pp_ods[i_read_count] = p_od; |
392 | | /* od_descriptor_t *p_iod = (od_descriptor_t *) param; */ |
393 | 151k | if ( !ODObjectDescriptorRead( p_object, i_descriptor_data, |
394 | 151k | p_descriptor_data, childparams ) ) |
395 | 24.6k | { |
396 | 24.6k | free( p_od ); |
397 | 24.6k | return i_read_count; |
398 | 126k | }; |
399 | 126k | break; |
400 | 151k | } |
401 | | |
402 | 25.5k | case ODTag_InitialObjectDescr: |
403 | 25.5k | { |
404 | 25.5k | od_descriptor_t *p_iod = calloc( 1, sizeof( od_descriptor_t ) ); |
405 | 25.5k | if( !p_iod ) |
406 | 0 | break; |
407 | 25.5k | od_read_params_t childparams; |
408 | 25.5k | childparams.p_od = params.pp_ods[i_read_count] = p_iod; |
409 | | /* od_descriptor_t *p_iod = (od_descriptor_t *) param; */ |
410 | 25.5k | if ( !OD_InitialObjectDesc_Read( p_object, i_descriptor_data, |
411 | 25.5k | p_descriptor_data, childparams ) ) |
412 | 0 | { |
413 | 0 | free( p_iod ); |
414 | 0 | return i_read_count; |
415 | 25.5k | }; |
416 | 25.5k | break; |
417 | 25.5k | } |
418 | | |
419 | 177k | case ODTag_ESDescr: /**/ |
420 | 177k | { |
421 | 177k | od_descriptor_t *p_iod = params.p_od; |
422 | 177k | od_read_params_t childparams; |
423 | 177k | childparams.es_descr = &p_iod->es_descr[i_read_count]; |
424 | 177k | if ( !OD_ESDesc_Read( p_object, i_descriptor_data, |
425 | 177k | p_descriptor_data, childparams ) ) |
426 | 2.31k | return i_read_count; |
427 | 174k | break; |
428 | 177k | } |
429 | | |
430 | 175k | case ODTag_DecConfigDescr: |
431 | 175k | { |
432 | 175k | if ( !OD_DecConfigDesc_Read( p_object, i_descriptor_data, |
433 | 175k | p_descriptor_data, params ) ) |
434 | 350 | return i_read_count; |
435 | 174k | break; |
436 | 175k | } |
437 | | |
438 | 174k | case ODTag_DecSpecificDescr: |
439 | 84.3k | { |
440 | 84.3k | if ( !OD_DecSpecificDesc_Read( p_object, i_descriptor_data, |
441 | 84.3k | p_descriptor_data, params ) ) |
442 | 193 | return i_read_count; |
443 | 84.1k | break; |
444 | 84.3k | } |
445 | | |
446 | 127k | case ODTag_SLDescr: |
447 | 127k | { |
448 | 127k | if ( !OD_SLDesc_Read( p_object, i_descriptor_data, |
449 | 127k | p_descriptor_data, params ) ) |
450 | 38.5k | return i_read_count; |
451 | 88.5k | break; |
452 | 127k | } |
453 | | |
454 | 88.5k | default: |
455 | | /* invalid i_target_tag from caller */ |
456 | 0 | vlc_assert_unreachable(); |
457 | 0 | return 0; |
458 | 740k | } |
459 | | |
460 | 674k | *pp_data += i_length; |
461 | 674k | *pi_data -= i_length; |
462 | | |
463 | 674k | i_read_count++; |
464 | 674k | } |
465 | | |
466 | 773k | return i_read_count; |
467 | 839k | } |
468 | | |
469 | | static uint8_t ODInit( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data, |
470 | | uint8_t i_start_tag, uint8_t i_min, uint8_t i_max, od_descriptor_t **pp_ods ) |
471 | 142k | { |
472 | 142k | od_read_params_t params; |
473 | 142k | params.pp_ods = pp_ods; |
474 | 142k | uint8_t i_read = OD_Desc_Read( p_object, &i_data, &p_data, i_start_tag, i_max, params ); |
475 | 142k | if ( i_read < i_min ) |
476 | 29.3k | { |
477 | 29.3k | od_debug( p_object, " cannot read first tag 0x%"PRIx8, i_start_tag ); |
478 | 29.3k | return 0; |
479 | 29.3k | } |
480 | | |
481 | 112k | return i_read; |
482 | 142k | } |
483 | | |
484 | | od_descriptor_t *IODNew( vlc_object_t *p_object, unsigned i_data, const uint8_t *p_data ) |
485 | 25.5k | { |
486 | 25.5k | if( i_data < 4 ) |
487 | 0 | return NULL; |
488 | | |
489 | 25.5k | uint8_t i_iod_scope = ODGetBytes( &i_data, &p_data, 1 ); /* scope */ |
490 | 25.5k | uint8_t i_iod_label = ODGetBytes( &i_data, &p_data, 1 ); |
491 | 25.5k | if( i_iod_label == 0x02 ) /* old vlc's buggy implementation of the OD_descriptor */ |
492 | 0 | { |
493 | 0 | i_iod_label = i_iod_scope; |
494 | 0 | i_iod_scope = 0x10; /* Add the missing front iod scope byte */ |
495 | 0 | i_data++; p_data--; /* next byte must be tag */ |
496 | 0 | } |
497 | | |
498 | 25.5k | od_debug( p_object, " * iod label:0x%"PRIx8" scope:0x%"PRIx8, |
499 | 25.5k | i_iod_label, i_iod_scope ); |
500 | | |
501 | 25.5k | if( i_iod_scope != 0x10 && i_iod_scope != 0x11 ) /* Uniqueness in program or transport */ |
502 | 0 | { |
503 | 0 | od_debug( p_object, " * can't handle reserved scope 0x%"PRIx8, i_iod_scope ); |
504 | 0 | return NULL; |
505 | 0 | } |
506 | | |
507 | 25.5k | od_descriptor_t * ods[1]; |
508 | 25.5k | uint8_t i_count = ODInit( p_object, i_data, p_data, ODTag_InitialObjectDescr, 1, 1, ods ); |
509 | 25.5k | if( !i_count ) |
510 | 0 | return NULL; |
511 | 25.5k | return ods[0]; |
512 | 25.5k | } |
513 | | |
514 | | void ODFree( od_descriptor_t *p_iod ) |
515 | 151k | { |
516 | 151k | if( p_iod->psz_url ) |
517 | 3.10k | { |
518 | 3.10k | free( p_iod->psz_url ); |
519 | 3.10k | free( p_iod ); |
520 | 3.10k | return; |
521 | 3.10k | } |
522 | | |
523 | 37.9M | for( size_t i = 0; i < ES_DESCRIPTOR_COUNT; i++ ) |
524 | 37.7M | { |
525 | 38.1M | #define es_descr p_iod->es_descr[i] |
526 | 37.7M | if( es_descr.b_ok ) |
527 | 173k | { |
528 | 173k | if( es_descr.psz_url ) |
529 | 142 | free( es_descr.psz_url ); |
530 | 173k | else |
531 | 173k | free( es_descr.dec_descr.p_extra ); |
532 | 173k | } |
533 | 37.7M | #undef es_descr |
534 | 37.7M | } |
535 | 148k | free( p_iod ); |
536 | 148k | } |
537 | | |
538 | | /***************************************************************************** |
539 | | * SL Packet Parser |
540 | | *****************************************************************************/ |
541 | | sl_header_data DecodeSLHeader( unsigned i_data, const uint8_t *p_data, |
542 | | const sl_config_descriptor_t *sl ) |
543 | 807k | { |
544 | 807k | sl_header_data ret = { 0 }; |
545 | | |
546 | 807k | bs_t s; |
547 | 807k | bs_init( &s, p_data, i_data ); |
548 | | |
549 | 807k | bool b_has_ocr = false; |
550 | 807k | bool b_is_idle = false; |
551 | 807k | bool b_has_padding = false; |
552 | 807k | uint8_t i_padding = 0; |
553 | | |
554 | 807k | if( sl->i_flags & USE_ACCESS_UNIT_START_FLAG ) |
555 | 617k | ret.b_au_start = bs_read1( &s ); |
556 | 807k | if( sl->i_flags & USE_ACCESS_UNIT_END_FLAG ) |
557 | 619k | ret.b_au_end = bs_read1( &s ); |
558 | 807k | if( sl->i_OCR_length > 0 ) |
559 | 299k | b_has_ocr = bs_read1( &s ); |
560 | 807k | if( sl->i_flags & USE_IDLE_FLAG ) |
561 | 618k | b_is_idle = bs_read1( &s ); |
562 | 807k | if( sl->i_flags & USE_PADDING_FLAG ) |
563 | 5.94k | b_has_padding = bs_read1( &s ); |
564 | | |
565 | 807k | if( ret.b_au_end == ret.b_au_start && ret.b_au_start == false ) |
566 | 348k | ret.b_au_end = ret.b_au_start = true; |
567 | | |
568 | 807k | if( b_has_padding ) |
569 | 4.14k | i_padding = bs_read( &s, 3 ); |
570 | | |
571 | | /* Optional fields */ |
572 | 807k | if( !b_is_idle && ( !b_has_padding || !i_padding ) ) /* When not idle and not only padding */ |
573 | 716k | { |
574 | 716k | bool b_has_dts = false; |
575 | 716k | bool b_has_cts = false; |
576 | 716k | bool b_has_instant_bitrate = false; |
577 | 716k | struct |
578 | 716k | { |
579 | 716k | bool *p_b; |
580 | 716k | vlc_tick_t *p_t; |
581 | 716k | } const timestamps[2] = { { &b_has_dts, &ret.i_dts }, { &b_has_cts, &ret.i_pts } }; |
582 | | |
583 | 716k | bs_skip( &s, sl->i_packet_seqnum_length ); |
584 | | |
585 | 716k | if( sl->i_degradation_priority_length && bs_read1( &s ) ) |
586 | 963 | bs_skip( &s, sl->i_degradation_priority_length ); |
587 | | |
588 | 716k | if( b_has_ocr ) |
589 | 26.2k | bs_skip( &s, sl->i_OCR_length ); |
590 | | |
591 | 716k | if ( ret.b_au_start ) |
592 | 702k | { |
593 | 702k | if( sl->i_flags & USE_RANDOM_ACCESS_POINT_FLAG ) |
594 | 10.6k | bs_read1( &s ); |
595 | | |
596 | 702k | bs_skip( &s, sl->i_AU_seqnum_length ); |
597 | | |
598 | 702k | if ( sl->i_flags & USE_TIMESTAMPS_FLAG ) |
599 | 524k | { |
600 | 524k | b_has_dts = bs_read1( &s ); |
601 | 524k | b_has_cts = bs_read1( &s ); |
602 | 524k | } |
603 | | |
604 | 702k | if( sl->i_instant_bitrate_length ) |
605 | 3.13k | b_has_instant_bitrate = bs_read1( &s ); |
606 | | |
607 | 2.10M | for( int i=0; i<2; i++ ) |
608 | 1.40M | { |
609 | 1.40M | if( !*(timestamps[i].p_b) ) |
610 | 926k | continue; |
611 | 478k | uint64_t i_read = bs_read( &s, __MIN( 32, sl->i_timestamp_length ) ); |
612 | 478k | if( sl->i_timestamp_length > 32 ) |
613 | 439k | { |
614 | 439k | uint8_t i_bits = __MAX( 1, sl->i_timestamp_length - 32 ); |
615 | 439k | i_read = i_read << i_bits; |
616 | 439k | i_read |= bs_read( &s, i_bits ); |
617 | 439k | } |
618 | 478k | if( sl->i_timestamp_resolution ) |
619 | 440k | *(timestamps[i].p_t) = VLC_TICK_0 + |
620 | 440k | vlc_tick_from_samples(i_read, sl->i_timestamp_resolution); |
621 | 478k | } |
622 | | |
623 | 702k | bs_skip( &s, sl->i_AU_length ); |
624 | | |
625 | 702k | if( b_has_instant_bitrate ) |
626 | 1.02k | bs_skip( &s, sl->i_instant_bitrate_length ); |
627 | 702k | } |
628 | | |
629 | | /* more to read if ExtSLConfigDescrTag */ |
630 | 716k | } |
631 | | |
632 | 807k | if ( b_has_padding && !i_padding ) /* all padding */ |
633 | 1.32k | ret.i_size = i_data; |
634 | 805k | else |
635 | 805k | ret.i_size = (bs_pos( &s ) + 7) / 8; |
636 | | |
637 | 807k | return ret; |
638 | 807k | } |
639 | | |
640 | | /***************************************************************************** |
641 | | * OD Commands Parser |
642 | | *****************************************************************************/ |
643 | 116k | #define ODTag_ObjectDescrUpdate 0x01 |
644 | 3.41k | #define ODTag_ObjectDescrRemove 0x02 |
645 | | |
646 | | struct bsearch_key |
647 | | { |
648 | | uint16_t id; |
649 | | const od_descriptor_t ***ppp_lowerbest; |
650 | | }; |
651 | | |
652 | | static int bsearch_cmp( const void *key_, const void *el_ ) |
653 | 422k | { |
654 | 422k | const struct bsearch_key *key = key_; |
655 | 422k | const od_descriptor_t *el = *((const od_descriptor_t **) el_); |
656 | 422k | if( key->id < el->i_ID ) |
657 | 164k | return -1; |
658 | 258k | if( key->ppp_lowerbest ) |
659 | 127k | *key->ppp_lowerbest = (const od_descriptor_t **) el_; |
660 | 258k | if( key->id > el->i_ID ) |
661 | 154k | return 1; |
662 | 103k | return 0; |
663 | 258k | } |
664 | | |
665 | | static void ObjectDescrUpdateCommandRead( vlc_object_t *p_object, od_descriptors_t *p_ods, |
666 | | unsigned i_data, const uint8_t *p_data ) |
667 | 116k | { |
668 | 116k | od_descriptor_t *p_odsread[255]; |
669 | 116k | uint8_t i_count = ODInit( p_object, i_data, p_data, ODTag_ObjectDescr, 1, 255, p_odsread ); |
670 | 243k | for( int i=0; i<i_count; i++ ) |
671 | 126k | { |
672 | 126k | od_descriptor_t *p_od = p_odsread[i]; |
673 | 126k | const od_descriptor_t **pp_lowerbest = NULL; |
674 | 126k | struct bsearch_key key = { .id = p_od->i_ID, .ppp_lowerbest = &pp_lowerbest }; |
675 | 126k | od_descriptor_t **pp_cur = bsearch( &key, p_ods->objects.p_elems, |
676 | 126k | p_ods->objects.i_size, sizeof(*pp_cur), |
677 | 126k | bsearch_cmp ); |
678 | 126k | if ( pp_cur ) |
679 | 102k | { |
680 | 102k | int i_pos = pp_cur - p_ods->objects.p_elems; |
681 | 102k | ODFree( *pp_cur ); |
682 | 102k | p_ods->objects.p_elems[i_pos] = p_od; |
683 | 102k | } |
684 | 24.3k | else |
685 | 24.3k | { |
686 | 24.3k | int i_pos = pp_lowerbest ? pp_lowerbest - (const od_descriptor_t **) p_ods->objects.p_elems + 1 : 0; |
687 | 24.3k | ARRAY_INSERT( p_ods->objects, p_od, i_pos ); |
688 | 24.3k | } |
689 | 126k | } |
690 | 116k | } |
691 | | |
692 | | static void ObjectDescrRemoveCommandRead( vlc_object_t *p_object, od_descriptors_t *p_ods, |
693 | | unsigned i_data, const uint8_t *p_data ) |
694 | 3.41k | { |
695 | 3.41k | VLC_UNUSED(p_object); |
696 | 3.41k | bs_t s; |
697 | 3.41k | bs_init( &s, p_data, i_data ); |
698 | 133k | for( unsigned i=0; i< (i_data * 8 / 10); i++ ) |
699 | 130k | { |
700 | 130k | struct bsearch_key key = { 0 }; |
701 | 130k | key.id = bs_read( &s, 10 ); |
702 | 130k | od_descriptor_t **pp_cur = bsearch( &key, p_ods->objects.p_elems, |
703 | 130k | p_ods->objects.i_size, sizeof(*pp_cur), |
704 | 130k | bsearch_cmp ); |
705 | 130k | if( pp_cur ) |
706 | 1.02k | ARRAY_REMOVE( p_ods->objects, pp_cur - p_ods->objects.p_elems ); |
707 | 130k | } |
708 | 3.41k | } |
709 | | |
710 | | void DecodeODCommand( vlc_object_t *p_object, od_descriptors_t *p_ods, |
711 | | unsigned i_data, const uint8_t *p_data ) |
712 | 120k | { |
713 | 406k | while( i_data ) |
714 | 292k | { |
715 | 292k | const uint8_t i_tag = ODGetBytes( &i_data, &p_data, 1 ); |
716 | 292k | const unsigned i_length = ODDescriptorLength( &i_data, &p_data ); |
717 | 292k | if( !i_length || i_length > i_data ) |
718 | 7.12k | break; |
719 | 285k | od_debug( p_object, "Decode tag 0x%x length %d", i_tag, i_length ); |
720 | 285k | switch( i_tag ) |
721 | 285k | { |
722 | 116k | case ODTag_ObjectDescrUpdate: |
723 | 116k | ObjectDescrUpdateCommandRead( p_object, p_ods, i_length, p_data ); |
724 | 116k | break; |
725 | 3.41k | case ODTag_ObjectDescrRemove: |
726 | 3.41k | ObjectDescrRemoveCommandRead( p_object, p_ods, i_length, p_data ); |
727 | 3.41k | break; |
728 | 165k | default: |
729 | 165k | break; |
730 | 285k | } |
731 | 285k | p_data += i_length; |
732 | 285k | i_data -= i_length; |
733 | 285k | } |
734 | 120k | } |