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( &param->seqhdr, &param->multiple_sequence, hdr_data, hdr_length );
624     else if( data[3] == 0x0E )  /* entry point header */
625         return vc1_try_to_put_header( &param->ephdr, &param->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