1 /*****************************************************************************
2 * asfpacket.c :
3 *****************************************************************************
4 * Copyright © 2001-2004, 2011, 2014 VLC authors and VideoLAN
5 *
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include "asfpacket.h"
27 #include <limits.h>
28
29 #ifndef NDEBUG
30 # define ASF_DEBUG 1
31 #endif
32
33 typedef struct asf_packet_t
34 {
35 uint32_t property;
36 uint32_t length;
37 uint32_t padding_length;
38 uint32_t send_time;
39 bool multiple;
40 int length_type;
41
42 /* buffer handling for this ASF packet */
43 uint32_t i_skip;
44 const uint8_t *p_peek;
45 uint32_t left;
46 } asf_packet_t;
47
GetValue2b(uint32_t * var,const uint8_t * p,unsigned int * skip,int left,int bits)48 static inline int GetValue2b(uint32_t *var, const uint8_t *p, unsigned int *skip, int left, int bits)
49 {
50 switch(bits&0x03)
51 {
52 case 1:
53 if (left < 1)
54 return -1;
55 *var = p[*skip]; *skip += 1;
56 return 0;
57 case 2:
58 if (left < 2)
59 return -1;
60 *var = GetWLE(&p[*skip]); *skip += 2;
61 return 0;
62 case 3:
63 if (left < 4)
64 return -1;
65 *var = GetDWLE(&p[*skip]); *skip += 4;
66 return 0;
67 case 0:
68 default:
69 return 0;
70 }
71 }
72
SkipBytes(stream_t * s,uint32_t i_bytes)73 static uint32_t SkipBytes( stream_t *s, uint32_t i_bytes )
74 {
75 ssize_t i_read = vlc_stream_Read( s, NULL, i_bytes );
76 return i_read > 0 ? (uint32_t) i_read : 0;
77 }
78
DemuxSubPayload(asf_packet_sys_t * p_packetsys,uint8_t i_stream_number,block_t ** pp_frame,uint32_t i_sub_payload_data_length,mtime_t i_pts,mtime_t i_dts,uint32_t i_media_object_offset,bool b_keyframe,bool b_ignore_pts)79 static int DemuxSubPayload( asf_packet_sys_t *p_packetsys,
80 uint8_t i_stream_number, block_t **pp_frame,
81 uint32_t i_sub_payload_data_length, mtime_t i_pts, mtime_t i_dts,
82 uint32_t i_media_object_offset, bool b_keyframe, bool b_ignore_pts )
83 {
84 /* FIXME I don't use i_media_object_number, sould I ? */
85 if( *pp_frame && i_media_object_offset == 0 )
86 {
87 p_packetsys->pf_send( p_packetsys, i_stream_number, pp_frame );
88 }
89
90 block_t *p_frag = vlc_stream_Block( p_packetsys->p_demux->s, i_sub_payload_data_length );
91 if( p_frag == NULL ) {
92 msg_Warn( p_packetsys->p_demux, "cannot read data" );
93 return -1;
94 }
95
96 p_frag->i_pts = (b_ignore_pts) ? VLC_TS_INVALID : VLC_TS_0 + i_pts;
97 p_frag->i_dts = VLC_TS_0 + i_dts;
98 if ( b_keyframe )
99 p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
100
101 block_ChainAppend( pp_frame, p_frag );
102
103 return 0;
104 }
105
ParsePayloadExtensions(asf_packet_sys_t * p_packetsys,const asf_track_info_t * p_tkinfo,const uint8_t * p_data,size_t i_data,bool * b_keyframe,int64_t * pi_extension_pts)106 static void ParsePayloadExtensions( asf_packet_sys_t *p_packetsys,
107 const asf_track_info_t *p_tkinfo,
108 const uint8_t *p_data, size_t i_data,
109 bool *b_keyframe,
110 int64_t *pi_extension_pts )
111 {
112 demux_t *p_demux = p_packetsys->p_demux;
113
114 if ( !p_tkinfo || !p_tkinfo->p_esp || !p_tkinfo->p_esp->p_ext )
115 return;
116
117 uint16_t i_payload_extensions_size;
118 asf_payload_extension_system_t *p_ext = NULL;
119
120 /* Extensions always come in the declared order */
121 for ( int i=0; i< p_tkinfo->p_esp->i_payload_extension_system_count; i++ )
122 {
123 p_ext = &p_tkinfo->p_esp->p_ext[i];
124 if ( p_ext->i_data_size == 0xFFFF ) /* Variable length extension data */
125 {
126 if ( i_data < 2 ) return;
127 i_payload_extensions_size = GetWLE( p_data );
128 p_data += 2;
129 i_data -= 2;
130 i_payload_extensions_size = 0;
131 }
132 else
133 {
134 i_payload_extensions_size = p_ext->i_data_size;
135 }
136
137 if ( i_data < i_payload_extensions_size ) return;
138
139 if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_outputcleanpoint_guid ) )
140 {
141 if ( i_payload_extensions_size != sizeof(uint8_t) ) goto sizeerror;
142 *b_keyframe |= *p_data;
143 }
144 else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_videoframe_guid ) )
145 {
146 if ( i_payload_extensions_size != sizeof(uint32_t) ) goto sizeerror;
147
148 uint32_t i_val = GetDWLE( p_data );
149 /* Valid keyframe must be a split frame start fragment */
150 *b_keyframe = i_val & ASF_EXTENSION_VIDEOFRAME_NEWFRAME;
151 if ( *b_keyframe )
152 {
153 /* And flagged as IFRAME */
154 *b_keyframe |= ( ( i_val & ASF_EXTENSION_VIDEOFRAME_TYPE_MASK )
155 == ASF_EXTENSION_VIDEOFRAME_IFRAME );
156 }
157 }
158 else if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_pixelaspectratio_guid ) &&
159 p_packetsys->pf_setaspectratio )
160 {
161 if ( i_payload_extensions_size != sizeof(uint16_t) ) goto sizeerror;
162
163 p_packetsys->pf_setaspectratio( p_packetsys, p_tkinfo->p_sp->i_stream_number,
164 p_data[0], p_data[1] );
165 }
166 else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_timing_rep_data_guid ) )
167 {
168 if ( i_payload_extensions_size != 48 ) goto sizeerror;
169 const int64_t i_pts = GetQWLE(&p_data[8]);
170 if(i_pts != -1)
171 *pi_extension_pts = i_pts / 10000;
172 }
173 #if 0
174 else
175 {
176 msg_Dbg( p_demux, "Unknown extension " GUID_FMT, GUID_PRINT( p_ext->i_extension_id ) );
177 }
178 #endif
179 i_data -= i_payload_extensions_size;
180 p_data += i_payload_extensions_size;
181 }
182
183 return;
184
185 sizeerror:
186 msg_Warn( p_demux, "Unknown extension " GUID_FMT " data size of %u",
187 GUID_PRINT( p_ext->i_extension_id ), i_payload_extensions_size );
188 }
189
DemuxPayload(asf_packet_sys_t * p_packetsys,asf_packet_t * pkt,int i_payload)190 static int DemuxPayload(asf_packet_sys_t *p_packetsys, asf_packet_t *pkt, int i_payload)
191 {
192 #ifndef ASF_DEBUG
193 VLC_UNUSED( i_payload );
194 #endif
195 demux_t *p_demux = p_packetsys->p_demux;
196
197 if( ! pkt->left || pkt->i_skip >= pkt->left )
198 return -1;
199
200 bool b_packet_keyframe = pkt->p_peek[pkt->i_skip] >> 7;
201 uint8_t i_stream_number = pkt->p_peek[pkt->i_skip++] & 0x7f;
202
203 uint32_t i_media_object_number = 0;
204 if (GetValue2b(&i_media_object_number, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 4) < 0)
205 return -1;
206 uint32_t i_media_object_offset = 0;
207 if (GetValue2b(&i_media_object_offset, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property >> 2) < 0)
208 return -1;
209 uint32_t i_replicated_data_length = 0;
210 if (GetValue2b(&i_replicated_data_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->property) < 0)
211 return -1;
212
213 int64_t i_pkt_time;
214 uint8_t i_pkt_time_delta = 0;
215 int64_t i_extension_pts = -1;
216 uint32_t i_payload_data_length = 0;
217 uint32_t i_temp_payload_length = 0;
218 *p_packetsys->pi_preroll = __MIN( *p_packetsys->pi_preroll, INT64_MAX );
219
220 /* First packet, in case we do not have index to guess preroll start time */
221 if ( *p_packetsys->pi_preroll_start == ASFPACKET_PREROLL_FROM_CURRENT )
222 *p_packetsys->pi_preroll_start = pkt->send_time * 1000;
223
224 asf_track_info_t *p_tkinfo = p_packetsys->pf_gettrackinfo( p_packetsys, i_stream_number );
225 if ( !p_tkinfo )
226 goto skip;
227
228 bool b_ignore_pts = (p_tkinfo->i_cat == VIDEO_ES); /* ignore PTS delta with video when not set by mux */
229
230 if( pkt->left - pkt->i_skip < i_replicated_data_length )
231 return -1;
232
233 /* Non compressed */
234 if( i_replicated_data_length > 7 ) // should be at least 8 bytes
235 {
236 /* Followed by 2 optional DWORDS, offset in media and *media* presentation time */
237 i_pkt_time = (mtime_t)GetDWLE( pkt->p_peek + pkt->i_skip + 4 );
238
239 /* Parsing extensions, See 7.3.1 */
240 ParsePayloadExtensions( p_packetsys, p_tkinfo,
241 &pkt->p_peek[pkt->i_skip + 8],
242 i_replicated_data_length - 8,
243 &b_packet_keyframe,
244 &i_extension_pts );
245 i_pkt_time -= *p_packetsys->pi_preroll;
246 if(i_extension_pts != -1)
247 i_extension_pts -= *p_packetsys->pi_preroll;
248 pkt->i_skip += i_replicated_data_length;
249 }
250 else if ( i_replicated_data_length == 0 )
251 {
252 /* optional DWORDS missing */
253 i_pkt_time = (mtime_t)pkt->send_time;
254 }
255 /* Compressed payload */
256 else if( i_replicated_data_length == 1 )
257 {
258 /* i_media_object_offset is *media* presentation time */
259 /* Next byte is *media* Presentation Time Delta */
260 i_pkt_time_delta = pkt->p_peek[pkt->i_skip];
261 b_ignore_pts = false;
262 i_pkt_time = (mtime_t)i_media_object_offset;
263 i_pkt_time -= *p_packetsys->pi_preroll;
264 pkt->i_skip++;
265 i_media_object_offset = 0;
266 }
267 else
268 {
269 /* >1 && <8 Invalid replicated length ! */
270 msg_Warn( p_demux, "Invalid replicated data length detected." );
271 if( pkt->length - pkt->i_skip < pkt->padding_length )
272 return -1;
273
274 i_payload_data_length = pkt->length - pkt->padding_length - pkt->i_skip;
275 goto skip;
276 }
277
278 if( ! pkt->left || pkt->i_skip >= pkt->left )
279 return -1;
280
281 bool b_preroll_done = ( pkt->send_time > (*p_packetsys->pi_preroll_start/1000 + *p_packetsys->pi_preroll) );
282
283 if (i_pkt_time < 0) i_pkt_time = 0; // FIXME?
284 i_pkt_time *= 1000;
285
286 if( pkt->multiple ) {
287 if (GetValue2b(&i_temp_payload_length, pkt->p_peek, &pkt->i_skip, pkt->left - pkt->i_skip, pkt->length_type) < 0)
288 return -1;
289 }
290 else
291 {
292 if( pkt->length - pkt->i_skip < pkt->padding_length )
293 return -1;
294 i_temp_payload_length = pkt->length - pkt->padding_length - pkt->i_skip;
295 }
296
297 i_payload_data_length = i_temp_payload_length;
298
299 #ifdef ASF_DEBUG
300 msg_Dbg( p_demux,
301 "payload(%d) stream_number:%"PRIu8" media_object_number:%d media_object_offset:%"PRIu32" replicated_data_length:%"PRIu32" payload_data_length %"PRIu32,
302 i_payload + 1, i_stream_number, i_media_object_number,
303 i_media_object_offset, i_replicated_data_length, i_payload_data_length );
304 msg_Dbg( p_demux,
305 " extpts=%"PRId64" pkttime=%"PRId64" st=%"PRIu32,
306 (i_extension_pts >= 0) ? i_extension_pts * 1000 : -1, i_pkt_time, pkt->send_time );
307 #endif
308
309 if( ! i_payload_data_length || i_payload_data_length > pkt->left )
310 {
311 msg_Dbg( p_demux, " payload length problem %d %"PRIu32" %"PRIu32, pkt->multiple, i_payload_data_length, pkt->left );
312 return -1;
313 }
314
315 if ( p_packetsys->pf_doskip &&
316 p_packetsys->pf_doskip( p_packetsys, i_stream_number, b_packet_keyframe ) )
317 goto skip;
318
319 if ( b_preroll_done )
320 {
321 mtime_t i_track_time = i_pkt_time;
322
323 if ( p_packetsys->pf_updatetime )
324 p_packetsys->pf_updatetime( p_packetsys, i_stream_number, i_track_time );
325 }
326
327 if( p_packetsys->pf_updatesendtime )
328 p_packetsys->pf_updatesendtime( p_packetsys, INT64_C(1000) * pkt->send_time );
329
330 uint32_t i_subpayload_count = 0;
331 while (i_payload_data_length && pkt->i_skip < pkt->left )
332 {
333 uint32_t i_sub_payload_data_length = i_payload_data_length;
334 if( i_replicated_data_length == 1 )
335 {
336 i_sub_payload_data_length = pkt->p_peek[pkt->i_skip++];
337 i_payload_data_length--;
338 if( i_sub_payload_data_length > i_payload_data_length )
339 goto skip;
340 }
341
342 SkipBytes( p_demux->s, pkt->i_skip );
343
344 mtime_t i_payload_pts;
345 #if 0
346 if( i_extension_pts != -1 )
347 {
348 i_payload_pts = i_extension_pts * 1000;
349 b_ignore_pts = false;
350 }
351 else
352 #endif
353 {
354 i_payload_pts = i_pkt_time + (mtime_t)i_pkt_time_delta * i_subpayload_count * 1000;
355 if ( p_tkinfo->p_sp )
356 i_payload_pts -= p_tkinfo->p_sp->i_time_offset * 10;
357 }
358
359 mtime_t i_payload_dts = i_pkt_time;
360
361 if ( p_tkinfo->p_sp )
362 i_payload_dts -= p_tkinfo->p_sp->i_time_offset * 10;
363
364 if ( i_sub_payload_data_length &&
365 DemuxSubPayload( p_packetsys, i_stream_number, &p_tkinfo->p_frame,
366 i_sub_payload_data_length, i_payload_pts, i_payload_dts,
367 i_media_object_offset, b_packet_keyframe, b_ignore_pts ) < 0)
368 return -1;
369
370 if ( pkt->left > pkt->i_skip + i_sub_payload_data_length )
371 pkt->left -= pkt->i_skip + i_sub_payload_data_length;
372 else
373 pkt->left = 0;
374 pkt->i_skip = 0;
375 if( pkt->left > 0 )
376 {
377 ssize_t i_return = vlc_stream_Peek( p_demux->s, &pkt->p_peek, pkt->left );
378 if ( i_return <= 0 || (size_t) i_return < pkt->left )
379 {
380 msg_Warn( p_demux, "cannot peek, EOF ?" );
381 return -1;
382 }
383 }
384
385 if ( i_sub_payload_data_length <= i_payload_data_length )
386 i_payload_data_length -= i_sub_payload_data_length;
387 else
388 i_payload_data_length = 0;
389
390 i_subpayload_count++;
391 }
392
393 return 0;
394
395 skip:
396 pkt->i_skip += i_payload_data_length;
397 return 0;
398 }
399
DemuxASFPacket(asf_packet_sys_t * p_packetsys,uint32_t i_data_packet_min,uint32_t i_data_packet_max,uint64_t i_data_begin,uint64_t i_data_end)400 int DemuxASFPacket( asf_packet_sys_t *p_packetsys,
401 uint32_t i_data_packet_min, uint32_t i_data_packet_max,
402 uint64_t i_data_begin, uint64_t i_data_end )
403 {
404 demux_t *p_demux = p_packetsys->p_demux;
405
406 const uint64_t i_read_pos = vlc_stream_Tell( p_demux->s );
407 if( i_read_pos < i_data_begin ||
408 (i_data_end && ( i_data_packet_min > i_data_end ||
409 i_read_pos > i_data_end - i_data_packet_min ) ) )
410 return 0;
411
412 const uint8_t *p_peek;
413 ssize_t i_return = vlc_stream_Peek( p_demux->s, &p_peek,i_data_packet_min );
414 if( i_return <= 0 || (size_t) i_return < i_data_packet_min )
415 {
416 msg_Warn( p_demux, "cannot peek while getting new packet, EOF ?" );
417 return 0;
418 }
419 unsigned int i_skip = 0;
420
421 /* *** parse error correction if present *** */
422 if( p_peek[0]&0x80 )
423 {
424 unsigned int i_error_correction_data_length = p_peek[0] & 0x0f;
425 unsigned int i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;
426 unsigned int i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03;
427 i_skip += 1; // skip error correction flags
428
429 if( i_error_correction_length_type != 0x00 ||
430 i_opaque_data_present != 0 ||
431 i_error_correction_data_length != 0x02 )
432 {
433 goto loop_error_recovery;
434 }
435
436 i_skip += i_error_correction_data_length;
437 }
438 else
439 msg_Warn( p_demux, "no error correction" );
440
441 /* sanity check */
442 if( i_skip + 2 >= i_data_packet_min )
443 goto loop_error_recovery;
444
445 asf_packet_t pkt;
446 int i_packet_flags = p_peek[i_skip]; i_skip++;
447 pkt.property = p_peek[i_skip]; i_skip++;
448 pkt.multiple = !!(i_packet_flags&0x01);
449
450 pkt.length = i_data_packet_min;
451 pkt.padding_length = 0;
452
453 if (GetValue2b(&pkt.length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 5) < 0)
454 goto loop_error_recovery;
455 uint32_t i_packet_sequence;
456 if (GetValue2b(&i_packet_sequence, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 1) < 0)
457 goto loop_error_recovery;
458 if (GetValue2b(&pkt.padding_length, p_peek, &i_skip, i_data_packet_min - i_skip, i_packet_flags >> 3) < 0)
459 goto loop_error_recovery;
460
461 if( pkt.padding_length > pkt.length )
462 {
463 msg_Warn( p_demux, "Too large padding: %"PRIu32, pkt.padding_length );
464 goto loop_error_recovery;
465 }
466
467 if( pkt.length < i_data_packet_min )
468 {
469 /* if packet length too short, there is extra padding */
470 pkt.padding_length += i_data_packet_min - pkt.length;
471 pkt.length = i_data_packet_min;
472 }
473
474 if( i_skip + 4 > i_data_packet_min )
475 goto loop_error_recovery;
476
477 pkt.send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
478 /* uint16_t i_packet_duration = GetWLE( p_peek + i_skip ); */ i_skip += 2;
479
480 if( i_data_end &&
481 (pkt.length > i_data_end ||
482 i_read_pos > i_data_end - pkt.length) )
483 {
484 msg_Warn( p_demux, "pkt size %"PRIu32" at %"PRIu64" does not fit data chunk",
485 pkt.length, i_read_pos );
486 return 0;
487 }
488
489 i_return = vlc_stream_Peek( p_demux->s, &p_peek, pkt.length );
490 if( i_return <= 0 || pkt.length == 0 || (size_t)i_return < pkt.length )
491 {
492 msg_Warn( p_demux, "cannot peek, EOF ?" );
493 return 0;
494 }
495
496 int i_payload_count = 1;
497 pkt.length_type = 0x02; //unused
498 if( pkt.multiple )
499 {
500 if( i_skip + 1 >= i_data_packet_min )
501 goto loop_error_recovery;
502 i_payload_count = p_peek[i_skip] & 0x3f;
503 pkt.length_type = ( p_peek[i_skip] >> 6 )&0x03;
504 i_skip++;
505 }
506
507 #ifdef ASF_DEBUG
508 msg_Dbg(p_demux, "%d payloads", i_payload_count);
509 #endif
510
511 pkt.i_skip = i_skip;
512 pkt.p_peek = p_peek;
513 pkt.left = pkt.length;
514
515 for( int i_payload = 0; i_payload < i_payload_count ; i_payload++ )
516 if (DemuxPayload(p_packetsys, &pkt, i_payload) < 0)
517 {
518 msg_Warn( p_demux, "payload err %d / %d", i_payload + 1, i_payload_count );
519 return 0;
520 }
521
522 if( pkt.left > 0 )
523 {
524 #ifdef ASF_DEBUG
525 if( pkt.left > pkt.padding_length )
526 msg_Warn( p_demux, "Didn't read %"PRIu32" bytes in the packet",
527 pkt.left - pkt.padding_length );
528 else if( pkt.left < pkt.padding_length )
529 msg_Warn( p_demux, "Read %"PRIu32" too much bytes in the packet",
530 pkt.padding_length - pkt.left );
531 #endif
532 i_return = vlc_stream_Read( p_demux->s, NULL, pkt.left );
533 if( i_return < 0 || (size_t) i_return < pkt.left )
534 {
535 msg_Err( p_demux, "cannot skip data, EOF ?" );
536 return 0;
537 }
538 }
539
540 return 1;
541
542 loop_error_recovery:
543 msg_Warn( p_demux, "unsupported packet header" );
544 if( i_data_packet_min != i_data_packet_max )
545 {
546 msg_Err( p_demux, "unsupported packet header, fatal error" );
547 return -1;
548 }
549 i_return = vlc_stream_Read( p_demux->s, NULL, i_data_packet_min );
550 if( i_return <= 0 || (size_t) i_return != i_data_packet_min )
551 {
552 msg_Warn( p_demux, "cannot skip data, EOF ?" );
553 return 0;
554 }
555
556 return 1;
557 }
558