1 /*****************************************************************************
2 * vc1.c
3 *****************************************************************************
4 * Copyright (C) 2012-2017 L-SMASH project
5 *
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7 *
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.
11 *
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 *****************************************************************************/
20
21 /* This file is available under an ISC license. */
22
23 #include "common/internal.h" /* must be placed first */
24
25 #include <string.h>
26 #include <stdlib.h>
27 #include <inttypes.h>
28
29 #include "core/box.h"
30
31 /***************************************************************************
32 SMPTE 421M-2006
33 SMPTE RP 2025-2007
34 ***************************************************************************/
35 #include "vc1.h"
36
37 struct lsmash_vc1_header_tag
38 {
39 uint8_t *ebdu;
40 uint32_t ebdu_size;
41 };
42
43 typedef enum
44 {
45 VC1_ADVANCED_PICTURE_TYPE_P = 0x0, /* 0b0 */
46 VC1_ADVANCED_PICTURE_TYPE_B = 0x2, /* 0b10 */
47 VC1_ADVANCED_PICTURE_TYPE_I = 0x6, /* 0b110 */
48 VC1_ADVANCED_PICTURE_TYPE_BI = 0xE, /* 0b1110 */
49 VC1_ADVANCED_PICTURE_TYPE_SKIPPED = 0xF, /* 0b1111 */
50 } vc1_picture_type;
51
52 typedef enum
53 {
54 VC1_ADVANCED_FIELD_PICTURE_TYPE_II = 0x0, /* 0b000 */
55 VC1_ADVANCED_FIELD_PICTURE_TYPE_IP = 0x1, /* 0b001 */
56 VC1_ADVANCED_FIELD_PICTURE_TYPE_PI = 0x2, /* 0b010 */
57 VC1_ADVANCED_FIELD_PICTURE_TYPE_PP = 0x3, /* 0b011 */
58 VC1_ADVANCED_FIELD_PICTURE_TYPE_BB = 0x4, /* 0b100 */
59 VC1_ADVANCED_FIELD_PICTURE_TYPE_BBI = 0x5, /* 0b101 */
60 VC1_ADVANCED_FIELD_PICTURE_TYPE_BIB = 0x6, /* 0b110 */
61 VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI = 0x7, /* 0b111 */
62 } vc1_field_picture_type;
63
64 typedef enum
65 {
66 VC1_FRAME_CODING_MODE_PROGRESSIVE = 0x0, /* 0b0 */
67 VC1_FRAME_CODING_MODE_FRAME_INTERLACE = 0x2, /* 0b10 */
68 VC1_FRAME_CODING_MODE_FIELD_INTERLACE = 0x3, /* 0b11 */
69 } vc1_frame_coding_mode;
70
vc1_destroy_header(lsmash_vc1_header_t * hdr)71 static void vc1_destroy_header( lsmash_vc1_header_t *hdr )
72 {
73 if( !hdr )
74 return;
75 lsmash_free( hdr->ebdu );
76 lsmash_free( hdr );
77 }
78
lsmash_destroy_vc1_headers(lsmash_vc1_specific_parameters_t * param)79 void lsmash_destroy_vc1_headers( lsmash_vc1_specific_parameters_t *param )
80 {
81 if( !param )
82 return;
83 vc1_destroy_header( param->seqhdr );
84 vc1_destroy_header( param->ephdr );
85 param->seqhdr = NULL;
86 param->ephdr = NULL;
87 }
88
vc1_destruct_specific_data(void * data)89 void vc1_destruct_specific_data( void *data )
90 {
91 if( !data )
92 return;
93 lsmash_destroy_vc1_headers( data );
94 lsmash_free( data );
95 }
96
vc1_cleanup_parser(vc1_info_t * info)97 void vc1_cleanup_parser( vc1_info_t *info )
98 {
99 if( !info )
100 return;
101 lsmash_destroy_vc1_headers( &info->dvc1_param );
102 lsmash_destroy_multiple_buffers( info->buffer.bank );
103 lsmash_bits_adhoc_cleanup( info->bits );
104 info->bits = NULL;
105 }
106
vc1_setup_parser(vc1_info_t * info,int parse_only)107 int vc1_setup_parser
108 (
109 vc1_info_t *info,
110 int parse_only
111 )
112 {
113 assert( info );
114 memset( info, 0, sizeof(vc1_info_t) );
115 vc1_stream_buffer_t *sb = &info->buffer;
116 sb->bank = lsmash_create_multiple_buffers( parse_only ? 1 : 3, VC1_DEFAULT_BUFFER_SIZE );
117 if( !sb->bank )
118 return LSMASH_ERR_MEMORY_ALLOC;
119 sb->rbdu = lsmash_withdraw_buffer( sb->bank, 1 );
120 if( !parse_only )
121 {
122 info->access_unit.data = lsmash_withdraw_buffer( sb->bank, 2 );
123 info->access_unit.incomplete_data = lsmash_withdraw_buffer( sb->bank, 3 );
124 }
125 info->bits = lsmash_bits_adhoc_create();
126 if( !info->bits )
127 {
128 lsmash_destroy_multiple_buffers( sb->bank );
129 return LSMASH_ERR_MEMORY_ALLOC;
130 }
131 info->prev_bdu_type = 0xFF; /* 0xFF is a forbidden value. */
132 return 0;
133 }
134
vc1_find_next_start_code_prefix(lsmash_bs_t * bs,uint8_t * bdu_type,uint64_t * trailing_zero_bytes)135 uint64_t vc1_find_next_start_code_prefix
136 (
137 lsmash_bs_t *bs,
138 uint8_t *bdu_type,
139 uint64_t *trailing_zero_bytes
140 )
141 {
142 uint64_t length = 0; /* the length of the latest EBDU */
143 uint64_t count = 0; /* the number of the trailing zero bytes after the latest EBDU */
144 if( !lsmash_bs_is_end( bs, VC1_START_CODE_LENGTH - 1 )
145 && 0x000001 == lsmash_bs_show_be24( bs, 0 ) )
146 {
147 *bdu_type = lsmash_bs_show_byte( bs, VC1_START_CODE_PREFIX_LENGTH );
148 length = VC1_START_CODE_LENGTH;
149 /* Find the start code of the next EBDU and get the length of the latest EBDU. */
150 int no_more = lsmash_bs_is_end( bs, length + VC1_START_CODE_LENGTH - 1 );
151 if( !no_more )
152 {
153 uint32_t sync_bytes = lsmash_bs_show_be24( bs, length );
154 while( 0x000001 != sync_bytes )
155 {
156 no_more = lsmash_bs_is_end( bs, ++length + VC1_START_CODE_LENGTH - 1 );
157 if( no_more )
158 break;
159 sync_bytes <<= 8;
160 sync_bytes |= lsmash_bs_show_byte( bs, length + VC1_START_CODE_PREFIX_LENGTH - 1 );
161 sync_bytes &= 0xFFFFFF;
162 }
163 }
164 if( no_more )
165 length = lsmash_bs_get_remaining_buffer_size( bs );
166 /* Any EBDU has no consecutive zero bytes at the end. */
167 while( 0x00 == lsmash_bs_show_byte( bs, length - 1 ) )
168 {
169 --length;
170 ++count;
171 }
172 }
173 else
174 *bdu_type = 0xFF; /* 0xFF is a forbidden value. */
175 *trailing_zero_bytes = count;
176 return length;
177 }
178
vc1_check_next_start_code_suffix(lsmash_bs_t * bs,uint8_t * p_bdu_type)179 int vc1_check_next_start_code_suffix
180 (
181 lsmash_bs_t *bs,
182 uint8_t *p_bdu_type
183 )
184 {
185 uint8_t bdu_type = *((uint8_t *)lsmash_bs_get_buffer_data( bs ) + VC1_START_CODE_PREFIX_LENGTH);
186 if( (bdu_type >= 0x00 && bdu_type <= 0x09)
187 || (bdu_type >= 0x20 && bdu_type <= 0x7F) )
188 return LSMASH_ERR_NAMELESS; /* SMPTE reserved */
189 if( bdu_type >= 0x80 && bdu_type <= 0xFF )
190 return LSMASH_ERR_INVALID_DATA; /* Forbidden */
191 *p_bdu_type = bdu_type;
192 return 0;
193 }
194
vc1_get_vlc(lsmash_bits_t * bits,int length)195 static inline uint8_t vc1_get_vlc( lsmash_bits_t *bits, int length )
196 {
197 uint8_t value = 0;
198 for( int i = 0; i < length; i++ )
199 if( lsmash_bits_get( bits, 1 ) )
200 value = (value << 1) | 1;
201 else
202 {
203 value = value << 1;
204 break;
205 }
206 return value;
207 }
208
209 /* Convert EBDU (Encapsulated Byte Data Unit) to RBDU (Raw Byte Data Unit). */
vc1_remove_emulation_prevention(uint8_t * src,uint64_t src_length,uint8_t * dst)210 static uint8_t *vc1_remove_emulation_prevention( uint8_t *src, uint64_t src_length, uint8_t *dst )
211 {
212 uint8_t *src_end = src + src_length;
213 while( src < src_end )
214 if( ((src + 2) < src_end) && !src[0] && !src[1] && (src[2] == 0x03) )
215 {
216 /* 0x000003 -> 0x0000 */
217 *dst++ = *src++;
218 *dst++ = *src++;
219 src++; /* Skip emulation_prevention_three_byte (0x03). */
220 }
221 else
222 *dst++ = *src++;
223 return dst;
224 }
225
vc1_import_rbdu_from_ebdu(lsmash_bits_t * bits,uint8_t * rbdu_buffer,uint8_t * ebdu,uint64_t ebdu_size)226 static int vc1_import_rbdu_from_ebdu( lsmash_bits_t *bits, uint8_t *rbdu_buffer, uint8_t *ebdu, uint64_t ebdu_size )
227 {
228 uint8_t *rbdu_start = rbdu_buffer;
229 uint8_t *rbdu_end = vc1_remove_emulation_prevention( ebdu, ebdu_size, rbdu_buffer );
230 uint64_t rbdu_length = rbdu_end - rbdu_start;
231 return lsmash_bits_import_data( bits, rbdu_start, rbdu_length );
232 }
233
vc1_parse_hrd_param(lsmash_bits_t * bits,vc1_hrd_param_t * hrd_param)234 static void vc1_parse_hrd_param( lsmash_bits_t *bits, vc1_hrd_param_t *hrd_param )
235 {
236 hrd_param->hrd_num_leaky_buckets = lsmash_bits_get( bits, 5 );
237 lsmash_bits_get( bits, 4 ); /* bitrate_exponent */
238 lsmash_bits_get( bits, 4 ); /* buffer_size_exponent */
239 for( uint8_t i = 0; i < hrd_param->hrd_num_leaky_buckets; i++ )
240 {
241 lsmash_bits_get( bits, 16 ); /* hrd_rate */
242 lsmash_bits_get( bits, 16 ); /* hrd_buffer */
243 }
244 }
245
vc1_parse_sequence_header(vc1_info_t * info,uint8_t * ebdu,uint64_t ebdu_size,int try_append)246 int vc1_parse_sequence_header( vc1_info_t *info, uint8_t *ebdu, uint64_t ebdu_size, int try_append )
247 {
248 lsmash_bits_t *bits = info->bits;
249 vc1_sequence_header_t *sequence = &info->sequence;
250 int err = vc1_import_rbdu_from_ebdu( bits, info->buffer.rbdu, ebdu + VC1_START_CODE_LENGTH, ebdu_size );
251 if( err < 0 )
252 return err;
253 memset( sequence, 0, sizeof(vc1_sequence_header_t) );
254 sequence->profile = lsmash_bits_get( bits, 2 );
255 if( sequence->profile != 3 )
256 return LSMASH_ERR_NAMELESS; /* SMPTE Reserved */
257 sequence->level = lsmash_bits_get( bits, 3 );
258 if( sequence->level > 4 )
259 return LSMASH_ERR_NAMELESS; /* SMPTE Reserved */
260 sequence->colordiff_format = lsmash_bits_get( bits, 2 );
261 if( sequence->colordiff_format != 1 )
262 return LSMASH_ERR_NAMELESS; /* 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 */
275 {
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 */
279 {
280 uint8_t aspect_ratio = lsmash_bits_get( bits, 4 );
281 if( aspect_ratio == 15 )
282 {
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 */
285 }
286 else
287 {
288 static const struct
289 {
290 uint32_t aspect_width;
291 uint32_t aspect_height;
292 } vc1_aspect_ratio[15] =
293 {
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 */
297 };
298 sequence->aspect_width = vc1_aspect_ratio[ aspect_ratio ].aspect_width;
299 sequence->aspect_height = vc1_aspect_ratio[ aspect_ratio ].aspect_height;
300 }
301 }
302 sequence->framerate_flag = lsmash_bits_get( bits, 1 );
303 if( sequence->framerate_flag )
304 {
305 if( lsmash_bits_get( bits, 1 ) ) /* framerateind */
306 {
307 sequence->framerate_numerator = lsmash_bits_get( bits, 16 ) + 1;
308 sequence->framerate_denominator = 32;
309 }
310 else
311 {
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( frameratenr == 0 )
315 return LSMASH_ERR_INVALID_DATA; /* Forbidden */
316 if( frameratenr > 7 )
317 return LSMASH_ERR_NAMELESS; /* SMPTE Reserved */
318 uint8_t frameratedr = lsmash_bits_get( bits, 4 );
319 if( frameratedr != 1 && frameratedr != 2 )
320 /* 0: Forbidden, 3-15: SMPTE Reserved */
321 return frameratedr == 0
322 ? LSMASH_ERR_INVALID_DATA
323 : LSMASH_ERR_NAMELESS;
324 if( frameratedr == 1 )
325 {
326 sequence->framerate_numerator = vc1_frameratenr_table[ frameratenr ];
327 sequence->framerate_denominator = 1;
328 }
329 else
330 {
331 sequence->framerate_numerator = vc1_frameratenr_table[ frameratenr ] * 1000;
332 sequence->framerate_denominator = 1001;
333 }
334 }
335 }
336 if( lsmash_bits_get( bits, 1 ) ) /* color_format_flag */
337 {
338 sequence->color_prim = lsmash_bits_get( bits, 8 );
339 sequence->transfer_char = lsmash_bits_get( bits, 8 );
340 sequence->matrix_coef = lsmash_bits_get( bits, 8 );
341 }
342 sequence->hrd_param_flag = lsmash_bits_get( bits, 1 );
343 if( sequence->hrd_param_flag )
344 vc1_parse_hrd_param( bits, &sequence->hrd_param );
345 }
346 /* '1' and stuffing bits ('0's) */
347 if( !lsmash_bits_get( bits, 1 ) )
348 return LSMASH_ERR_INVALID_DATA;
349 lsmash_bits_empty( bits );
350 /* Preparation for creating VC1SpecificBox */
351 if( try_append )
352 {
353 /* Update some specific parameters. */
354 lsmash_vc1_specific_parameters_t *param = &info->dvc1_param;
355 lsmash_vc1_header_t *seqhdr = param->seqhdr;
356 if( !seqhdr )
357 {
358 seqhdr = lsmash_malloc( sizeof(lsmash_vc1_header_t) );
359 if( !seqhdr )
360 return LSMASH_ERR_MEMORY_ALLOC;
361 seqhdr->ebdu = lsmash_memdup( ebdu, ebdu_size );
362 if( !seqhdr->ebdu )
363 {
364 lsmash_free( seqhdr );
365 return LSMASH_ERR_MEMORY_ALLOC;
366 }
367 seqhdr->ebdu_size = ebdu_size;
368 param->seqhdr = seqhdr;
369 }
370 else if( seqhdr && seqhdr->ebdu && (seqhdr->ebdu_size == ebdu_size) )
371 param->multiple_sequence |= !!memcmp( ebdu, seqhdr->ebdu, seqhdr->ebdu_size );
372 param->profile = sequence->profile << 2;
373 param->level = LSMASH_MAX( param->level, sequence->level );
374 param->interlaced |= sequence->interlace;
375 uint32_t framerate = sequence->framerate_flag
376 ? ((double)sequence->framerate_numerator / sequence->framerate_denominator) + 0.5
377 : 0xffffffff; /* 0xffffffff means framerate is unknown or unspecified. */
378 if( param->framerate == 0 )
379 param->framerate = framerate;
380 else if( param->framerate != framerate )
381 param->framerate = 0xffffffff;
382 }
383 info->sequence.present = 1;
384 return bits->bs->error ? LSMASH_ERR_NAMELESS : 0;
385 }
386
vc1_parse_entry_point_header(vc1_info_t * info,uint8_t * ebdu,uint64_t ebdu_size,int try_append)387 int vc1_parse_entry_point_header( vc1_info_t *info, uint8_t *ebdu, uint64_t ebdu_size, int try_append )
388 {
389 lsmash_bits_t *bits = info->bits;
390 vc1_sequence_header_t *sequence = &info->sequence;
391 vc1_entry_point_t *entry_point = &info->entry_point;
392 int err = vc1_import_rbdu_from_ebdu( bits, info->buffer.rbdu, ebdu + VC1_START_CODE_LENGTH, ebdu_size );
393 if( err < 0 )
394 return err;
395 memset( entry_point, 0, sizeof(vc1_entry_point_t) );
396 uint8_t broken_link_flag = lsmash_bits_get( bits, 1 ); /* 0: no concatenation between the current and the previous entry points
397 * 1: concatenated and needed to discard B-pictures */
398 entry_point->closed_entry_point = lsmash_bits_get( bits, 1 ); /* 0: Open RAP, 1: Closed RAP */
399 if( broken_link_flag && entry_point->closed_entry_point )
400 return LSMASH_ERR_INVALID_DATA; /* invalid combination */
401 lsmash_bits_get( bits, 4 ); /* panscan_flag (1)
402 * refdist_flag (1)
403 * loopfilter (1)
404 * fastuvmc (1) */
405 uint8_t extended_mv = lsmash_bits_get( bits, 1 );
406 lsmash_bits_get( bits, 6 ); /* dquant (2)
407 * vstransform (1)
408 * overlap (1)
409 * quantizer (2) */
410 if( sequence->hrd_param_flag )
411 for( uint8_t i = 0; i < sequence->hrd_param.hrd_num_leaky_buckets; i++ )
412 lsmash_bits_get( bits, 8 ); /* hrd_full */
413 /* Decide coded size here.
414 * The correct formula is defined in Amendment 2:2011 to SMPTE ST 421M:2006.
415 * Don't use the formula specified in SMPTE 421M-2006. */
416 uint16_t coded_width;
417 uint16_t coded_height;
418 if( lsmash_bits_get( bits, 1 ) ) /* coded_size_flag */
419 {
420 coded_width = lsmash_bits_get( bits, 12 );
421 coded_height = lsmash_bits_get( bits, 12 );
422 }
423 else
424 {
425 coded_width = sequence->max_coded_width;
426 coded_height = sequence->max_coded_height;
427 }
428 coded_width = 2 * (coded_width + 1); /* corrected */
429 coded_height = 2 * (coded_height + 1); /* corrected */
430 if( sequence->disp_horiz_size == 0 || sequence->disp_vert_size == 0 )
431 {
432 sequence->disp_horiz_size = coded_width;
433 sequence->disp_vert_size = coded_height;
434 }
435 /* */
436 if( extended_mv )
437 lsmash_bits_get( bits, 1 ); /* extended_dmv */
438 if( lsmash_bits_get( bits, 1 ) ) /* range_mapy_flag */
439 lsmash_bits_get( bits, 3 ); /* range_mapy */
440 if( lsmash_bits_get( bits, 1 ) ) /* range_mapuv_flag */
441 lsmash_bits_get( bits, 3 ); /* range_mapuv */
442 /* '1' and stuffing bits ('0's) */
443 if( !lsmash_bits_get( bits, 1 ) )
444 return LSMASH_ERR_INVALID_DATA;
445 lsmash_bits_empty( bits );
446 /* Preparation for creating VC1SpecificBox */
447 if( try_append )
448 {
449 lsmash_vc1_specific_parameters_t *param = &info->dvc1_param;
450 lsmash_vc1_header_t *ephdr = param->ephdr;
451 if( !ephdr )
452 {
453 ephdr = lsmash_malloc( sizeof(lsmash_vc1_header_t) );
454 if( !ephdr )
455 return LSMASH_ERR_MEMORY_ALLOC;
456 ephdr->ebdu = lsmash_memdup( ebdu, ebdu_size );
457 if( !ephdr->ebdu )
458 {
459 lsmash_free( ephdr );
460 return LSMASH_ERR_MEMORY_ALLOC;
461 }
462 ephdr->ebdu_size = ebdu_size;
463 param->ephdr = ephdr;
464 }
465 else if( ephdr && ephdr->ebdu && (ephdr->ebdu_size == ebdu_size) )
466 param->multiple_entry |= !!memcmp( ebdu, ephdr->ebdu, ephdr->ebdu_size );
467 }
468 info->entry_point.present = 1;
469 return bits->bs->error ? LSMASH_ERR_NAMELESS : 0;
470 }
471
vc1_parse_advanced_picture(lsmash_bits_t * bits,vc1_sequence_header_t * sequence,vc1_picture_info_t * picture,uint8_t * rbdu_buffer,uint8_t * ebdu,uint64_t ebdu_size)472 int vc1_parse_advanced_picture( lsmash_bits_t *bits,
473 vc1_sequence_header_t *sequence, vc1_picture_info_t *picture,
474 uint8_t *rbdu_buffer, uint8_t *ebdu, uint64_t ebdu_size )
475 {
476 int err = vc1_import_rbdu_from_ebdu( bits, rbdu_buffer, ebdu + VC1_START_CODE_LENGTH, ebdu_size );
477 if( err < 0 )
478 return err;
479 if( sequence->interlace )
480 picture->frame_coding_mode = vc1_get_vlc( bits, 2 );
481 else
482 picture->frame_coding_mode = 0;
483 if( picture->frame_coding_mode != 0x3 )
484 picture->type = vc1_get_vlc( bits, 4 ); /* ptype (variable length) */
485 else
486 picture->type = lsmash_bits_get( bits, 3 ); /* fptype (3) */
487 picture->present = 1;
488 lsmash_bits_empty( bits );
489 return bits->bs->error ? LSMASH_ERR_NAMELESS : 0;
490 }
491
vc1_update_au_property(vc1_access_unit_t * access_unit,vc1_picture_info_t * picture)492 void vc1_update_au_property( vc1_access_unit_t *access_unit, vc1_picture_info_t *picture )
493 {
494 access_unit->random_accessible = picture->random_accessible;
495 access_unit->closed_gop = picture->closed_gop;
496 /* I-picture
497 * Be coded using information only from itself. (independent)
498 * All the macroblocks in an I-picture are intra-coded.
499 * P-picture
500 * Be coded using motion compensated prediction from past reference fields or frame.
501 * Can contain macroblocks that are inter-coded (i.e. coded using prediction) and macroblocks that are intra-coded.
502 * B-picture
503 * Be coded using motion compensated prediction from past and/or future reference fields or frames. (bi-predictive)
504 * Cannot be used for predicting any other picture. (disposable)
505 * BI-picture
506 * All the macroblocks in BI-picture are intra-coded. (independent)
507 * Cannot be used for predicting any other picture. (disposable) */
508 if( picture->frame_coding_mode == 0x3 )
509 {
510 /* field interlace */
511 access_unit->independent = picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_II || picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI;
512 access_unit->non_bipredictive = picture->type < VC1_ADVANCED_FIELD_PICTURE_TYPE_BB || picture->type == VC1_ADVANCED_FIELD_PICTURE_TYPE_BIBI;
513 access_unit->disposable = picture->type >= VC1_ADVANCED_FIELD_PICTURE_TYPE_BB;
514 }
515 else
516 {
517 /* frame progressive/interlace */
518 access_unit->independent = picture->type == VC1_ADVANCED_PICTURE_TYPE_I || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
519 access_unit->non_bipredictive = picture->type != VC1_ADVANCED_PICTURE_TYPE_B;
520 access_unit->disposable = picture->type == VC1_ADVANCED_PICTURE_TYPE_B || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
521 }
522 picture->present = 0;
523 picture->type = 0;
524 picture->closed_gop = 0;
525 picture->start_of_sequence = 0;
526 picture->random_accessible = 0;
527 }
528
vc1_find_au_delimit_by_bdu_type(uint8_t bdu_type,uint8_t prev_bdu_type)529 int vc1_find_au_delimit_by_bdu_type( uint8_t bdu_type, uint8_t prev_bdu_type )
530 {
531 /* In any access unit, EBDU with smaller least significant 8-bits of BDU type doesn't precede EBDU with larger one.
532 * Therefore, the condition: (bdu_type 0xF) > (prev_bdu_type & 0xF) is more precisely.
533 * No two or more frame start codes shall be in the same access unit. */
534 return bdu_type > prev_bdu_type || (bdu_type == 0x0D && prev_bdu_type == 0x0D);
535 }
536
vc1_supplement_buffer(vc1_stream_buffer_t * sb,vc1_access_unit_t * access_unit,uint32_t size)537 int vc1_supplement_buffer( vc1_stream_buffer_t *sb, vc1_access_unit_t *access_unit, uint32_t size )
538 {
539 lsmash_multiple_buffers_t *bank = lsmash_resize_multiple_buffers( sb->bank, size );
540 if( !bank )
541 return LSMASH_ERR_MEMORY_ALLOC;
542 sb->bank = bank;
543 sb->rbdu = lsmash_withdraw_buffer( bank, 1 );
544 if( access_unit && bank->number_of_buffers == 3 )
545 {
546 access_unit->data = lsmash_withdraw_buffer( bank, 2 );
547 access_unit->incomplete_data = lsmash_withdraw_buffer( bank, 3 );
548 }
549 return 0;
550 }
551
lsmash_create_vc1_specific_info(lsmash_vc1_specific_parameters_t * param,uint32_t * data_length)552 uint8_t *lsmash_create_vc1_specific_info( lsmash_vc1_specific_parameters_t *param, uint32_t *data_length )
553 {
554 if( !param || !data_length )
555 return NULL;
556 if( !param->seqhdr || !param->ephdr )
557 return NULL;
558 /* Calculate enough buffer size. */
559 lsmash_vc1_header_t *seqhdr = param->seqhdr;
560 lsmash_vc1_header_t *ephdr = param->ephdr;
561 /* Create a VC1SpecificBox */
562 lsmash_bits_t *bits = lsmash_bits_adhoc_create();
563 if( !bits )
564 return NULL;
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 lsmash_bits_adhoc_cleanup( bits );
589 /* Update box size. */
590 LSMASH_SET_BE32( data, *data_length );
591 return data;
592 }
593
vc1_try_to_put_header(lsmash_vc1_header_t ** p_hdr,uint8_t * multiple_hdr,void * hdr_data,uint32_t hdr_length)594 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 {
596 lsmash_vc1_header_t *hdr = *p_hdr;
597 if( !hdr )
598 {
599 hdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
600 if( !hdr )
601 return LSMASH_ERR_MEMORY_ALLOC;
602 }
603 else if( hdr->ebdu )
604 {
605 *multiple_hdr |= hdr->ebdu_size == hdr_length ? !!memcmp( hdr_data, hdr->ebdu, hdr->ebdu_size ) : 1;
606 return 0;
607 }
608 hdr->ebdu = lsmash_memdup( hdr_data, hdr_length );
609 hdr->ebdu_size = hdr->ebdu ? hdr_length : 0;
610 *p_hdr = hdr;
611 return hdr->ebdu ? 0 : LSMASH_ERR_MEMORY_ALLOC;
612 }
613
lsmash_put_vc1_header(lsmash_vc1_specific_parameters_t * param,void * hdr_data,uint32_t hdr_length)614 int lsmash_put_vc1_header( lsmash_vc1_specific_parameters_t *param, void *hdr_data, uint32_t hdr_length )
615 {
616 if( !param || !hdr_data || hdr_length < 5 )
617 return LSMASH_ERR_FUNCTION_PARAM;
618 /* Check start code prefix (0x000001). */
619 uint8_t *data = (uint8_t *)hdr_data;
620 if( data[0] != 0x00 || data[1] != 0x00 || data[2] != 0x01 )
621 return LSMASH_ERR_INVALID_DATA;
622 if( data[3] == 0x0F ) /* sequence header */
623 return vc1_try_to_put_header( ¶m->seqhdr, ¶m->multiple_sequence, hdr_data, hdr_length );
624 else if( data[3] == 0x0E ) /* entry point header */
625 return vc1_try_to_put_header( ¶m->ephdr, ¶m->multiple_entry, hdr_data, hdr_length );
626 return LSMASH_ERR_INVALID_DATA;
627 }
628
vc1_parse_succeeded(vc1_info_t * info,lsmash_vc1_specific_parameters_t * param)629 static int vc1_parse_succeeded
630 (
631 vc1_info_t *info,
632 lsmash_vc1_specific_parameters_t *param
633 )
634 {
635 int ret;
636 if( info->sequence.present && info->entry_point.present )
637 {
638 *param = info->dvc1_param;
639 /* Avoid freeing headers. */
640 info->dvc1_param.seqhdr = NULL;
641 info->dvc1_param.ephdr = NULL;
642 ret = 0;
643 }
644 else
645 ret = LSMASH_ERR_INVALID_DATA;
646 vc1_cleanup_parser( info );
647 return ret;
648 }
649
vc1_parse_failed(vc1_info_t * info,int ret)650 static inline int vc1_parse_failed
651 (
652 vc1_info_t *info,
653 int ret
654 )
655 {
656 vc1_cleanup_parser( info );
657 return ret;
658 }
659
lsmash_setup_vc1_specific_parameters_from_access_unit(lsmash_vc1_specific_parameters_t * param,uint8_t * data,uint32_t data_length)660 int lsmash_setup_vc1_specific_parameters_from_access_unit( lsmash_vc1_specific_parameters_t *param, uint8_t *data, uint32_t data_length )
661 {
662 if( !param || !data || data_length == 0 )
663 return LSMASH_ERR_FUNCTION_PARAM;
664 vc1_info_t *info = &(vc1_info_t){ { 0 } };
665 lsmash_bs_t *bs = &(lsmash_bs_t){ 0 };
666 int err = lsmash_bs_set_empty_stream( bs, data, data_length );
667 if( err < 0 )
668 return err;
669 if( (err = vc1_setup_parser( info, 1 )) < 0 )
670 return vc1_parse_failed( info, err );
671 info->dvc1_param = *param;
672 vc1_stream_buffer_t *sb = &info->buffer;
673 while( 1 )
674 {
675 uint8_t bdu_type;
676 uint64_t trailing_zero_bytes;
677 uint64_t ebdu_length = vc1_find_next_start_code_prefix( bs, &bdu_type, &trailing_zero_bytes );
678 if( ebdu_length <= VC1_START_CODE_LENGTH && lsmash_bs_is_end( bs, ebdu_length ) )
679 /* For the last EBDU. This EBDU already has been parsed. */
680 return vc1_parse_succeeded( info, param );
681 else if( bdu_type == 0xFF )
682 return vc1_parse_failed( info, LSMASH_ERR_INVALID_DATA );
683 uint64_t next_ebdu_head_pos = info->ebdu_head_pos
684 + ebdu_length
685 + trailing_zero_bytes;
686 if( bdu_type >= 0x0A && bdu_type <= 0x0F )
687 {
688 /* Complete the current access unit if encountered delimiter of current access unit. */
689 if( vc1_find_au_delimit_by_bdu_type( bdu_type, info->prev_bdu_type ) )
690 /* The last video coded EBDU belongs to the access unit you want at this time. */
691 return vc1_parse_succeeded( info, param );
692 /* Increase the buffer if needed. */
693 if( sb->bank->buffer_size < ebdu_length
694 && (err = vc1_supplement_buffer( sb, NULL, 2 * ebdu_length )) < 0 )
695 return vc1_parse_failed( info, err );
696 /* Process EBDU by its BDU type. */
697 uint8_t *ebdu = lsmash_bs_get_buffer_data( bs );
698 switch( bdu_type )
699 {
700 /* FRM_SC: Frame start code
701 * FLD_SC: Field start code
702 * SLC_SC: Slice start code
703 * SEQ_SC: Sequence header start code
704 * EP_SC: Entry-point start code
705 * PIC_L: Picture layer
706 * SLC_L: Slice layer
707 * SEQ_L: Sequence layer
708 * EP_L: Entry-point layer */
709 case 0x0D : /* Frame
710 * For the Progressive or Frame Interlace mode, shall signal the beginning of a new video frame.
711 * For the Field Interlace mode, shall signal the beginning of a sequence of two independently coded video fields.
712 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][[SLC_SC][SLC_L] (optional)] ... */
713 {
714 vc1_picture_info_t *picture = &info->picture;
715 if( (err = vc1_parse_advanced_picture( info->bits, &info->sequence, picture, info->buffer.rbdu, ebdu, ebdu_length )) < 0 )
716 return vc1_parse_failed( info, err );
717 info->dvc1_param.bframe_present |= picture->frame_coding_mode == 0x3
718 ? picture->type >= VC1_ADVANCED_FIELD_PICTURE_TYPE_BB
719 : picture->type == VC1_ADVANCED_PICTURE_TYPE_B || picture->type == VC1_ADVANCED_PICTURE_TYPE_BI;
720 }
721 case 0x0C : /* Field
722 * Shall only be used for Field Interlaced frames
723 * and shall only be used to signal the beginning of the second field of the frame.
724 * [FRM_SC][PIC_L][FLD_SC][PIC_L][[SLC_SC][SLC_L] (optional)] ...
725 * Field start code is followed by INTERLACE_FIELD_PICTURE_FIELD2() which doesn't have info of its field picture type.*/
726 break;
727 case 0x0B : /* Slice
728 * Shall not be used for start code of the first slice of a frame.
729 * Shall not be used for start code of the first slice of an interlace field coded picture.
730 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][SLC_SC][SLC_L][[SLC_SC][SLC_L] (optional)] ...
731 * Slice layer may repeat frame header. We just ignore it. */
732 info->dvc1_param.slice_present = 1;
733 break;
734 case 0x0E : /* Entry-point header
735 * Entry-point indicates the direct followed frame is a start of group of frames.
736 * Entry-point doesn't indicates the frame is a random access point when multiple sequence headers are present,
737 * since it is necessary to decode sequence header which subsequent frames belong to for decoding them.
738 * Entry point shall be followed by
739 * 1. I-picture - progressive or frame interlace
740 * 2. I/I-picture, I/P-picture, or P/I-picture - field interlace
741 * [[SEQ_SC][SEQ_L] (optional)][EP_SC][EP_L][FRM_SC][PIC_L] ... */
742 if( (err = vc1_parse_entry_point_header( info, ebdu, ebdu_length, 1 )) < 0 )
743 return vc1_parse_failed( info, err );
744 break;
745 case 0x0F : /* Sequence header
746 * [SEQ_SC][SEQ_L][EP_SC][EP_L][FRM_SC][PIC_L] ... */
747 if( (err = vc1_parse_sequence_header( info, ebdu, ebdu_length, 1 )) < 0 )
748 return vc1_parse_failed( info, err );
749 break;
750 default : /* End-of-sequence (0x0A) */
751 break;
752 }
753 }
754 /* Move to the first byte of the next EBDU. */
755 info->prev_bdu_type = bdu_type;
756 if( lsmash_bs_read_seek( bs, next_ebdu_head_pos, SEEK_SET ) != next_ebdu_head_pos )
757 return vc1_parse_failed( info, LSMASH_ERR_NAMELESS );
758 /* Check if no more data to read from the stream. */
759 if( !lsmash_bs_is_end( bs, VC1_START_CODE_PREFIX_LENGTH ) )
760 info->ebdu_head_pos = next_ebdu_head_pos;
761 else
762 return vc1_parse_succeeded( info, param );
763 }
764 }
765
vc1_check_next_start_code_prefix(uint8_t * buf_pos,uint8_t * buf_end)766 static inline int vc1_check_next_start_code_prefix( uint8_t *buf_pos, uint8_t *buf_end )
767 {
768 return ((buf_pos + 2) < buf_end) && !buf_pos[0] && !buf_pos[1] && (buf_pos[2] == 0x01);
769 }
770
vc1_construct_specific_parameters(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)771 int vc1_construct_specific_parameters( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
772 {
773 assert( dst && dst->data.structured && src && src->data.unstructured );
774 if( src->size < ISOM_BASEBOX_COMMON_SIZE + 7 )
775 return LSMASH_ERR_INVALID_DATA;
776 lsmash_vc1_specific_parameters_t *param = (lsmash_vc1_specific_parameters_t *)dst->data.structured;
777 uint8_t *data = src->data.unstructured;
778 uint64_t size = LSMASH_GET_BE32( data );
779 data += ISOM_BASEBOX_COMMON_SIZE;
780 if( size == 1 )
781 {
782 size = LSMASH_GET_BE64( data );
783 data += 8;
784 }
785 if( size != src->size )
786 return LSMASH_ERR_INVALID_DATA;
787 param->profile = (data[0] >> 4) & 0x0F;
788 if( param->profile != 12 )
789 return LSMASH_ERR_PATCH_WELCOME; /* We don't support profile other than 12 (Advanced profile). */
790 param->level = (data[0] >> 1) & 0x07;
791 param->cbr = (data[1] >> 4) & 0x01;
792 param->interlaced = !((data[2] >> 5) & 0x01);
793 param->multiple_sequence = !((data[2] >> 4) & 0x01);
794 param->multiple_entry = !((data[2] >> 3) & 0x01);
795 param->slice_present = !((data[2] >> 2) & 0x01);
796 param->bframe_present = !((data[2] >> 1) & 0x01);
797 param->framerate = LSMASH_GET_BE32( &data[3] );
798 /* Try to get seqhdr_ephdr[]. */
799 if( !param->seqhdr )
800 {
801 param->seqhdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
802 if( !param->seqhdr )
803 return LSMASH_ERR_MEMORY_ALLOC;
804 }
805 if( !param->ephdr )
806 {
807 param->ephdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
808 if( !param->ephdr )
809 return LSMASH_ERR_MEMORY_ALLOC;
810 }
811 lsmash_vc1_header_t *seqhdr = param->seqhdr;
812 lsmash_vc1_header_t *ephdr = param->ephdr;
813 data += 7;
814 uint8_t *pos = data;
815 uint8_t *end = src->data.unstructured + src->size;
816 /* Find the start point of Sequence header EBDU. */
817 while( pos < end )
818 {
819 if( vc1_check_next_start_code_prefix( pos, end ) && (pos + 3 < end) && *(pos + 3) == 0x0F )
820 {
821 seqhdr->ebdu_size = 4;
822 pos += 4;
823 break;
824 }
825 ++pos;
826 }
827 /* Find the end point of Sequence header EBDU. */
828 while( pos < end )
829 {
830 if( vc1_check_next_start_code_prefix( pos, end ) )
831 break;
832 ++ seqhdr->ebdu_size;
833 }
834 /* Find the start point of Entry-point header EBDU. */
835 while( pos < end )
836 {
837 if( vc1_check_next_start_code_prefix( pos, end ) && (pos + 3 < end) && *(pos + 3) == 0x0E )
838 {
839 ephdr->ebdu_size = 4;
840 pos += 4;
841 break;
842 }
843 ++pos;
844 }
845 /* Find the end point of Entry-point header EBDU. */
846 while( pos < end )
847 {
848 if( vc1_check_next_start_code_prefix( pos, end ) )
849 break;
850 ++ ephdr->ebdu_size;
851 }
852 /* Append the Sequence header EBDU and Entry-point header EBDU if present. */
853 if( seqhdr->ebdu_size )
854 {
855 lsmash_free( seqhdr->ebdu );
856 seqhdr->ebdu = lsmash_memdup( data, seqhdr->ebdu_size );
857 if( !seqhdr->ebdu )
858 return LSMASH_ERR_MEMORY_ALLOC;
859 }
860 if( ephdr->ebdu_size )
861 {
862 lsmash_free( ephdr->ebdu );
863 ephdr->ebdu = lsmash_memdup( data, ephdr->ebdu_size );
864 if( !ephdr->ebdu )
865 return LSMASH_ERR_MEMORY_ALLOC;
866 }
867 return 0;
868 }
869
vc1_copy_codec_specific(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)870 int vc1_copy_codec_specific( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
871 {
872 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
873 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
874 lsmash_vc1_specific_parameters_t *src_data = (lsmash_vc1_specific_parameters_t *)src->data.structured;
875 lsmash_vc1_specific_parameters_t *dst_data = (lsmash_vc1_specific_parameters_t *)dst->data.structured;
876 lsmash_destroy_vc1_headers( dst_data );
877 *dst_data = *src_data;
878 if( !src_data->seqhdr && !src_data->ephdr )
879 return 0;
880 if( src_data->seqhdr )
881 {
882 dst_data->seqhdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
883 if( !dst_data->seqhdr )
884 return LSMASH_ERR_MEMORY_ALLOC;
885 if( src_data->seqhdr->ebdu_size )
886 {
887 dst_data->seqhdr->ebdu = lsmash_memdup( src_data->seqhdr->ebdu, src_data->seqhdr->ebdu_size );
888 if( !dst_data->seqhdr->ebdu )
889 {
890 lsmash_destroy_vc1_headers( dst_data );
891 return LSMASH_ERR_MEMORY_ALLOC;
892 }
893 }
894 dst_data->seqhdr->ebdu_size = src_data->seqhdr->ebdu_size;
895 }
896 if( src_data->ephdr )
897 {
898 dst_data->ephdr = lsmash_malloc_zero( sizeof(lsmash_vc1_header_t) );
899 if( !dst_data->ephdr )
900 {
901 lsmash_destroy_vc1_headers( dst_data );
902 return LSMASH_ERR_MEMORY_ALLOC;
903 }
904 if( src_data->ephdr->ebdu_size )
905 {
906 dst_data->ephdr->ebdu = lsmash_memdup( src_data->ephdr->ebdu, src_data->ephdr->ebdu_size );
907 if( !dst_data->ephdr->ebdu )
908 {
909 lsmash_destroy_vc1_headers( dst_data );
910 return LSMASH_ERR_MEMORY_ALLOC;
911 }
912 }
913 dst_data->ephdr->ebdu_size = src_data->ephdr->ebdu_size;
914 }
915 return 0;
916 }
917
vc1_print_codec_specific(FILE * fp,lsmash_file_t * file,isom_box_t * box,int level)918 int vc1_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
919 {
920 assert( box->manager & LSMASH_BINARY_CODED_BOX );
921 int indent = level;
922 lsmash_ifprintf( fp, indent++, "[%s: VC1 Specific Box]\n", isom_4cc2str( box->type.fourcc ) );
923 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", box->pos );
924 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", box->size );
925 if( box->size < ISOM_BASEBOX_COMMON_SIZE + 7 )
926 return LSMASH_ERR_INVALID_DATA;
927 uint8_t *data = box->binary;
928 isom_skip_box_common( &data );
929 uint8_t profile = (data[0] >> 4) & 0x0F;
930 if( profile != 12 )
931 return 0; /* We don't support profile other than 12 (Advanced profile). */
932 lsmash_ifprintf( fp, indent, "profile = %"PRIu8"\n", profile );
933 lsmash_ifprintf( fp, indent, "level = %"PRIu8"\n", (data[0] >> 1) & 0x07 );
934 lsmash_ifprintf( fp, indent, "reserved = %"PRIu8"\n", data[0] & 0x01 );
935 lsmash_ifprintf( fp, indent, "level = %"PRIu8"\n", (data[1] >> 5) & 0x07 );
936 lsmash_ifprintf( fp, indent, "cbr = %"PRIu8"\n", (data[1] >> 4) & 0x01 );
937 lsmash_ifprintf( fp, indent, "reserved1 = 0x%02"PRIx8"\n", (data[1] & 0x0F) | ((data[2] >> 6) & 0x03) );
938 lsmash_ifprintf( fp, indent, "no_interlace = %"PRIu8"\n", (data[2] >> 5) & 0x01 );
939 lsmash_ifprintf( fp, indent, "no_multiple_seq = %"PRIu8"\n", (data[2] >> 4) & 0x01 );
940 lsmash_ifprintf( fp, indent, "no_multiple_entry = %"PRIu8"\n", (data[2] >> 3) & 0x01 );
941 lsmash_ifprintf( fp, indent, "no_slice_code = %"PRIu8"\n", (data[2] >> 2) & 0x01 );
942 lsmash_ifprintf( fp, indent, "no_bframe = %"PRIu8"\n", (data[2] >> 1) & 0x01 );
943 lsmash_ifprintf( fp, indent, "reserved2 = %"PRIu8"\n", data[2] & 0x01 );
944 uint32_t framerate = LSMASH_GET_BE32( &data[3] );
945 lsmash_ifprintf( fp, indent, "framerate = %"PRIu32"\n", framerate );
946 uint32_t seqhdr_ephdr_size = box->size - (data - box->binary + 7);
947 if( seqhdr_ephdr_size )
948 {
949 lsmash_ifprintf( fp, indent, "seqhdr_ephdr[]\n" );
950 data += 7;
951 for( uint32_t i = 0; i < seqhdr_ephdr_size; i += 8 )
952 {
953 lsmash_ifprintf( fp, indent + 1, "" );
954 for( uint32_t j = 0; ; j++ )
955 if( j == 7 || (i + j == seqhdr_ephdr_size - 1) )
956 {
957 fprintf( fp, "0x%02"PRIx8"\n", data[i + j] );
958 break;
959 }
960 else
961 fprintf( fp, "0x%02"PRIx8" ", data[i + j] );
962 }
963 }
964 return 0;
965 }
966