importer: Evaluate return value properly.
[L-SMASH.git] / codecs / vc1.c
blob0f44cb115556d3f14a1155f249997dd36af664a3
1 /*****************************************************************************
2 * vc1.c:
3 *****************************************************************************
4 * Copyright (C) 2012-2014 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
25 #include <string.h>
26 #include <stdlib.h>
27 #include <inttypes.h>
29 #include "core/box.h"
31 /***************************************************************************
32 SMPTE 421M-2006
33 SMPTE RP 2025-2007
34 ***************************************************************************/
35 #include "vc1.h"
37 #define IF_INVALID_VALUE( x ) if( x )
39 struct lsmash_vc1_header_tag
41 uint8_t *ebdu;
42 uint32_t ebdu_size;
45 typedef enum
47 VC1_ADVANCED_PICTURE_TYPE_P = 0x0, /* 0b0 */
48 VC1_ADVANCED_PICTURE_TYPE_B = 0x2, /* 0b10 */
49 VC1_ADVANCED_PICTURE_TYPE_I = 0x6, /* 0b110 */
50 VC1_ADVANCED_PICTURE_TYPE_BI = 0xE, /* 0b1110 */
51 VC1_ADVANCED_PICTURE_TYPE_SKIPPED = 0xF, /* 0b1111 */
52 } vc1_picture_type;
54 typedef enum
56 VC1_ADVANCED_FIELD_PICTURE_TYPE_II = 0x0, /* 0b000 */
57 VC1_ADVANCED_FIELD_PICTURE_TYPE_IP = 0x1, /* 0b001 */
58 VC1_ADVANCED_FIELD_PICTURE_TYPE_PI = 0x2, /* 0b010 */
59 VC1_ADVANCED_FIELD_PICTURE_TYPE_PP = 0x3, /* 0b011 */
60 VC1_ADVANCED_FIELD_PICTURE_TYPE_BB = 0x4, /* 0b100 */
61 VC1_ADVANCED_FIELD_PICTURE_TYPE_BBI = 0x5, /* 0b101 */
62 VC1_ADVANCED_FIELD_PICTURE_TYPE_BIB = 0x6, /* 0b110 */
63 VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI = 0x7, /* 0b111 */
64 } vc1_field_picture_type;
66 typedef enum
68 VC1_FRAME_CODING_MODE_PROGRESSIVE = 0x0, /* 0b0 */
69 VC1_FRAME_CODING_MODE_FRAME_INTERLACE = 0x2, /* 0b10 */
70 VC1_FRAME_CODING_MODE_FIELD_INTERLACE = 0x3, /* 0b11 */
71 } vc1_frame_coding_mode;
73 static void vc1_destroy_header( lsmash_vc1_header_t *hdr )
75 if( !hdr )
76 return;
77 lsmash_free( hdr->ebdu );
78 lsmash_free( hdr );
81 void lsmash_destroy_vc1_headers( lsmash_vc1_specific_parameters_t *param )
83 if( !param )
84 return;
85 vc1_destroy_header( param->seqhdr );
86 vc1_destroy_header( param->ephdr );
87 param->seqhdr = NULL;
88 param->ephdr = NULL;
91 void vc1_destruct_specific_data( void *data )
93 if( !data )
94 return;
95 lsmash_destroy_vc1_headers( data );
96 lsmash_free( data );
99 void vc1_cleanup_parser( vc1_info_t *info )
101 if( !info )
102 return;
103 lsmash_destroy_vc1_headers( &info->dvc1_param );
104 lsmash_destroy_multiple_buffers( info->buffer.bank );
105 lsmash_bits_adhoc_cleanup( info->bits );
106 info->bits = NULL;
109 int vc1_setup_parser
111 vc1_info_t *info,
112 int parse_only
115 if( !info )
116 return -1;
117 memset( info, 0, sizeof(vc1_info_t) );
118 vc1_stream_buffer_t *sb = &info->buffer;
119 sb->bank = lsmash_create_multiple_buffers( parse_only ? 1 : 3, VC1_DEFAULT_BUFFER_SIZE );
120 if( !sb->bank )
121 return -1;
122 sb->rbdu = lsmash_withdraw_buffer( sb->bank, 1 );
123 if( !parse_only )
125 info->access_unit.data = lsmash_withdraw_buffer( sb->bank, 2 );
126 info->access_unit.incomplete_data = lsmash_withdraw_buffer( sb->bank, 3 );
128 info->bits = lsmash_bits_adhoc_create();
129 if( !info->bits )
131 lsmash_destroy_multiple_buffers( sb->bank );
132 return -1;
134 info->prev_bdu_type = 0xFF; /* 0xFF is a forbidden value. */
135 return 0;
138 uint64_t vc1_find_next_start_code_prefix
140 lsmash_bs_t *bs,
141 uint8_t *bdu_type,
142 uint64_t *trailing_zero_bytes
145 uint64_t length = 0; /* the length of the latest EBDU */
146 uint64_t count = 0; /* the number of the trailing zero bytes after the latest EBDU */
147 if( !lsmash_bs_is_end( bs, VC1_START_CODE_LENGTH - 1 )
148 && 0x000001 == lsmash_bs_show_be24( bs, 0 ) )
150 *bdu_type = lsmash_bs_show_byte( bs, VC1_START_CODE_PREFIX_LENGTH );
151 length = VC1_START_CODE_LENGTH;
152 /* Find the start code of the next EBDU and get the length of the latest EBDU. */
153 int no_more = lsmash_bs_is_end( bs, length + VC1_START_CODE_LENGTH - 1 );
154 if( !no_more )
156 uint32_t sync_bytes = lsmash_bs_show_be24( bs, length );
157 while( 0x000001 != sync_bytes )
159 no_more = lsmash_bs_is_end( bs, ++length + VC1_START_CODE_LENGTH - 1 );
160 if( no_more )
161 break;
162 sync_bytes <<= 8;
163 sync_bytes |= lsmash_bs_show_byte( bs, length + VC1_START_CODE_PREFIX_LENGTH - 1 );
164 sync_bytes &= 0xFFFFFF;
167 if( no_more )
168 length = lsmash_bs_get_remaining_buffer_size( bs );
169 /* Any EBDU has no consecutive zero bytes at the end. */
170 while( 0x00 == lsmash_bs_show_byte( bs, length - 1 ) )
172 --length;
173 ++count;
176 else
177 *bdu_type = 0xFF; /* 0xFF is a forbidden value. */
178 *trailing_zero_bytes = count;
179 return length;
182 int vc1_check_next_start_code_suffix
184 lsmash_bs_t *bs,
185 uint8_t *p_bdu_type
188 uint8_t bdu_type = *((uint8_t *)lsmash_bs_get_buffer_data( bs ) + VC1_START_CODE_PREFIX_LENGTH);
189 if( (bdu_type >= 0x00 && bdu_type <= 0x09)
190 || (bdu_type >= 0x20 && bdu_type <= 0xFF) )
191 return -1; /* SMPTE reserved or forbidden value */
192 *p_bdu_type = bdu_type;
193 return 0;
196 static inline uint8_t vc1_get_vlc( lsmash_bits_t *bits, int length )
198 uint8_t value = 0;
199 for( int i = 0; i < length; i++ )
200 if( lsmash_bits_get( bits, 1 ) )
201 value = (value << 1) | 1;
202 else
204 value = value << 1;
205 break;
207 return value;
210 /* Convert EBDU (Encapsulated Byte Data Unit) to RBDU (Raw Byte Data Unit). */
211 static uint8_t *vc1_remove_emulation_prevention( uint8_t *src, uint64_t src_length, uint8_t *dst )
213 uint8_t *src_end = src + src_length;
214 while( src < src_end )
215 if( ((src + 2) < src_end) && !src[0] && !src[1] && (src[2] == 0x03) )
217 /* 0x000003 -> 0x0000 */
218 *dst++ = *src++;
219 *dst++ = *src++;
220 src++; /* Skip emulation_prevention_three_byte (0x03). */
222 else
223 *dst++ = *src++;
224 return dst;
227 static int vc1_import_rbdu_from_ebdu( lsmash_bits_t *bits, uint8_t *rbdu_buffer, uint8_t *ebdu, uint64_t ebdu_size )
229 uint8_t *rbdu_start = rbdu_buffer;
230 uint8_t *rbdu_end = vc1_remove_emulation_prevention( ebdu, ebdu_size, rbdu_buffer );
231 uint64_t rbdu_length = rbdu_end - rbdu_start;
232 return lsmash_bits_import_data( bits, rbdu_start, rbdu_length );
235 static void vc1_parse_hrd_param( lsmash_bits_t *bits, vc1_hrd_param_t *hrd_param )
237 hrd_param->hrd_num_leaky_buckets = lsmash_bits_get( bits, 5 );
238 lsmash_bits_get( bits, 4 ); /* bitrate_exponent */
239 lsmash_bits_get( bits, 4 ); /* buffer_size_exponent */
240 for( uint8_t i = 0; i < hrd_param->hrd_num_leaky_buckets; i++ )
242 lsmash_bits_get( bits, 16 ); /* hrd_rate */
243 lsmash_bits_get( bits, 16 ); /* hrd_buffer */
247 int vc1_parse_sequence_header( vc1_info_t *info, uint8_t *ebdu, uint64_t ebdu_size, int try_append )
249 lsmash_bits_t *bits = info->bits;
250 vc1_sequence_header_t *sequence = &info->sequence;
251 if( vc1_import_rbdu_from_ebdu( bits, info->buffer.rbdu, ebdu + VC1_START_CODE_LENGTH, ebdu_size ) < 0 )
252 return -1;
253 memset( sequence, 0, sizeof(vc1_sequence_header_t) );
254 sequence->profile = lsmash_bits_get( bits, 2 );
255 if( sequence->profile != 3 )
256 return -1; /* SMPTE Reserved */
257 sequence->level = lsmash_bits_get( bits, 3 );
258 if( sequence->level > 4 )
259 return -1; /* SMPTE Reserved */
260 sequence->colordiff_format = lsmash_bits_get( bits, 2 );
261 if( sequence->colordiff_format != 1 )
262 return -1; /* SMPTE Reserved */
263 lsmash_bits_get( bits, 9 ); /* frmrtq_postproc (3)
264 * bitrtq_postproc (5)
265 * postproc_flag (1) */
266 sequence->max_coded_width = lsmash_bits_get( bits, 12 );
267 sequence->max_coded_height = lsmash_bits_get( bits, 12 );
268 lsmash_bits_get( bits, 1 ); /* pulldown */
269 sequence->interlace = lsmash_bits_get( bits, 1 );
270 lsmash_bits_get( bits, 4 ); /* tfcntrflag (1)
271 * finterpflag (1)
272 * reserved (1)
273 * psf (1) */
274 if( lsmash_bits_get( bits, 1 ) ) /* display_ext */
276 sequence->disp_horiz_size = lsmash_bits_get( bits, 14 ) + 1;
277 sequence->disp_vert_size = lsmash_bits_get( bits, 14 ) + 1;
278 if( lsmash_bits_get( bits, 1 ) ) /* aspect_ratio_flag */
280 uint8_t aspect_ratio = lsmash_bits_get( bits, 4 );
281 if( aspect_ratio == 15 )
283 sequence->aspect_width = lsmash_bits_get( bits, 8 ) + 1; /* aspect_horiz_size */
284 sequence->aspect_height = lsmash_bits_get( bits, 8 ) + 1; /* aspect_vert_size */
286 else
288 static const struct
290 uint32_t aspect_width;
291 uint32_t aspect_height;
292 } vc1_aspect_ratio[15] =
294 { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 },
295 { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160, 99 },
296 { 0, 0 } /* SMPTE Reserved */
298 sequence->aspect_width = vc1_aspect_ratio[ aspect_ratio ].aspect_width;
299 sequence->aspect_height = vc1_aspect_ratio[ aspect_ratio ].aspect_height;
302 sequence->framerate_flag = lsmash_bits_get( bits, 1 );
303 if( sequence->framerate_flag )
305 if( lsmash_bits_get( bits, 1 ) ) /* framerateind */
307 sequence->framerate_numerator = lsmash_bits_get( bits, 16 ) + 1;
308 sequence->framerate_denominator = 32;
310 else
312 static const uint32_t vc1_frameratenr_table[8] = { 0, 24, 25, 30, 50, 60, 48, 72 };
313 uint8_t frameratenr = lsmash_bits_get( bits, 8 );
314 IF_INVALID_VALUE( frameratenr == 0 )
315 return -1; /* Forbidden */
316 if( frameratenr > 7 )
317 return -1; /* SMPTE Reserved */
318 uint8_t frameratedr = lsmash_bits_get( bits, 4 );
319 if( frameratedr != 1 && frameratedr != 2 )
320 return -1; /* 0: Forbidden, 3-15: SMPTE Reserved */
321 if( frameratedr == 1 )
323 sequence->framerate_numerator = vc1_frameratenr_table[ frameratenr ];
324 sequence->framerate_denominator = 1;
326 else
328 sequence->framerate_numerator = vc1_frameratenr_table[ frameratenr ] * 1000;
329 sequence->framerate_denominator = 1001;
333 if( lsmash_bits_get( bits, 1 ) ) /* color_format_flag */
335 sequence->color_prim = lsmash_bits_get( bits, 8 );
336 sequence->transfer_char = lsmash_bits_get( bits, 8 );
337 sequence->matrix_coef = lsmash_bits_get( bits, 8 );
339 sequence->hrd_param_flag = lsmash_bits_get( bits, 1 );
340 if( sequence->hrd_param_flag )
341 vc1_parse_hrd_param( bits, &sequence->hrd_param );
343 /* '1' and stuffing bits ('0's) */
344 IF_INVALID_VALUE( !lsmash_bits_get( bits, 1 ) )
345 return -1;
346 lsmash_bits_empty( bits );
347 /* Preparation for creating VC1SpecificBox */
348 if( try_append )
350 /* Update some specific parameters. */
351 lsmash_vc1_specific_parameters_t *param = &info->dvc1_param;
352 lsmash_vc1_header_t *seqhdr = param->seqhdr;
353 if( !seqhdr )
355 seqhdr = lsmash_malloc( sizeof(lsmash_vc1_header_t) );
356 if( !seqhdr )
357 return -1;
358 seqhdr->ebdu = lsmash_memdup( ebdu, ebdu_size );
359 if( !seqhdr->ebdu )
361 lsmash_free( seqhdr );
362 return -1;
364 seqhdr->ebdu_size = ebdu_size;
365 param->seqhdr = seqhdr;
367 else if( seqhdr && seqhdr->ebdu && (seqhdr->ebdu_size == ebdu_size) )
368 param->multiple_sequence |= !!memcmp( ebdu, seqhdr->ebdu, seqhdr->ebdu_size );
369 param->profile = sequence->profile << 2;
370 param->level = LSMASH_MAX( param->level, sequence->level );
371 param->interlaced |= sequence->interlace;
372 uint32_t framerate = sequence->framerate_flag
373 ? ((double)sequence->framerate_numerator / sequence->framerate_denominator) + 0.5
374 : 0xffffffff; /* 0xffffffff means framerate is unknown or unspecified. */
375 if( param->framerate == 0 )
376 param->framerate = framerate;
377 else if( param->framerate != framerate )
378 param->framerate = 0xffffffff;
380 info->sequence.present = 1;
381 return bits->bs->error ? -1 : 0;
384 int vc1_parse_entry_point_header( vc1_info_t *info, uint8_t *ebdu, uint64_t ebdu_size, int try_append )
386 lsmash_bits_t *bits = info->bits;
387 vc1_sequence_header_t *sequence = &info->sequence;
388 vc1_entry_point_t *entry_point = &info->entry_point;
389 if( vc1_import_rbdu_from_ebdu( bits, info->buffer.rbdu, ebdu + VC1_START_CODE_LENGTH, ebdu_size ) < 0 )
390 return -1;
391 memset( entry_point, 0, sizeof(vc1_entry_point_t) );
392 uint8_t broken_link_flag = lsmash_bits_get( bits, 1 ); /* 0: no concatenation between the current and the previous entry points
393 * 1: concatenated and needed to discard B-pictures */
394 entry_point->closed_entry_point = lsmash_bits_get( bits, 1 ); /* 0: Open RAP, 1: Closed RAP */
395 IF_INVALID_VALUE( broken_link_flag && entry_point->closed_entry_point )
396 return -1; /* invalid combination */
397 lsmash_bits_get( bits, 4 ); /* panscan_flag (1)
398 * refdist_flag (1)
399 * loopfilter (1)
400 * fastuvmc (1) */
401 uint8_t extended_mv = lsmash_bits_get( bits, 1 );
402 lsmash_bits_get( bits, 6 ); /* dquant (2)
403 * vstransform (1)
404 * overlap (1)
405 * quantizer (2) */
406 if( sequence->hrd_param_flag )
407 for( uint8_t i = 0; i < sequence->hrd_param.hrd_num_leaky_buckets; i++ )
408 lsmash_bits_get( bits, 8 ); /* hrd_full */
409 /* Decide coded size here.
410 * The correct formula is defined in Amendment 2:2011 to SMPTE ST 421M:2006.
411 * Don't use the formula specified in SMPTE 421M-2006. */
412 uint16_t coded_width;
413 uint16_t coded_height;
414 if( lsmash_bits_get( bits, 1 ) ) /* coded_size_flag */
416 coded_width = lsmash_bits_get( bits, 12 );
417 coded_height = lsmash_bits_get( bits, 12 );
419 else
421 coded_width = sequence->max_coded_width;
422 coded_height = sequence->max_coded_height;
424 coded_width = 2 * (coded_width + 1); /* corrected */
425 coded_height = 2 * (coded_height + 1); /* corrected */
426 if( sequence->disp_horiz_size == 0 || sequence->disp_vert_size == 0 )
428 sequence->disp_horiz_size = coded_width;
429 sequence->disp_vert_size = coded_height;
431 /* */
432 if( extended_mv )
433 lsmash_bits_get( bits, 1 ); /* extended_dmv */
434 if( lsmash_bits_get( bits, 1 ) ) /* range_mapy_flag */
435 lsmash_bits_get( bits, 3 ); /* range_mapy */
436 if( lsmash_bits_get( bits, 1 ) ) /* range_mapuv_flag */
437 lsmash_bits_get( bits, 3 ); /* range_mapuv */
438 /* '1' and stuffing bits ('0's) */
439 IF_INVALID_VALUE( !lsmash_bits_get( bits, 1 ) )
440 return -1;
441 lsmash_bits_empty( bits );
442 /* Preparation for creating VC1SpecificBox */
443 if( try_append )
445 lsmash_vc1_specific_parameters_t *param = &info->dvc1_param;
446 lsmash_vc1_header_t *ephdr = param->ephdr;
447 if( !ephdr )
449 ephdr = lsmash_malloc( sizeof(lsmash_vc1_header_t) );
450 if( !ephdr )
451 return -1;
452 ephdr->ebdu = lsmash_memdup( ebdu, ebdu_size );
453 if( !ephdr->ebdu )
455 lsmash_free( ephdr );
456 return -1;
458 ephdr->ebdu_size = ebdu_size;
459 param->ephdr = ephdr;
461 else if( ephdr && ephdr->ebdu && (ephdr->ebdu_size == ebdu_size) )
462 param->multiple_entry |= !!memcmp( ebdu, ephdr->ebdu, ephdr->ebdu_size );
464 info->entry_point.present = 1;
465 return bits->bs->error ? -1 : 0;
468 int vc1_parse_advanced_picture( lsmash_bits_t *bits,
469 vc1_sequence_header_t *sequence, vc1_picture_info_t *picture,
470 uint8_t *rbdu_buffer, uint8_t *ebdu, uint64_t ebdu_size )
472 if( vc1_import_rbdu_from_ebdu( bits, rbdu_buffer, ebdu + VC1_START_CODE_LENGTH, ebdu_size ) < 0 )
473 return -1;
474 if( sequence->interlace )
475 picture->frame_coding_mode = vc1_get_vlc( bits, 2 );
476 else
477 picture->frame_coding_mode = 0;
478 if( picture->frame_coding_mode != 0x3 )
479 picture->type = vc1_get_vlc( bits, 4 ); /* ptype (variable length) */
480 else
481 picture->type = lsmash_bits_get( bits, 3 ); /* fptype (3) */
482 picture->present = 1;
483 lsmash_bits_empty( bits );
484 return bits->bs->error ? -1 : 0;
487 void vc1_update_au_property( vc1_access_unit_t *access_unit, vc1_picture_info_t *picture )
489 access_unit->random_accessible = picture->random_accessible;
490 access_unit->closed_gop = picture->closed_gop;
491 /* I-picture
492 * Be coded using information only from itself. (independent)
493 * All the macroblocks in an I-picture are intra-coded.
494 * P-picture
495 * Be coded using motion compensated prediction from past reference fields or frame.
496 * Can contain macroblocks that are inter-coded (i.e. coded using prediction) and macroblocks that are intra-coded.
497 * B-picture
498 * Be coded using motion compensated prediction from past and/or future reference fields or frames. (bi-predictive)
499 * Cannot be used for predicting any other picture. (disposable)
500 * BI-picture
501 * All the macroblocks in BI-picture are intra-coded. (independent)
502 * Cannot be used for predicting any other picture. (disposable) */
503 if( picture->frame_coding_mode == 0x3 )
505 /* field interlace */
506 access_unit->independent = picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_II || picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI;
507 access_unit->non_bipredictive = picture->type < VC1_ADVANCED_FIELD_PICTURE_TYPE_BB || picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI;
508 access_unit->disposable = picture->type >= VC1_ADVANCED_FIELD_PICTURE_TYPE_BB;
510 else
512 /* frame progressive/interlace */
513 access_unit->independent = picture->type == VC1_ADVANCED_PICTURE_TYPE_I || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
514 access_unit->non_bipredictive = picture->type != VC1_ADVANCED_PICTURE_TYPE_B;
515 access_unit->disposable = picture->type == VC1_ADVANCED_PICTURE_TYPE_B || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
517 picture->present = 0;
518 picture->type = 0;
519 picture->closed_gop = 0;
520 picture->start_of_sequence = 0;
521 picture->random_accessible = 0;
524 int vc1_find_au_delimit_by_bdu_type( uint8_t bdu_type, uint8_t prev_bdu_type )
526 /* In any access unit, EBDU with smaller least significant 8-bits of BDU type doesn't precede EBDU with larger one.
527 * Therefore, the condition: (bdu_type 0xF) > (prev_bdu_type & 0xF) is more precisely.
528 * No two or more frame start codes shall be in the same access unit. */
529 return bdu_type > prev_bdu_type || (bdu_type == 0x0D && prev_bdu_type == 0x0D);
532 int vc1_supplement_buffer( vc1_stream_buffer_t *sb, vc1_access_unit_t *access_unit, uint32_t size )
534 lsmash_multiple_buffers_t *bank = lsmash_resize_multiple_buffers( sb->bank, size );
535 if( !bank )
536 return -1;
537 sb->bank = bank;
538 sb->rbdu = lsmash_withdraw_buffer( bank, 1 );
539 if( access_unit && bank->number_of_buffers == 3 )
541 access_unit->data = lsmash_withdraw_buffer( bank, 2 );
542 access_unit->incomplete_data = lsmash_withdraw_buffer( bank, 3 );
544 return 0;
547 uint8_t *lsmash_create_vc1_specific_info( lsmash_vc1_specific_parameters_t *param, uint32_t *data_length )
549 if( !param || !data_length )
550 return NULL;
551 if( !param->seqhdr && !param->ephdr )
552 return NULL;
553 /* Calculate enough buffer size. */
554 lsmash_vc1_header_t *seqhdr = param->seqhdr;
555 lsmash_vc1_header_t *ephdr = param->ephdr;
556 uint32_t buffer_size = ISOM_BASEBOX_COMMON_SIZE + 7 + seqhdr->ebdu_size + ephdr->ebdu_size;
557 /* Set up bitstream writer. */
558 uint8_t buffer[buffer_size];
559 lsmash_bits_t bits = { 0 };
560 lsmash_bs_t bs = { 0 };
561 bs.buffer.data = buffer;
562 bs.buffer.alloc = buffer_size;
563 lsmash_bits_init( &bits, &bs );
564 /* Create a VC1SpecificBox */
565 lsmash_bits_put( &bits, 32, 0 ); /* box size */
566 lsmash_bits_put( &bits, 32, ISOM_BOX_TYPE_DVC1.fourcc ); /* box type: 'dvc1' */
567 lsmash_bits_put( &bits, 4, param->profile ); /* profile */
568 lsmash_bits_put( &bits, 3, param->level ); /* level */
569 lsmash_bits_put( &bits, 1, 0 ); /* reserved */
570 /* VC1AdvDecSpecStruc (for Advanced Profile) */
571 lsmash_bits_put( &bits, 3, param->level ); /* level (identical to the previous level field) */
572 lsmash_bits_put( &bits, 1, param->cbr ); /* cbr */
573 lsmash_bits_put( &bits, 6, 0 ); /* reserved */
574 lsmash_bits_put( &bits, 1, !param->interlaced ); /* no_interlace */
575 lsmash_bits_put( &bits, 1, !param->multiple_sequence ); /* no_multiple_seq */
576 lsmash_bits_put( &bits, 1, !param->multiple_entry ); /* no_multiple_entry */
577 lsmash_bits_put( &bits, 1, !param->slice_present ); /* no_slice_code */
578 lsmash_bits_put( &bits, 1, !param->bframe_present ); /* no_bframe */
579 lsmash_bits_put( &bits, 1, 0 ); /* reserved */
580 lsmash_bits_put( &bits, 32, param->framerate ); /* framerate */
581 /* seqhdr_ephdr[] */
582 for( uint32_t i = 0; i < seqhdr->ebdu_size; i++ )
583 lsmash_bits_put( &bits, 8, *(seqhdr->ebdu + i) );
584 for( uint32_t i = 0; i < ephdr->ebdu_size; i++ )
585 lsmash_bits_put( &bits, 8, *(ephdr->ebdu + i) );
586 /* */
587 uint8_t *data = lsmash_bits_export_data( &bits, data_length );
588 /* Update box size. */
589 LSMASH_SET_BE32( data, *data_length );
590 return data;
593 static int vc1_try_to_put_header( lsmash_vc1_header_t **p_hdr, uint8_t *multiple_hdr, void *hdr_data, uint32_t hdr_length )
595 lsmash_vc1_header_t *hdr = *p_hdr;
596 if( !hdr )
598 hdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
599 if( !hdr )
600 return -1;
602 else if( hdr->ebdu )
604 *multiple_hdr |= hdr->ebdu_size == hdr_length ? !!memcmp( hdr_data, hdr->ebdu, hdr->ebdu_size ) : 1;
605 return 0;
607 hdr->ebdu = lsmash_memdup( hdr_data, hdr_length );
608 hdr->ebdu_size = hdr->ebdu ? hdr_length : 0;
609 *p_hdr = hdr;
610 return hdr->ebdu ? 0 : -1;
613 int lsmash_put_vc1_header( lsmash_vc1_specific_parameters_t *param, void *hdr_data, uint32_t hdr_length )
615 if( !param || !hdr_data || hdr_length < 5 )
616 return -1;
617 /* Check start code prefix (0x000001). */
618 uint8_t *data = (uint8_t *)hdr_data;
619 if( data[0] != 0x00 || data[1] != 0x00 || data[2] != 0x01 )
620 return -1;
621 if( data[3] == 0x0F ) /* sequence header */
622 return vc1_try_to_put_header( &param->seqhdr, &param->multiple_sequence, hdr_data, hdr_length );
623 else if( data[3] == 0x0E ) /* entry point header */
624 return vc1_try_to_put_header( &param->ephdr, &param->multiple_entry, hdr_data, hdr_length );
625 return -1;
628 static int vc1_parse_succeeded( vc1_info_t *info, lsmash_vc1_specific_parameters_t *param )
630 int ret;
631 if( info->sequence.present && info->entry_point.present )
633 *param = info->dvc1_param;
634 /* Avoid freeing headers. */
635 info->dvc1_param.seqhdr = NULL;
636 info->dvc1_param.ephdr = NULL;
637 ret = 0;
639 else
640 ret = -1;
641 vc1_cleanup_parser( info );
642 return ret;
645 static inline int vc1_parse_failed( vc1_info_t *info )
647 vc1_cleanup_parser( info );
648 return -1;
651 int lsmash_setup_vc1_specific_parameters_from_access_unit( lsmash_vc1_specific_parameters_t *param, uint8_t *data, uint32_t data_length )
653 if( !param || !data || data_length == 0 )
654 return -1;
655 vc1_info_t *info = &(vc1_info_t){ { 0 } };
656 lsmash_bs_t *bs = &(lsmash_bs_t){ 0 };
657 if( lsmash_bs_set_empty_stream( bs, data, data_length ) < 0 )
658 return -1;
659 if( vc1_setup_parser( info, 1 ) < 0 )
660 return vc1_parse_failed( info );
661 info->dvc1_param = *param;
662 vc1_stream_buffer_t *sb = &info->buffer;
663 while( 1 )
665 uint8_t bdu_type;
666 uint64_t trailing_zero_bytes;
667 uint64_t ebdu_length = vc1_find_next_start_code_prefix( bs, &bdu_type, &trailing_zero_bytes );
668 if( ebdu_length <= VC1_START_CODE_LENGTH && lsmash_bs_is_end( bs, ebdu_length ) )
669 /* For the last EBDU. This EBDU already has been parsed. */
670 return vc1_parse_succeeded( info, param );
671 else if( bdu_type == 0xFF )
672 return vc1_parse_failed( info );
673 uint64_t next_ebdu_head_pos = info->ebdu_head_pos
674 + ebdu_length
675 + trailing_zero_bytes;
676 if( bdu_type >= 0x0A && bdu_type <= 0x0F )
678 /* Complete the current access unit if encountered delimiter of current access unit. */
679 if( vc1_find_au_delimit_by_bdu_type( bdu_type, info->prev_bdu_type ) )
680 /* The last video coded EBDU belongs to the access unit you want at this time. */
681 return vc1_parse_succeeded( info, param );
682 /* Increase the buffer if needed. */
683 if( sb->bank->buffer_size < ebdu_length
684 && vc1_supplement_buffer( sb, NULL, 2 * ebdu_length ) < 0 )
685 return vc1_parse_failed( info );
686 /* Process EBDU by its BDU type. */
687 uint8_t *ebdu = lsmash_bs_get_buffer_data( bs );
688 switch( bdu_type )
690 /* FRM_SC: Frame start code
691 * FLD_SC: Field start code
692 * SLC_SC: Slice start code
693 * SEQ_SC: Sequence header start code
694 * EP_SC: Entry-point start code
695 * PIC_L: Picture layer
696 * SLC_L: Slice layer
697 * SEQ_L: Sequence layer
698 * EP_L: Entry-point layer */
699 case 0x0D : /* Frame
700 * For the Progressive or Frame Interlace mode, shall signal the beginning of a new video frame.
701 * For the Field Interlace mode, shall signal the beginning of a sequence of two independently coded video fields.
702 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][[SLC_SC][SLC_L] (optional)] ... */
704 vc1_picture_info_t *picture = &info->picture;
705 if( vc1_parse_advanced_picture( info->bits, &info->sequence, picture, info->buffer.rbdu, ebdu, ebdu_length ) < 0 )
706 return vc1_parse_failed( info );
707 info->dvc1_param.bframe_present |= picture->frame_coding_mode == 0x3
708 ? picture->type >= VC1_ADVANCED_FIELD_PICTURE_TYPE_BB
709 : picture->type == VC1_ADVANCED_PICTURE_TYPE_B || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
711 case 0x0C : /* Field
712 * Shall only be used for Field Interlaced frames
713 * and shall only be used to signal the beginning of the second field of the frame.
714 * [FRM_SC][PIC_L][FLD_SC][PIC_L][[SLC_SC][SLC_L] (optional)] ...
715 * Field start code is followed by INTERLACE_FIELD_PICTURE_FIELD2() which doesn't have info of its field picture type.*/
716 break;
717 case 0x0B : /* Slice
718 * Shall not be used for start code of the first slice of a frame.
719 * Shall not be used for start code of the first slice of an interlace field coded picture.
720 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][SLC_SC][SLC_L][[SLC_SC][SLC_L] (optional)] ...
721 * Slice layer may repeat frame header. We just ignore it. */
722 info->dvc1_param.slice_present = 1;
723 break;
724 case 0x0E : /* Entry-point header
725 * Entry-point indicates the direct followed frame is a start of group of frames.
726 * Entry-point doesn't indicates the frame is a random access point when multiple sequence headers are present,
727 * since it is necessary to decode sequence header which subsequent frames belong to for decoding them.
728 * Entry point shall be followed by
729 * 1. I-picture - progressive or frame interlace
730 * 2. I/I-picture, I/P-picture, or P/I-picture - field interlace
731 * [[SEQ_SC][SEQ_L] (optional)][EP_SC][EP_L][FRM_SC][PIC_L] ... */
732 if( vc1_parse_entry_point_header( info, ebdu, ebdu_length, 1 ) < 0 )
733 return vc1_parse_failed( info );
734 break;
735 case 0x0F : /* Sequence header
736 * [SEQ_SC][SEQ_L][EP_SC][EP_L][FRM_SC][PIC_L] ... */
737 if( vc1_parse_sequence_header( info, ebdu, ebdu_length, 1 ) < 0 )
738 return vc1_parse_failed( info );
739 break;
740 default : /* End-of-sequence (0x0A) */
741 break;
744 /* Move to the first byte of the next EBDU. */
745 info->prev_bdu_type = bdu_type;
746 if( lsmash_bs_read_seek( bs, next_ebdu_head_pos, SEEK_SET ) != next_ebdu_head_pos )
747 return vc1_parse_failed( info );
748 /* Check if no more data to read from the stream. */
749 if( !lsmash_bs_is_end( bs, VC1_START_CODE_PREFIX_LENGTH ) )
750 info->ebdu_head_pos = next_ebdu_head_pos;
751 else
752 return vc1_parse_succeeded( info, param );
756 static inline int vc1_check_next_start_code_prefix( uint8_t *buf_pos, uint8_t *buf_end )
758 return ((buf_pos + 2) < buf_end) && !buf_pos[0] && !buf_pos[1] && (buf_pos[2] == 0x01);
761 int vc1_construct_specific_parameters( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
763 assert( dst && dst->data.structured && src && src->data.unstructured );
764 if( src->size < ISOM_BASEBOX_COMMON_SIZE + 7 )
765 return -1;
766 lsmash_vc1_specific_parameters_t *param = (lsmash_vc1_specific_parameters_t *)dst->data.structured;
767 uint8_t *data = src->data.unstructured;
768 uint64_t size = LSMASH_GET_BE32( data );
769 data += ISOM_BASEBOX_COMMON_SIZE;
770 if( size == 1 )
772 size = LSMASH_GET_BE64( data );
773 data += 8;
775 if( size != src->size )
776 return -1;
777 param->profile = (data[0] >> 4) & 0x0F;
778 if( param->profile != 12 )
779 return -1; /* We don't support profile other than 12 (Advanced profile). */
780 param->level = (data[0] >> 1) & 0x07;
781 param->cbr = (data[1] >> 4) & 0x01;
782 param->interlaced = !((data[2] >> 5) & 0x01);
783 param->multiple_sequence = !((data[2] >> 4) & 0x01);
784 param->multiple_entry = !((data[2] >> 3) & 0x01);
785 param->slice_present = !((data[2] >> 2) & 0x01);
786 param->bframe_present = !((data[2] >> 1) & 0x01);
787 param->framerate = LSMASH_GET_BE32( &data[3] );
788 /* Try to get seqhdr_ephdr[]. */
789 if( !param->seqhdr )
791 param->seqhdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
792 if( !param->seqhdr )
793 return -1;
795 if( !param->ephdr )
797 param->ephdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
798 if( !param->ephdr )
799 return -1;
801 lsmash_vc1_header_t *seqhdr = param->seqhdr;
802 lsmash_vc1_header_t *ephdr = param->ephdr;
803 data += 7;
804 uint8_t *pos = data;
805 uint8_t *end = src->data.unstructured + src->size;
806 /* Find the start point of Sequence header EBDU. */
807 while( pos < end )
809 if( vc1_check_next_start_code_prefix( pos, end ) && (pos + 3 < end) && *(pos + 3) == 0x0F )
811 seqhdr->ebdu_size = 4;
812 pos += 4;
813 break;
815 ++pos;
817 /* Find the end point of Sequence header EBDU. */
818 while( pos < end )
820 if( vc1_check_next_start_code_prefix( pos, end ) )
821 break;
822 ++ seqhdr->ebdu_size;
824 /* Find the start point of Entry-point header EBDU. */
825 while( pos < end )
827 if( vc1_check_next_start_code_prefix( pos, end ) && (pos + 3 < end) && *(pos + 3) == 0x0E )
829 ephdr->ebdu_size = 4;
830 pos += 4;
831 break;
833 ++pos;
835 /* Find the end point of Entry-point header EBDU. */
836 while( pos < end )
838 if( vc1_check_next_start_code_prefix( pos, end ) )
839 break;
840 ++ ephdr->ebdu_size;
842 /* Append the Sequence header EBDU and Entry-point header EBDU if present. */
843 if( seqhdr->ebdu_size )
845 lsmash_free( seqhdr->ebdu );
846 seqhdr->ebdu = lsmash_memdup( data, seqhdr->ebdu_size );
847 if( !seqhdr->ebdu )
848 return -1;
850 if( ephdr->ebdu_size )
852 lsmash_free( ephdr->ebdu );
853 ephdr->ebdu = lsmash_memdup( data, ephdr->ebdu_size );
854 if( !ephdr->ebdu )
855 return -1;
857 return 0;
860 int vc1_copy_codec_specific( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
862 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
863 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
864 lsmash_vc1_specific_parameters_t *src_data = (lsmash_vc1_specific_parameters_t *)src->data.structured;
865 lsmash_vc1_specific_parameters_t *dst_data = (lsmash_vc1_specific_parameters_t *)dst->data.structured;
866 lsmash_destroy_vc1_headers( dst_data );
867 *dst_data = *src_data;
868 if( !src_data->seqhdr && !src_data->ephdr )
869 return 0;
870 if( src_data->seqhdr )
872 dst_data->seqhdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
873 if( !dst_data->seqhdr )
874 return -1;
875 if( src_data->seqhdr->ebdu_size )
877 dst_data->seqhdr->ebdu = lsmash_memdup( src_data->seqhdr->ebdu, src_data->seqhdr->ebdu_size );
878 if( !dst_data->seqhdr->ebdu )
880 lsmash_destroy_vc1_headers( dst_data );
881 return -1;
884 dst_data->seqhdr->ebdu_size = src_data->seqhdr->ebdu_size;
886 if( src_data->ephdr )
888 dst_data->ephdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
889 if( !dst_data->ephdr )
891 lsmash_destroy_vc1_headers( dst_data );
892 return -1;
894 if( src_data->ephdr->ebdu_size )
896 dst_data->ephdr->ebdu = lsmash_memdup( src_data->ephdr->ebdu, src_data->ephdr->ebdu_size );
897 if( !dst_data->ephdr->ebdu )
899 lsmash_destroy_vc1_headers( dst_data );
900 return -1;
903 dst_data->ephdr->ebdu_size = src_data->ephdr->ebdu_size;
905 return 0;
908 int vc1_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
910 assert( fp && file && box && (box->manager & LSMASH_BINARY_CODED_BOX) );
911 int indent = level;
912 lsmash_ifprintf( fp, indent++, "[%s: VC1 Specific Box]\n", isom_4cc2str( box->type.fourcc ) );
913 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
914 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
915 if( box->size < ISOM_BASEBOX_COMMON_SIZE + 7 )
916 return -1;
917 uint8_t *data = box->binary;
918 isom_skip_box_common( &data );
919 uint8_t profile = (data[0] >> 4) & 0x0F;
920 if( profile != 12 )
921 return 0; /* We don't support profile other than 12 (Advanced profile). */
922 lsmash_ifprintf( fp, indent, "profile = %"PRIu8"\n", profile );
923 lsmash_ifprintf( fp, indent, "level = %"PRIu8"\n", (data[0] >> 1) & 0x07 );
924 lsmash_ifprintf( fp, indent, "reserved = %"PRIu8"\n", data[0] & 0x01 );
925 lsmash_ifprintf( fp, indent, "level = %"PRIu8"\n", (data[1] >> 5) & 0x07 );
926 lsmash_ifprintf( fp, indent, "cbr = %"PRIu8"\n", (data[1] >> 4) & 0x01 );
927 lsmash_ifprintf( fp, indent, "reserved1 = 0x%02"PRIx8"\n", (data[1] & 0x0F) | ((data[2] >> 6) & 0x03) );
928 lsmash_ifprintf( fp, indent, "no_interlace = %"PRIu8"\n", (data[2] >> 5) & 0x01 );
929 lsmash_ifprintf( fp, indent, "no_multiple_seq = %"PRIu8"\n", (data[2] >> 4) & 0x01 );
930 lsmash_ifprintf( fp, indent, "no_multiple_entry = %"PRIu8"\n", (data[2] >> 3) & 0x01 );
931 lsmash_ifprintf( fp, indent, "no_slice_code = %"PRIu8"\n", (data[2] >> 2) & 0x01 );
932 lsmash_ifprintf( fp, indent, "no_bframe = %"PRIu8"\n", (data[2] >> 1) & 0x01 );
933 lsmash_ifprintf( fp, indent, "reserved2 = %"PRIu8"\n", data[2] & 0x01 );
934 uint32_t framerate = LSMASH_GET_BE32( &data[3] );
935 lsmash_ifprintf( fp, indent, "framerate = %"PRIu32"\n", framerate );
936 uint32_t seqhdr_ephdr_size = box->size - (data - box->binary + 7);
937 if( seqhdr_ephdr_size )
939 lsmash_ifprintf( fp, indent, "seqhdr_ephdr[]\n" );
940 data += 7;
941 for( uint32_t i = 0; i < seqhdr_ephdr_size; i += 8 )
943 lsmash_ifprintf( fp, indent + 1, "" );
944 for( uint32_t j = 0; ; j++ )
945 if( j == 7 || (i + j == seqhdr_ephdr_size - 1) )
947 fprintf( fp, "0x%02"PRIx8"\n", data[i + j] );
948 break;
950 else
951 fprintf( fp, "0x%02"PRIx8" ", data[i + j] );
954 return 0;