1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2017 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 */
30 #include "box_default.h"
36 #include "codecs/mp4a.h"
37 #include "codecs/mp4sys.h"
38 #include "codecs/description.h"
40 static int isom_bs_read_box_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
42 assert( bs
&& box
&& box
->file
);
43 /* Reset the counter so that we can use it to get position within the box. */
44 lsmash_bs_reset_counter( bs
);
45 /* Read the common fields of box. */
46 box
->pos
= lsmash_bs_get_stream_pos( bs
);
50 /* Read size and type. */
51 box
->size
= lsmash_bs_get_be32( bs
);
52 box
->type
.fourcc
= lsmash_bs_get_be32( bs
);
53 /* If size is set to 1, the actual size is repersented in the next 8 bytes.
54 * If size is set to 0, this box ends at the end of the stream. */
56 box
->size
= lsmash_bs_get_be64( bs
);
59 /* This box is the last box in the stream. */
60 box
->manager
|= LSMASH_LAST_BOX
;
62 box
->size
= bs
->written
- (lsmash_bs_get_stream_pos( bs
) - lsmash_bs_count( bs
));
64 /* We haven't known the box size yet.
65 * To get the box size, read the stream until the end of the stream. */
68 int ret
= lsmash_bs_read( bs
, 1 );
69 if( bs
->eof
|| ret
< 0 )
71 /* OK, now we know the box size. */
72 box
->size
= lsmash_bs_count( bs
) + lsmash_bs_get_remaining_buffer_size( bs
);
74 /* This box may end incompletely at the end of the stream. */
75 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
80 /* Here, we don't set up extended box type fields if this box is not a UUID Box. */
81 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
82 && box
->size
>= lsmash_bs_count( bs
) + 16 )
85 lsmash_box_type_t
*type
= &box
->type
;
86 uint64_t temp64
= lsmash_bs_get_be64( bs
);
87 type
->user
.fourcc
= (temp64
>> 32) & 0xffffffff;
88 LSMASH_SET_BE32( &type
->user
.id
[0], temp64
);
89 temp64
= lsmash_bs_get_be64( bs
);
90 LSMASH_SET_BE64( &type
->user
.id
[4], temp64
);
95 static int isom_read_fullbox_common_extension( lsmash_bs_t
*bs
, isom_box_t
*box
)
97 if( !isom_is_fullbox( box
) )
99 /* Get version and flags. */
100 box
->version
= lsmash_bs_get_byte( bs
);
101 box
->flags
= lsmash_bs_get_be24( bs
);
102 box
->manager
|= LSMASH_FULLBOX
;
106 /* Don't copy destructor since a destructor is defined as box specific. */
107 static void isom_basebox_common_copy( isom_box_t
*dst
, const isom_box_t
*src
)
109 dst
->root
= src
->root
;
110 dst
->file
= src
->file
;
111 dst
->parent
= src
->parent
;
112 dst
->manager
= src
->manager
;
114 dst
->size
= src
->size
;
115 dst
->type
= src
->type
;
118 static void isom_fullbox_common_copy( isom_box_t
*dst
, const isom_box_t
*src
)
120 dst
->root
= src
->root
;
121 dst
->file
= src
->file
;
122 dst
->parent
= src
->parent
;
123 dst
->manager
= src
->manager
;
125 dst
->size
= src
->size
;
126 dst
->type
= src
->type
;
127 dst
->version
= src
->version
;
128 dst
->flags
= src
->flags
;
131 static void isom_box_common_copy( void *dst
, const void *src
)
133 assert( LSMASH_IS_EXISTING_BOX( (isom_box_t
*)dst
)
134 && LSMASH_IS_EXISTING_BOX( (isom_box_t
*)src
) );
135 if( lsmash_check_box_type_identical( ((isom_box_t
*)src
)->type
, ISOM_BOX_TYPE_STSD
) )
137 isom_basebox_common_copy( (isom_box_t
*)dst
, (isom_box_t
*)src
);
140 if( isom_is_fullbox( src
) )
141 isom_fullbox_common_copy( (isom_box_t
*)dst
, (isom_box_t
*)src
);
143 isom_basebox_common_copy( (isom_box_t
*)dst
, (isom_box_t
*)src
);
146 static void isom_skip_box_rest( lsmash_bs_t
*bs
, isom_box_t
*box
)
148 if( box
->manager
& LSMASH_LAST_BOX
)
150 box
->size
= (box
->manager
& LSMASH_FULLBOX
) ? ISOM_FULLBOX_COMMON_SIZE
: ISOM_BASEBOX_COMMON_SIZE
;
151 uint64_t start
= lsmash_bs_get_stream_pos( bs
);
152 if( !bs
->unseekable
)
153 lsmash_bs_read_seek( bs
, 0, SEEK_END
);
156 lsmash_bs_skip_bytes( bs
, UINT32_MAX
);
157 uint64_t end
= lsmash_bs_get_stream_pos( bs
);
158 box
->size
+= end
- start
;
161 uint64_t skip_bytes
= box
->size
- lsmash_bs_count( bs
);
162 if( !bs
->unseekable
)
164 /* The stream is seekable. So, skip by seeking the stream. */
165 uint64_t start
= lsmash_bs_get_stream_pos( bs
);
166 lsmash_bs_read_seek( bs
, skip_bytes
, SEEK_CUR
);
167 uint64_t end
= lsmash_bs_get_stream_pos( bs
);
168 if( end
- start
!= skip_bytes
)
170 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
173 /* The stream is unseekable. So, skip by reading the stream. */
174 lsmash_bs_skip_bytes_64( bs
, skip_bytes
);
175 if( box
->size
> lsmash_bs_count( bs
) )
176 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
179 static void isom_validate_box_size( lsmash_bs_t
*bs
, isom_box_t
*box
)
181 uint64_t pos
= lsmash_bs_count( bs
);
182 if( box
->manager
& LSMASH_LAST_BOX
)
187 if( box
->size
< pos
)
189 fprintf( stderr
, "[%s] box has less bytes than expected: %"PRId64
"\n", isom_4cc2str( box
->type
.fourcc
), pos
- box
->size
);
192 else if( box
->size
> pos
)
194 /* The box probably has extra padding bytes at the end. */
195 fprintf( stderr
, "[%s] box has more bytes than expected: %"PRId64
"\n", isom_4cc2str( box
->type
.fourcc
), box
->size
- pos
);
196 isom_skip_box_rest( bs
, box
);
200 static int isom_read_children( lsmash_file_t
*file
, isom_box_t
*box
, void *parent
, int level
)
203 lsmash_bs_t
*bs
= file
->bs
;
204 isom_box_t
*parent_box
= (isom_box_t
*)parent
;
205 uint64_t parent_pos
= lsmash_bs_count( bs
);
206 while( !(ret
= isom_read_box( file
, box
, parent_box
, parent_pos
, level
)) )
208 parent_pos
+= box
->size
;
209 if( parent_box
->size
<= parent_pos
|| bs
->eob
|| bs
->error
)
212 box
->size
= parent_pos
; /* for file size */
216 static int isom_read_leaf_box_common_last_process( lsmash_file_t
*file
, isom_box_t
*box
, int level
, void *instance
)
218 isom_validate_box_size( file
->bs
, box
);
219 isom_box_common_copy( instance
, box
);
220 return isom_add_print_func( file
, instance
, level
);
223 static int isom_read_unknown_box( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
225 lsmash_bs_t
*bs
= file
->bs
;
226 uint64_t read_size
= box
->size
- lsmash_bs_count( bs
);
227 if( box
->manager
& LSMASH_INCOMPLETE_BOX
)
228 return LSMASH_ERR_INVALID_DATA
;
229 isom_unknown_box_t
*unknown
= ALLOCATE_BOX( unknown
);
230 if( LSMASH_IS_NON_EXISTING_BOX( unknown
) )
231 return LSMASH_ERR_MEMORY_ALLOC
;
232 if( lsmash_list_add_entry( &parent
->extensions
, unknown
) < 0 )
234 isom_remove_box_by_itself( unknown
);
235 return LSMASH_ERR_MEMORY_ALLOC
;
237 isom_box_common_copy( unknown
, box
);
238 unknown
->manager
|= LSMASH_UNKNOWN_BOX
;
239 unknown
->destruct
= (isom_extension_destructor_t
)isom_remove_unknown_box
;
240 isom_set_box_writer( (isom_box_t
*)unknown
);
243 unknown
->unknown_field
= lsmash_bs_get_bytes( bs
, read_size
);
244 if( unknown
->unknown_field
)
245 unknown
->unknown_size
= read_size
;
247 unknown
->manager
|= LSMASH_INCOMPLETE_BOX
;
249 if( !(file
->flags
& LSMASH_FILE_MODE_DUMP
) )
251 /* Create a dummy for dump. */
252 isom_dummy_t
*dummy
= ALLOCATE_BOX( dummy
);
253 if( LSMASH_IS_NON_EXISTING_BOX( dummy
) )
254 return LSMASH_ERR_MEMORY_ALLOC
;
255 box
->manager
|= LSMASH_ABSENT_IN_FILE
| LSMASH_UNKNOWN_BOX
;
256 isom_box_common_copy( dummy
, box
);
257 int ret
= isom_add_print_func( file
, dummy
, level
);
260 isom_remove_box_by_itself( dummy
);
266 #define ADD_BOX( box_name, parent_type ) \
267 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
268 if( LSMASH_IS_NON_EXISTING_BOX( box_name ) ) \
269 return LSMASH_ERR_NAMELESS
271 static int isom_read_ftyp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
273 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
274 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->ftyp
) )
275 return isom_read_unknown_box( file
, box
, parent
, level
);
276 ADD_BOX( ftyp
, lsmash_file_t
);
277 lsmash_bs_t
*bs
= file
->bs
;
278 ftyp
->major_brand
= lsmash_bs_get_be32( bs
);
279 ftyp
->minor_version
= lsmash_bs_get_be32( bs
);
280 uint64_t pos
= lsmash_bs_count( bs
);
281 ftyp
->brand_count
= box
->size
> pos
? (box
->size
- pos
) / sizeof(uint32_t) : 0;
282 size_t alloc_size
= ftyp
->brand_count
* sizeof(uint32_t);
283 ftyp
->compatible_brands
= ftyp
->brand_count
? lsmash_malloc( alloc_size
) : NULL
;
284 if( ftyp
->brand_count
&& !ftyp
->compatible_brands
)
285 return LSMASH_ERR_MEMORY_ALLOC
;
286 for( uint32_t i
= 0; i
< ftyp
->brand_count
; i
++ )
287 ftyp
->compatible_brands
[i
] = lsmash_bs_get_be32( bs
);
288 if( !file
->compatible_brands
&& ftyp
->compatible_brands
)
290 file
->compatible_brands
= lsmash_memdup( ftyp
->compatible_brands
, alloc_size
);
291 if( !file
->compatible_brands
)
292 return LSMASH_ERR_MEMORY_ALLOC
;
293 file
->brand_count
= ftyp
->brand_count
;
295 return isom_read_leaf_box_common_last_process( file
, box
, level
, ftyp
);
298 static int isom_read_styp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
300 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
301 return isom_read_unknown_box( file
, box
, parent
, level
);
302 ADD_BOX( styp
, lsmash_file_t
);
303 lsmash_bs_t
*bs
= file
->bs
;
304 styp
->major_brand
= lsmash_bs_get_be32( bs
);
305 styp
->minor_version
= lsmash_bs_get_be32( bs
);
306 uint64_t pos
= lsmash_bs_count( bs
);
307 styp
->brand_count
= box
->size
> pos
? (box
->size
- pos
) / sizeof(uint32_t) : 0;
308 size_t alloc_size
= styp
->brand_count
* sizeof(uint32_t);
309 styp
->compatible_brands
= styp
->brand_count
? lsmash_malloc( alloc_size
) : NULL
;
310 if( styp
->brand_count
&& !styp
->compatible_brands
)
311 return LSMASH_ERR_MEMORY_ALLOC
;
312 for( uint32_t i
= 0; i
< styp
->brand_count
; i
++ )
313 styp
->compatible_brands
[i
] = lsmash_bs_get_be32( bs
);
314 if( !file
->compatible_brands
&& styp
->compatible_brands
)
316 file
->compatible_brands
= lsmash_memdup( styp
->compatible_brands
, alloc_size
);
317 if( !file
->compatible_brands
)
318 return LSMASH_ERR_MEMORY_ALLOC
;
319 file
->brand_count
= styp
->brand_count
;
321 file
->flags
|= LSMASH_FILE_MODE_SEGMENT
;
322 return isom_read_leaf_box_common_last_process( file
, box
, level
, styp
);
325 static int isom_read_sidx( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
327 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
328 return isom_read_unknown_box( file
, box
, parent
, level
);
329 ADD_BOX( sidx
, lsmash_file_t
);
330 lsmash_bs_t
*bs
= file
->bs
;
331 sidx
->reference_ID
= lsmash_bs_get_be32( bs
);
332 sidx
->timescale
= lsmash_bs_get_be32( bs
);
333 if( box
->version
== 0 )
335 sidx
->earliest_presentation_time
= lsmash_bs_get_be32( bs
);
336 sidx
->first_offset
= lsmash_bs_get_be32( bs
);
340 sidx
->earliest_presentation_time
= lsmash_bs_get_be64( bs
);
341 sidx
->first_offset
= lsmash_bs_get_be64( bs
);
343 sidx
->reserved
= lsmash_bs_get_be16( bs
);
344 sidx
->reference_count
= lsmash_bs_get_be16( bs
);
345 for( uint64_t pos
= lsmash_bs_count( bs
);
346 pos
< box
->size
&& sidx
->list
->entry_count
< sidx
->reference_count
;
347 pos
= lsmash_bs_count( bs
) )
349 isom_sidx_referenced_item_t
*data
= lsmash_malloc( sizeof(isom_sidx_referenced_item_t
) );
351 return LSMASH_ERR_MEMORY_ALLOC
;
352 if( lsmash_list_add_entry( sidx
->list
, data
) < 0 )
355 return LSMASH_ERR_MEMORY_ALLOC
;
358 temp32
= lsmash_bs_get_be32( bs
);
359 data
->reference_type
= (temp32
>> 31) & 0x00000001;
360 data
->reference_size
= temp32
& 0x7FFFFFFF;
361 data
->subsegment_duration
= lsmash_bs_get_be32( bs
);
362 temp32
= lsmash_bs_get_be32( bs
);
363 data
->starts_with_SAP
= (temp32
>> 31) & 0x00000001;
364 data
->SAP_type
= (temp32
>> 28) & 0x00000007;
365 data
->SAP_delta_time
= temp32
& 0x0FFFFFFF;
367 file
->flags
|= LSMASH_FILE_MODE_INDEX
;
368 return isom_read_leaf_box_common_last_process( file
, box
, level
, sidx
);
371 static int isom_read_moov( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
373 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
374 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->moov
) )
375 return isom_read_unknown_box( file
, box
, parent
, level
);
376 ADD_BOX( moov
, lsmash_file_t
);
377 file
->flags
|= LSMASH_FILE_MODE_INITIALIZATION
;
378 file
->initializer
= file
;
379 isom_box_common_copy( moov
, box
);
380 int ret
= isom_add_print_func( file
, moov
, level
);
383 return isom_read_children( file
, box
, moov
, level
);
386 static int isom_read_mvhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
388 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
389 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->mvhd
) )
390 return isom_read_unknown_box( file
, box
, parent
, level
);
391 ADD_BOX( mvhd
, isom_moov_t
);
392 lsmash_bs_t
*bs
= file
->bs
;
395 mvhd
->creation_time
= lsmash_bs_get_be64( bs
);
396 mvhd
->modification_time
= lsmash_bs_get_be64( bs
);
397 mvhd
->timescale
= lsmash_bs_get_be32( bs
);
398 mvhd
->duration
= lsmash_bs_get_be64( bs
);
402 mvhd
->creation_time
= lsmash_bs_get_be32( bs
);
403 mvhd
->modification_time
= lsmash_bs_get_be32( bs
);
404 mvhd
->timescale
= lsmash_bs_get_be32( bs
);
405 mvhd
->duration
= lsmash_bs_get_be32( bs
);
407 mvhd
->rate
= lsmash_bs_get_be32( bs
);
408 mvhd
->volume
= lsmash_bs_get_be16( bs
);
409 mvhd
->reserved
= lsmash_bs_get_be16( bs
);
410 mvhd
->preferredLong
[0] = lsmash_bs_get_be32( bs
);
411 mvhd
->preferredLong
[1] = lsmash_bs_get_be32( bs
);
412 for( int i
= 0; i
< 9; i
++ )
413 mvhd
->matrix
[i
] = lsmash_bs_get_be32( bs
);
414 mvhd
->previewTime
= lsmash_bs_get_be32( bs
);
415 mvhd
->previewDuration
= lsmash_bs_get_be32( bs
);
416 mvhd
->posterTime
= lsmash_bs_get_be32( bs
);
417 mvhd
->selectionTime
= lsmash_bs_get_be32( bs
);
418 mvhd
->selectionDuration
= lsmash_bs_get_be32( bs
);
419 mvhd
->currentTime
= lsmash_bs_get_be32( bs
);
420 mvhd
->next_track_ID
= lsmash_bs_get_be32( bs
);
421 return isom_read_leaf_box_common_last_process( file
, box
, level
, mvhd
);
424 static int isom_read_iods( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
426 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
427 return isom_read_unknown_box( file
, box
, parent
, level
);
428 ADD_BOX( iods
, isom_moov_t
);
429 lsmash_bs_t
*bs
= file
->bs
;
430 iods
->OD
= mp4sys_get_descriptor( bs
, NULL
);
432 return LSMASH_ERR_INVALID_DATA
;
433 return isom_read_leaf_box_common_last_process( file
, box
, level
, iods
);
436 static int isom_read_qt_color_table( lsmash_bs_t
*bs
, isom_qt_color_table_t
*color_table
)
438 color_table
->seed
= lsmash_bs_get_be32( bs
);
439 color_table
->flags
= lsmash_bs_get_be16( bs
);
440 color_table
->size
= lsmash_bs_get_be16( bs
);
442 return LSMASH_ERR_INVALID_DATA
;
443 isom_qt_color_array_t
*array
= lsmash_malloc_zero( (color_table
->size
+ 1) * sizeof(isom_qt_color_array_t
) );
445 return LSMASH_ERR_MEMORY_ALLOC
;
446 color_table
->array
= array
;
447 for( uint16_t i
= 0; i
<= color_table
->size
; i
++ )
449 uint64_t color
= lsmash_bs_get_be64( bs
);
450 array
[i
].value
= (color
>> 48) & 0xffff;
451 array
[i
].r
= (color
>> 32) & 0xffff;
452 array
[i
].g
= (color
>> 16) & 0xffff;
453 array
[i
].b
= color
& 0xffff;
458 static int isom_read_ctab( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
460 ADD_BOX( ctab
, isom_moov_t
);
461 lsmash_bs_t
*bs
= file
->bs
;
462 int ret
= isom_read_qt_color_table( bs
, &ctab
->color_table
);
465 return isom_read_leaf_box_common_last_process( file
, box
, level
, ctab
);
468 static int isom_read_trak( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
470 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
471 return isom_read_unknown_box( file
, box
, parent
, level
);
472 ADD_BOX( trak
, isom_moov_t
);
473 box
->parent
= parent
;
474 box
->root
= file
->root
;
476 isom_box_common_copy( trak
, box
);
477 int ret
= isom_add_print_func( file
, trak
, level
);
480 return isom_read_children( file
, box
, trak
, level
);
483 static int isom_read_tkhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
485 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
486 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->tkhd
) )
487 return isom_read_unknown_box( file
, box
, parent
, level
);
488 ADD_BOX( tkhd
, isom_trak_t
);
489 lsmash_bs_t
*bs
= file
->bs
;
492 tkhd
->creation_time
= lsmash_bs_get_be64( bs
);
493 tkhd
->modification_time
= lsmash_bs_get_be64( bs
);
494 tkhd
->track_ID
= lsmash_bs_get_be32( bs
);
495 tkhd
->reserved1
= lsmash_bs_get_be32( bs
);
496 tkhd
->duration
= lsmash_bs_get_be64( bs
);
500 tkhd
->creation_time
= lsmash_bs_get_be32( bs
);
501 tkhd
->modification_time
= lsmash_bs_get_be32( bs
);
502 tkhd
->track_ID
= lsmash_bs_get_be32( bs
);
503 tkhd
->reserved1
= lsmash_bs_get_be32( bs
);
504 tkhd
->duration
= lsmash_bs_get_be32( bs
);
506 tkhd
->reserved2
[0] = lsmash_bs_get_be32( bs
);
507 tkhd
->reserved2
[1] = lsmash_bs_get_be32( bs
);
508 tkhd
->layer
= lsmash_bs_get_be16( bs
);
509 tkhd
->alternate_group
= lsmash_bs_get_be16( bs
);
510 tkhd
->volume
= lsmash_bs_get_be16( bs
);
511 tkhd
->reserved3
= lsmash_bs_get_be16( bs
);
512 for( int i
= 0; i
< 9; i
++ )
513 tkhd
->matrix
[i
] = lsmash_bs_get_be32( bs
);
514 tkhd
->width
= lsmash_bs_get_be32( bs
);
515 tkhd
->height
= lsmash_bs_get_be32( bs
);
516 return isom_read_leaf_box_common_last_process( file
, box
, level
, tkhd
);
519 static int isom_read_tapt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
521 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
522 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->tapt
) )
523 return isom_read_unknown_box( file
, box
, parent
, level
);
524 ADD_BOX( tapt
, isom_trak_t
);
525 isom_box_common_copy( tapt
, box
);
526 int ret
= isom_add_print_func( file
, tapt
, level
);
529 return isom_read_children( file
, box
, tapt
, level
);
532 static int isom_read_clef( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
534 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_TAPT
)
535 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t
*)parent
)->clef
) )
536 return isom_read_unknown_box( file
, box
, parent
, level
);
537 ADD_BOX( clef
, isom_tapt_t
);
538 lsmash_bs_t
*bs
= file
->bs
;
539 clef
->width
= lsmash_bs_get_be32( bs
);
540 clef
->height
= lsmash_bs_get_be32( bs
);
541 return isom_read_leaf_box_common_last_process( file
, box
, level
, clef
);
544 static int isom_read_prof( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
546 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_TAPT
)
547 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t
*)parent
)->prof
) )
548 return isom_read_unknown_box( file
, box
, parent
, level
);
549 ADD_BOX( prof
, isom_tapt_t
);
550 lsmash_bs_t
*bs
= file
->bs
;
551 prof
->width
= lsmash_bs_get_be32( bs
);
552 prof
->height
= lsmash_bs_get_be32( bs
);
553 return isom_read_leaf_box_common_last_process( file
, box
, level
, prof
);
556 static int isom_read_enof( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
558 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_TAPT
)
559 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t
*)parent
)->enof
) )
560 return isom_read_unknown_box( file
, box
, parent
, level
);
561 ADD_BOX( enof
, isom_tapt_t
);
562 lsmash_bs_t
*bs
= file
->bs
;
563 enof
->width
= lsmash_bs_get_be32( bs
);
564 enof
->height
= lsmash_bs_get_be32( bs
);
565 return isom_read_leaf_box_common_last_process( file
, box
, level
, enof
);
568 static int isom_read_edts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
570 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
571 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->edts
) )
572 return isom_read_unknown_box( file
, box
, parent
, level
);
573 ADD_BOX( edts
, isom_trak_t
);
574 isom_box_common_copy( edts
, box
);
575 if( isom_add_print_func( file
, edts
, level
) < 0 )
577 return isom_read_children( file
, box
, edts
, level
);
580 static int isom_read_elst( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
582 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_EDTS
)
583 || LSMASH_IS_EXISTING_BOX( ((isom_edts_t
*)parent
)->elst
) )
584 return isom_read_unknown_box( file
, box
, parent
, level
);
585 ADD_BOX( elst
, isom_edts_t
);
586 lsmash_bs_t
*bs
= file
->bs
;
587 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
588 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& elst
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
590 isom_elst_entry_t
*data
= lsmash_malloc( sizeof(isom_elst_entry_t
) );
592 return LSMASH_ERR_MEMORY_ALLOC
;
593 if( lsmash_list_add_entry( elst
->list
, data
) < 0 )
596 return LSMASH_ERR_MEMORY_ALLOC
;
598 if( box
->version
== 1 )
600 data
->segment_duration
= lsmash_bs_get_be64( bs
);
601 data
->media_time
= (int64_t)lsmash_bs_get_be64( bs
);
605 data
->segment_duration
= lsmash_bs_get_be32( bs
);
606 data
->media_time
= (int32_t)lsmash_bs_get_be32( bs
);
608 data
->media_rate
= lsmash_bs_get_be32( bs
);
610 return isom_read_leaf_box_common_last_process( file
, box
, level
, elst
);
613 static int isom_read_tref( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
615 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
616 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->tref
) )
617 return isom_read_unknown_box( file
, box
, parent
, level
);
618 ADD_BOX( tref
, isom_trak_t
);
619 isom_box_common_copy( tref
, box
);
620 int ret
= isom_add_print_func( file
, tref
, level
);
623 return isom_read_children( file
, box
, tref
, level
);
626 static int isom_read_track_reference_type( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
628 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
629 return isom_read_unknown_box( file
, box
, parent
, level
);
630 isom_tref_type_t
*ref
= isom_add_track_reference_type( (isom_tref_t
*)parent
, box
->type
.fourcc
);
632 return LSMASH_ERR_NAMELESS
;
633 lsmash_bs_t
*bs
= file
->bs
;
634 ref
->ref_count
= (box
->size
- lsmash_bs_count( bs
) ) / sizeof(uint32_t);
637 ref
->track_ID
= lsmash_malloc( ref
->ref_count
* sizeof(uint32_t) );
641 return LSMASH_ERR_MEMORY_ALLOC
;
643 for( uint32_t i
= 0; i
< ref
->ref_count
; i
++ )
644 ref
->track_ID
[i
] = lsmash_bs_get_be32( bs
);
646 return isom_read_leaf_box_common_last_process( file
, box
, level
, ref
);
649 static int isom_read_mdia( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
651 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
652 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->mdia
) )
653 return isom_read_unknown_box( file
, box
, parent
, level
);
654 ADD_BOX( mdia
, isom_trak_t
);
655 isom_box_common_copy( mdia
, box
);
656 int ret
= isom_add_print_func( file
, mdia
, level
);
659 return isom_read_children( file
, box
, mdia
, level
);
662 static int isom_read_mdhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
664 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
)
665 || LSMASH_IS_EXISTING_BOX( ((isom_mdia_t
*)parent
)->mdhd
) )
666 return isom_read_unknown_box( file
, box
, parent
, level
);
667 ADD_BOX( mdhd
, isom_mdia_t
);
668 lsmash_bs_t
*bs
= file
->bs
;
671 mdhd
->creation_time
= lsmash_bs_get_be64( bs
);
672 mdhd
->modification_time
= lsmash_bs_get_be64( bs
);
673 mdhd
->timescale
= lsmash_bs_get_be32( bs
);
674 mdhd
->duration
= lsmash_bs_get_be64( bs
);
678 mdhd
->creation_time
= lsmash_bs_get_be32( bs
);
679 mdhd
->modification_time
= lsmash_bs_get_be32( bs
);
680 mdhd
->timescale
= lsmash_bs_get_be32( bs
);
681 mdhd
->duration
= lsmash_bs_get_be32( bs
);
683 mdhd
->language
= lsmash_bs_get_be16( bs
);
684 mdhd
->quality
= lsmash_bs_get_be16( bs
);
685 return isom_read_leaf_box_common_last_process( file
, box
, level
, mdhd
);
688 static int isom_read_hdlr( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
690 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
)
691 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
692 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
)
693 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
))
694 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
) && LSMASH_IS_EXISTING_BOX( ((isom_mdia_t
*)parent
)->hdlr
))
695 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->hdlr
))
696 || (lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->hdlr
))
697 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) && LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->hdlr
)) )
698 return isom_read_unknown_box( file
, box
, parent
, level
);
699 ADD_BOX( hdlr
, void );
700 lsmash_bs_t
*bs
= file
->bs
;
701 hdlr
->componentType
= lsmash_bs_get_be32( bs
);
702 hdlr
->componentSubtype
= lsmash_bs_get_be32( bs
);
703 hdlr
->componentManufacturer
= lsmash_bs_get_be32( bs
);
704 hdlr
->componentFlags
= lsmash_bs_get_be32( bs
);
705 hdlr
->componentFlagsMask
= lsmash_bs_get_be32( bs
);
706 uint64_t pos
= lsmash_bs_count( bs
);
707 hdlr
->componentName_length
= box
->size
- pos
;
708 if( hdlr
->componentName_length
)
710 hdlr
->componentName
= lsmash_malloc( hdlr
->componentName_length
);
711 if( !hdlr
->componentName
)
712 return LSMASH_ERR_MEMORY_ALLOC
;
713 for( uint32_t i
= 0; pos
< box
->size
; pos
= lsmash_bs_count( bs
) )
714 hdlr
->componentName
[i
++] = lsmash_bs_get_byte( bs
);
716 return isom_read_leaf_box_common_last_process( file
, box
, level
, hdlr
);
719 static int isom_read_minf( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
721 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
)
722 || LSMASH_IS_EXISTING_BOX( ((isom_mdia_t
*)parent
)->minf
) )
723 return isom_read_unknown_box( file
, box
, parent
, level
);
724 ADD_BOX( minf
, isom_mdia_t
);
725 isom_box_common_copy( minf
, box
);
726 int ret
= isom_add_print_func( file
, minf
, level
);
729 return isom_read_children( file
, box
, minf
, level
);
732 static int isom_read_vmhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
734 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
735 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->vmhd
) )
736 return isom_read_unknown_box( file
, box
, parent
, level
);
737 ADD_BOX( vmhd
, isom_minf_t
);
738 lsmash_bs_t
*bs
= file
->bs
;
739 vmhd
->graphicsmode
= lsmash_bs_get_be16( bs
);
740 for( int i
= 0; i
< 3; i
++ )
741 vmhd
->opcolor
[i
] = lsmash_bs_get_be16( bs
);
742 return isom_read_leaf_box_common_last_process( file
, box
, level
, vmhd
);
745 static int isom_read_smhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
747 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
748 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->smhd
) )
749 return isom_read_unknown_box( file
, box
, parent
, level
);
750 ADD_BOX( smhd
, isom_minf_t
);
751 lsmash_bs_t
*bs
= file
->bs
;
752 smhd
->balance
= lsmash_bs_get_be16( bs
);
753 smhd
->reserved
= lsmash_bs_get_be16( bs
);
754 return isom_read_leaf_box_common_last_process( file
, box
, level
, smhd
);
757 static int isom_read_hmhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
759 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
760 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->hmhd
) )
761 return isom_read_unknown_box( file
, box
, parent
, level
);
762 ADD_BOX( hmhd
, isom_minf_t
);
763 lsmash_bs_t
*bs
= file
->bs
;
764 hmhd
->maxPDUsize
= lsmash_bs_get_be16( bs
);
765 hmhd
->avgPDUsize
= lsmash_bs_get_be16( bs
);
766 hmhd
->maxbitrate
= lsmash_bs_get_be32( bs
);
767 hmhd
->avgbitrate
= lsmash_bs_get_be32( bs
);
768 hmhd
->reserved
= lsmash_bs_get_be32( bs
);
769 return isom_read_leaf_box_common_last_process( file
, box
, level
, hmhd
);
772 static int isom_read_nmhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
774 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
775 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->nmhd
) )
776 return isom_read_unknown_box( file
, box
, parent
, level
);
777 ADD_BOX( nmhd
, isom_minf_t
);
778 return isom_read_leaf_box_common_last_process( file
, box
, level
, nmhd
);
781 static int isom_read_gmhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
783 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
784 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->gmhd
) )
785 return isom_read_unknown_box( file
, box
, parent
, level
);
786 ADD_BOX( gmhd
, isom_minf_t
);
787 isom_box_common_copy( gmhd
, box
);
788 int ret
= isom_add_print_func( file
, gmhd
, level
);
791 return isom_read_children( file
, box
, gmhd
, level
);
794 static int isom_read_gmin( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
796 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_GMHD
)
797 || LSMASH_IS_EXISTING_BOX( ((isom_gmhd_t
*)parent
)->gmin
) )
798 return isom_read_unknown_box( file
, box
, parent
, level
);
799 ADD_BOX( gmin
, isom_gmhd_t
);
800 lsmash_bs_t
*bs
= file
->bs
;
801 gmin
->graphicsmode
= lsmash_bs_get_be16( bs
);
802 for( int i
= 0; i
< 3; i
++ )
803 gmin
->opcolor
[i
] = lsmash_bs_get_be16( bs
);
804 gmin
->balance
= lsmash_bs_get_be16( bs
);
805 gmin
->reserved
= lsmash_bs_get_be16( bs
);
806 return isom_read_leaf_box_common_last_process( file
, box
, level
, gmin
);
809 static int isom_read_text( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
811 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_GMHD
)
812 || LSMASH_IS_EXISTING_BOX( ((isom_gmhd_t
*)parent
)->text
) )
813 return isom_read_unknown_box( file
, box
, parent
, level
);
814 ADD_BOX( text
, isom_gmhd_t
);
815 lsmash_bs_t
*bs
= file
->bs
;
816 for( int i
= 0; i
< 9; i
++ )
817 text
->matrix
[i
] = lsmash_bs_get_be32( bs
);
818 return isom_read_leaf_box_common_last_process( file
, box
, level
, text
);
821 static int isom_read_dinf( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
823 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
824 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
825 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
))
826 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) && LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->dinf
))
827 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->dinf
))
828 || (lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->dinf
)) )
829 return isom_read_unknown_box( file
, box
, parent
, level
);
830 ADD_BOX( dinf
, void );
831 isom_box_common_copy( dinf
, box
);
832 int ret
= isom_add_print_func( file
, dinf
, level
);
835 return isom_read_children( file
, box
, dinf
, level
);
838 static int isom_read_dref( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
840 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_DINF
)
841 || LSMASH_IS_EXISTING_BOX( ((isom_dinf_t
*)parent
)->dref
) )
842 return isom_read_unknown_box( file
, box
, parent
, level
);
843 ADD_BOX( dref
, isom_dinf_t
);
844 lsmash_bs_t
*bs
= file
->bs
;
845 dref
->list
.entry_count
= lsmash_bs_get_be32( bs
);
846 isom_box_common_copy( dref
, box
);
847 int ret
= isom_add_print_func( file
, dref
, level
);
850 return isom_read_children( file
, box
, dref
, level
);
853 static int isom_read_dref_entry( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
855 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_DREF
) )
856 return isom_read_unknown_box( file
, box
, parent
, level
);
857 isom_dref_t
*dref
= (isom_dref_t
*)parent
;
858 if( !dref
->list
.head
)
859 dref
->list
.entry_count
= 0; /* discard entry_count gotten from the file */
860 isom_dref_entry_t
*ref
= isom_add_dref_entry( dref
, box
->type
);
862 return LSMASH_ERR_NAMELESS
;
863 lsmash_bs_t
*bs
= file
->bs
;
864 if( lsmash_check_box_type_identical( ref
->type
, ISOM_BOX_TYPE_URL
) )
866 uint64_t pos
= lsmash_bs_count( bs
);
867 ref
->location_length
= box
->size
- pos
;
868 if( ref
->location_length
)
870 ref
->location
= lsmash_malloc( ref
->location_length
);
872 return LSMASH_ERR_MEMORY_ALLOC
;
873 for( uint32_t i
= 0; pos
< box
->size
; pos
= lsmash_bs_count( bs
) )
874 ref
->location
[i
++] = lsmash_bs_get_byte( bs
);
877 if( box
->flags
& 0x000001 )
878 ref
->ref_file
= ref
->file
;
879 box
->parent
= parent
;
880 return isom_read_leaf_box_common_last_process( file
, box
, level
, ref
);
883 static int isom_read_stbl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
885 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
)
886 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t
*)parent
)->stbl
) )
887 return isom_read_unknown_box( file
, box
, parent
, level
);
888 ADD_BOX( stbl
, isom_minf_t
);
889 isom_box_common_copy( stbl
, box
);
890 int ret
= isom_add_print_func( file
, stbl
, level
);
893 return isom_read_children( file
, box
, stbl
, level
);
896 static int isom_read_stsd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
898 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
899 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stsd
) )
900 return isom_read_unknown_box( file
, box
, parent
, level
);
901 ADD_BOX( stsd
, isom_stbl_t
);
902 lsmash_bs_t
*bs
= file
->bs
;
903 stsd
->entry_count
= lsmash_bs_get_be32( bs
);
904 isom_box_common_copy( stsd
, box
);
905 int ret
= isom_add_print_func( file
, stsd
, level
);
908 uint64_t stsd_pos
= lsmash_bs_count( bs
);
909 for( uint32_t i
= 0; i
< stsd
->entry_count
|| (stsd_pos
+ ISOM_BASEBOX_COMMON_SIZE
) <= stsd
->size
; i
++ )
911 if( (ret
= isom_read_box( file
, box
, (isom_box_t
*)stsd
, stsd_pos
, level
)) != 0 )
913 stsd_pos
+= box
->size
;
914 if( stsd
->size
<= stsd_pos
|| bs
->eob
|| bs
->error
)
917 if( stsd
->size
< stsd_pos
)
919 fprintf( stderr
, "[stsd] box has extra bytes: %"PRId64
"\n", stsd_pos
- stsd
->size
);
920 stsd
->size
= stsd_pos
;
922 box
->size
= stsd
->size
;
926 static int isom_read_codec_specific( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
928 lsmash_bs_t
*bs
= file
->bs
;
929 uint64_t opaque_pos
= lsmash_bs_count( bs
);
930 uint64_t exdata_length
= box
->size
- opaque_pos
;
931 if( exdata_length
> UINT32_MAX
)
932 return LSMASH_ERR_MEMORY_ALLOC
;
933 uint8_t *exdata
= lsmash_malloc( box
->size
);
935 return LSMASH_ERR_MEMORY_ALLOC
;
936 int ret
= lsmash_bs_get_bytes_ex( bs
, exdata_length
, exdata
+ (uintptr_t)opaque_pos
);
939 LSMASH_SET_BE32( &exdata
[0], box
->size
);
940 LSMASH_SET_BE32( &exdata
[4], box
->type
.fourcc
);
942 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
944 LSMASH_SET_BE32( &exdata
[8], box
->type
.user
.fourcc
);
945 memcpy( &exdata
[12], box
->type
.user
.id
, 12 );
948 if( box
->manager
& LSMASH_FULLBOX
)
950 LSMASH_SET_BYTE( &exdata
[i
], box
->version
);
952 LSMASH_SET_BE24( &exdata
[i
], box
->flags
);
955 if( i
!= opaque_pos
)
957 ret
= LSMASH_ERR_INVALID_DATA
;
960 if( (ret
= isom_add_extension_binary( parent
, box
->type
, LSMASH_BOX_PRECEDENCE_N
, exdata
, box
->size
)) < 0 )
962 isom_box_t
*ext
= (isom_box_t
*)parent
->extensions
.tail
->data
;
963 box
->manager
|= ext
->manager
;
964 isom_validate_box_size( file
->bs
, box
);
965 isom_basebox_common_copy( ext
, box
);
966 return isom_add_print_func( file
, ext
, level
);
968 lsmash_free( exdata
);
972 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type
, isom_stsd_t
*stsd
)
974 assert( isom_check_media_hdlr_from_stsd( stsd
) );
975 void *sample_desc
= NULL
;
976 lsmash_media_type media_type
= ((isom_mdia_t
*)stsd
->parent
->parent
->parent
)->hdlr
->componentSubtype
;
977 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
978 sample_desc
= ALLOCATE_BOX( visual_entry
);
979 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
980 sample_desc
= ALLOCATE_BOX( audio_entry
);
981 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
983 if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
984 sample_desc
= ALLOCATE_BOX( tx3g_entry
);
985 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TEXT_TEXT
) )
986 sample_desc
= ALLOCATE_BOX( qt_text_entry
);
988 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
) )
989 sample_desc
= ALLOCATE_BOX( mp4s_entry
);
992 ((isom_box_t
*)sample_desc
)->offset_in_parent
= offsetof( isom_stsd_t
, list
);
993 ((isom_box_t
*)sample_desc
)->destruct
= (isom_extension_destructor_t
)isom_remove_sample_description
;
997 static void *isom_add_description( lsmash_codec_type_t sample_type
, isom_stsd_t
*stsd
)
999 void *sample_desc
= isom_sample_description_alloc( sample_type
, stsd
);
1002 if( lsmash_list_add_entry( &stsd
->list
, sample_desc
) < 0 )
1004 lsmash_free( sample_desc
);
1007 if( lsmash_list_add_entry( &stsd
->extensions
, sample_desc
) < 0 )
1009 lsmash_list_remove_entry_tail( &stsd
->list
);
1015 static int isom_read_visual_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1017 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1018 return isom_read_unknown_box( file
, box
, parent
, level
);
1019 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1020 if( LSMASH_IS_NON_EXISTING_BOX( visual
) )
1021 return LSMASH_ERR_MEMORY_ALLOC
;
1022 lsmash_bs_t
*bs
= file
->bs
;
1023 for( int i
= 0; i
< 6; i
++ )
1024 visual
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1025 visual
->data_reference_index
= lsmash_bs_get_be16( bs
);
1026 visual
->version
= lsmash_bs_get_be16( bs
);
1027 visual
->revision_level
= lsmash_bs_get_be16( bs
);
1028 visual
->vendor
= lsmash_bs_get_be32( bs
);
1029 visual
->temporalQuality
= lsmash_bs_get_be32( bs
);
1030 visual
->spatialQuality
= lsmash_bs_get_be32( bs
);
1031 visual
->width
= lsmash_bs_get_be16( bs
);
1032 visual
->height
= lsmash_bs_get_be16( bs
);
1033 visual
->horizresolution
= lsmash_bs_get_be32( bs
);
1034 visual
->vertresolution
= lsmash_bs_get_be32( bs
);
1035 visual
->dataSize
= lsmash_bs_get_be32( bs
);
1036 visual
->frame_count
= lsmash_bs_get_be16( bs
);
1037 for( int i
= 0; i
< 32; i
++ )
1038 visual
->compressorname
[i
] = lsmash_bs_get_byte( bs
);
1039 visual
->depth
= lsmash_bs_get_be16( bs
);
1040 visual
->color_table_ID
= lsmash_bs_get_be16( bs
);
1042 if( visual
->color_table_ID
== 0
1043 && lsmash_bs_get_pos( bs
) < box
->size
1044 && (ret
= isom_read_qt_color_table( bs
, &visual
->color_table
)) < 0 )
1046 box
->parent
= parent
;
1047 box
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1048 isom_box_common_copy( visual
, box
);
1049 if( (ret
= isom_add_print_func( file
, visual
, level
)) < 0 )
1051 return isom_read_children( file
, box
, visual
, level
);
1054 static int isom_read_esds( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1056 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4V_VIDEO
)
1057 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
1058 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_ENCA_AUDIO
)
1059 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_M4AE_AUDIO
)
1060 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
)
1061 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1062 return isom_read_codec_specific( file
, box
, parent
, level
);
1063 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1065 box
->type
= QT_BOX_TYPE_ESDS
;
1066 assert( LSMASH_IS_EXISTING_BOX( parent
->parent
) );
1067 if( lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_CODEC_TYPE_MP4A_AUDIO
) )
1068 parent
->parent
->type
= QT_CODEC_TYPE_MP4A_AUDIO
;
1071 box
->type
= ISOM_BOX_TYPE_ESDS
;
1072 ADD_BOX( esds
, void );
1073 lsmash_bs_t
*bs
= file
->bs
;
1074 esds
->ES
= mp4sys_get_descriptor( bs
, NULL
);
1076 return LSMASH_ERR_INVALID_DATA
;
1077 return isom_read_leaf_box_common_last_process( file
, box
, level
, esds
);
1080 static int isom_read_btrt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1082 ADD_BOX( btrt
, isom_visual_entry_t
);
1083 lsmash_bs_t
*bs
= file
->bs
;
1084 btrt
->bufferSizeDB
= lsmash_bs_get_be32( bs
);
1085 btrt
->maxBitrate
= lsmash_bs_get_be32( bs
);
1086 btrt
->avgBitrate
= lsmash_bs_get_be32( bs
);
1087 return isom_read_leaf_box_common_last_process( file
, box
, level
, btrt
);
1090 static int isom_read_glbl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1092 ADD_BOX( glbl
, isom_visual_entry_t
);
1093 lsmash_bs_t
*bs
= file
->bs
;
1094 uint32_t header_size
= box
->size
- ISOM_BASEBOX_COMMON_SIZE
;
1097 glbl
->header_data
= lsmash_malloc( header_size
);
1098 if( !glbl
->header_data
)
1099 return LSMASH_ERR_MEMORY_ALLOC
;
1100 for( uint32_t i
= 0; i
< header_size
; i
++ )
1101 glbl
->header_data
[i
] = lsmash_bs_get_byte( bs
);
1103 glbl
->header_size
= header_size
;
1104 return isom_read_leaf_box_common_last_process( file
, box
, level
, glbl
);
1107 static int isom_read_clap( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1109 ADD_BOX( clap
, isom_visual_entry_t
);
1110 lsmash_bs_t
*bs
= file
->bs
;
1111 clap
->cleanApertureWidthN
= lsmash_bs_get_be32( bs
);
1112 clap
->cleanApertureWidthD
= lsmash_bs_get_be32( bs
);
1113 clap
->cleanApertureHeightN
= lsmash_bs_get_be32( bs
);
1114 clap
->cleanApertureHeightD
= lsmash_bs_get_be32( bs
);
1115 clap
->horizOffN
= lsmash_bs_get_be32( bs
);
1116 clap
->horizOffD
= lsmash_bs_get_be32( bs
);
1117 clap
->vertOffN
= lsmash_bs_get_be32( bs
);
1118 clap
->vertOffD
= lsmash_bs_get_be32( bs
);
1119 return isom_read_leaf_box_common_last_process( file
, box
, level
, clap
);
1122 static int isom_read_pasp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1124 ADD_BOX( pasp
, isom_visual_entry_t
);
1125 lsmash_bs_t
*bs
= file
->bs
;
1126 pasp
->hSpacing
= lsmash_bs_get_be32( bs
);
1127 pasp
->vSpacing
= lsmash_bs_get_be32( bs
);
1128 return isom_read_leaf_box_common_last_process( file
, box
, level
, pasp
);
1131 static int isom_read_colr( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1133 ADD_BOX( colr
, isom_visual_entry_t
);
1134 lsmash_bs_t
*bs
= file
->bs
;
1135 colr
->color_parameter_type
= lsmash_bs_get_be32( bs
);
1136 if( colr
->color_parameter_type
== QT_COLOR_PARAMETER_TYPE_NCLC
1137 || colr
->color_parameter_type
== ISOM_COLOR_PARAMETER_TYPE_NCLX
)
1139 colr
->primaries_index
= lsmash_bs_get_be16( bs
);
1140 colr
->transfer_function_index
= lsmash_bs_get_be16( bs
);
1141 colr
->matrix_index
= lsmash_bs_get_be16( bs
);
1142 if( colr
->color_parameter_type
== ISOM_COLOR_PARAMETER_TYPE_NCLX
)
1144 if( lsmash_bs_count( bs
) < box
->size
)
1146 uint8_t temp8
= lsmash_bs_get_byte( bs
);
1147 colr
->full_range_flag
= (temp8
>> 7) & 0x01;
1148 colr
->reserved
= temp8
& 0x7f;
1152 /* It seems this box is broken or incomplete. */
1153 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
1154 colr
->full_range_flag
= 0;
1159 box
->manager
|= LSMASH_QTFF_BASE
;
1161 box
->type
= (box
->manager
& LSMASH_QTFF_BASE
) ? QT_BOX_TYPE_COLR
: ISOM_BOX_TYPE_COLR
;
1162 return isom_read_leaf_box_common_last_process( file
, box
, level
, colr
);
1165 static int isom_read_gama( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1167 ADD_BOX( gama
, isom_visual_entry_t
);
1168 lsmash_bs_t
*bs
= file
->bs
;
1169 gama
->level
= lsmash_bs_get_be32( bs
);
1170 return isom_read_leaf_box_common_last_process( file
, box
, level
, gama
);
1173 static int isom_read_fiel( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1175 ADD_BOX( fiel
, isom_visual_entry_t
);
1176 lsmash_bs_t
*bs
= file
->bs
;
1177 fiel
->fields
= lsmash_bs_get_byte( bs
);
1178 fiel
->detail
= lsmash_bs_get_byte( bs
);
1179 return isom_read_leaf_box_common_last_process( file
, box
, level
, fiel
);
1182 static int isom_read_clli( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1184 ADD_BOX( clli
, isom_visual_entry_t
);
1185 lsmash_bs_t
*bs
= file
->bs
;
1186 clli
->max_content_light_level
= lsmash_bs_get_be16( bs
);
1187 clli
->max_pic_average_light_level
= lsmash_bs_get_be16( bs
);
1188 return isom_read_leaf_box_common_last_process( file
, box
, level
, clli
);
1191 static int isom_read_mdcv( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1193 ADD_BOX( mdcv
, isom_visual_entry_t
);
1194 lsmash_bs_t
*bs
= file
->bs
;
1195 mdcv
->display_primaries_g_x
= lsmash_bs_get_be16( bs
);
1196 mdcv
->display_primaries_g_y
= lsmash_bs_get_be16( bs
);
1197 mdcv
->display_primaries_b_x
= lsmash_bs_get_be16( bs
);
1198 mdcv
->display_primaries_b_y
= lsmash_bs_get_be16( bs
);
1199 mdcv
->display_primaries_r_x
= lsmash_bs_get_be16( bs
);
1200 mdcv
->display_primaries_r_y
= lsmash_bs_get_be16( bs
);
1201 mdcv
->white_point_x
= lsmash_bs_get_be16( bs
);
1202 mdcv
->white_point_y
= lsmash_bs_get_be16( bs
);
1203 mdcv
->max_display_mastering_luminance
= lsmash_bs_get_be32( bs
);
1204 mdcv
->min_display_mastering_luminance
= lsmash_bs_get_be32( bs
);
1205 return isom_read_leaf_box_common_last_process( file
, box
, level
, mdcv
);
1208 static int isom_read_cspc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1210 ADD_BOX( cspc
, isom_visual_entry_t
);
1211 lsmash_bs_t
*bs
= file
->bs
;
1212 cspc
->pixel_format
= lsmash_bs_get_be32( bs
);
1213 return isom_read_leaf_box_common_last_process( file
, box
, level
, cspc
);
1216 static int isom_read_sgbt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1218 ADD_BOX( sgbt
, isom_visual_entry_t
);
1219 lsmash_bs_t
*bs
= file
->bs
;
1220 sgbt
->significantBits
= lsmash_bs_get_byte( bs
);
1221 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgbt
);
1224 static int isom_read_stsl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1226 ADD_BOX( stsl
, isom_visual_entry_t
);
1227 lsmash_bs_t
*bs
= file
->bs
;
1228 stsl
->constraint_flag
= lsmash_bs_get_byte( bs
);
1229 stsl
->scale_method
= lsmash_bs_get_byte( bs
);
1230 stsl
->display_center_x
= lsmash_bs_get_be16( bs
);
1231 stsl
->display_center_y
= lsmash_bs_get_be16( bs
);
1232 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsl
);
1235 static int isom_read_audio_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1237 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1238 return isom_read_unknown_box( file
, box
, parent
, level
);
1239 isom_audio_entry_t
*audio
= (isom_audio_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1240 if( LSMASH_IS_NON_EXISTING_BOX( audio
) )
1241 return LSMASH_ERR_MEMORY_ALLOC
;
1242 lsmash_bs_t
*bs
= file
->bs
;
1243 for( int i
= 0; i
< 6; i
++ )
1244 audio
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1245 audio
->data_reference_index
= lsmash_bs_get_be16( bs
);
1246 audio
->version
= lsmash_bs_get_be16( bs
);
1247 audio
->revision_level
= lsmash_bs_get_be16( bs
);
1248 audio
->vendor
= lsmash_bs_get_be32( bs
);
1249 audio
->channelcount
= lsmash_bs_get_be16( bs
);
1250 audio
->samplesize
= lsmash_bs_get_be16( bs
);
1251 audio
->compression_ID
= lsmash_bs_get_be16( bs
);
1252 audio
->packet_size
= lsmash_bs_get_be16( bs
);
1253 audio
->samplerate
= lsmash_bs_get_be32( bs
);
1254 if( audio
->version
== 0 && isom_is_qt_audio( box
->type
) )
1256 /* Skip weird extra bytes.
1257 * About QTFF, extensions were first added with Sound Sample Description v1. */
1258 while( lsmash_bs_count( bs
) + ISOM_BASEBOX_COMMON_SIZE
<= box
->size
)
1260 uint32_t size
= lsmash_bs_show_be32( bs
, 0 );
1261 if( size
== 0 || lsmash_bs_count( bs
) + size
> box
->size
)
1262 lsmash_bs_skip_bytes( bs
, 1 );
1267 else if( audio
->version
== 1 )
1269 if( ((isom_stsd_t
*)parent
)->version
== 0 )
1271 audio
->samplesPerPacket
= lsmash_bs_get_be32( bs
);
1272 audio
->bytesPerPacket
= lsmash_bs_get_be32( bs
);
1273 audio
->bytesPerFrame
= lsmash_bs_get_be32( bs
);
1274 audio
->bytesPerSample
= lsmash_bs_get_be32( bs
);
1275 box
->manager
|= LSMASH_QTFF_BASE
;
1278 /* AudioSampleEntryV1 has no additional fields. */
1279 box
->manager
&= ~LSMASH_QTFF_BASE
;
1281 else if( audio
->version
== 2 )
1283 audio
->sizeOfStructOnly
= lsmash_bs_get_be32( bs
);
1284 audio
->audioSampleRate
= lsmash_bs_get_be64( bs
);
1285 audio
->numAudioChannels
= lsmash_bs_get_be32( bs
);
1286 audio
->always7F000000
= lsmash_bs_get_be32( bs
);
1287 audio
->constBitsPerChannel
= lsmash_bs_get_be32( bs
);
1288 audio
->formatSpecificFlags
= lsmash_bs_get_be32( bs
);
1289 audio
->constBytesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1290 audio
->constLPCMFramesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1291 box
->manager
|= LSMASH_QTFF_BASE
;
1293 box
->parent
= parent
;
1294 box
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1295 isom_box_common_copy( audio
, box
);
1296 int ret
= isom_add_print_func( file
, audio
, level
);
1299 return isom_read_children( file
, box
, audio
, level
);
1302 static int isom_read_wave( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1304 ADD_BOX( wave
, isom_audio_entry_t
);
1305 isom_box_common_copy( wave
, box
);
1306 int ret
= isom_add_print_func( file
, wave
, level
);
1309 return isom_read_children( file
, box
, wave
, level
);
1312 static int isom_read_frma( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1314 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1315 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->frma
) )
1316 return isom_read_unknown_box( file
, box
, parent
, level
);
1317 ADD_BOX( frma
, isom_wave_t
);
1318 lsmash_bs_t
*bs
= file
->bs
;
1319 frma
->data_format
= lsmash_bs_get_be32( bs
);
1320 return isom_read_leaf_box_common_last_process( file
, box
, level
, frma
);
1323 static int isom_read_enda( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1325 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1326 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->enda
) )
1327 return isom_read_unknown_box( file
, box
, parent
, level
);
1328 ADD_BOX( enda
, isom_wave_t
);
1329 lsmash_bs_t
*bs
= file
->bs
;
1330 enda
->littleEndian
= lsmash_bs_get_be16( bs
);
1331 return isom_read_leaf_box_common_last_process( file
, box
, level
, enda
);
1334 static int isom_read_terminator( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1336 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1337 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->terminator
) )
1338 return isom_read_unknown_box( file
, box
, parent
, level
);
1339 ADD_BOX( terminator
, isom_wave_t
);
1340 return isom_read_leaf_box_common_last_process( file
, box
, level
, terminator
);
1343 static int isom_read_chan( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1345 ADD_BOX( chan
, isom_audio_entry_t
);
1346 lsmash_bs_t
*bs
= file
->bs
;
1347 chan
->channelLayoutTag
= lsmash_bs_get_be32( bs
);
1348 chan
->channelBitmap
= lsmash_bs_get_be32( bs
);
1349 chan
->numberChannelDescriptions
= lsmash_bs_get_be32( bs
);
1350 if( chan
->numberChannelDescriptions
)
1352 isom_channel_description_t
*desc
= lsmash_malloc( chan
->numberChannelDescriptions
* sizeof(isom_channel_description_t
) );
1354 return LSMASH_ERR_MEMORY_ALLOC
;
1355 chan
->channelDescriptions
= desc
;
1356 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
1358 desc
->channelLabel
= lsmash_bs_get_be32( bs
);
1359 desc
->channelFlags
= lsmash_bs_get_be32( bs
);
1360 for( int j
= 0; j
< 3; j
++ )
1361 desc
->coordinates
[j
] = lsmash_bs_get_be32( bs
);
1364 return isom_read_leaf_box_common_last_process( file
, box
, level
, chan
);
1367 static int isom_read_srat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1369 ADD_BOX( srat
, isom_audio_entry_t
);
1370 lsmash_bs_t
*bs
= file
->bs
;
1371 srat
->sampling_rate
= lsmash_bs_get_be32( bs
);
1372 return isom_read_leaf_box_common_last_process( file
, box
, level
, srat
);
1375 static int isom_read_qt_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1377 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1378 return isom_read_unknown_box( file
, box
, parent
, level
);
1379 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1380 if( LSMASH_IS_NON_EXISTING_BOX( text
) )
1381 return LSMASH_ERR_MEMORY_ALLOC
;
1382 lsmash_bs_t
*bs
= file
->bs
;
1383 for( int i
= 0; i
< 6; i
++ )
1384 text
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1385 text
->data_reference_index
= lsmash_bs_get_be16( bs
);
1386 text
->displayFlags
= lsmash_bs_get_be32( bs
);
1387 text
->textJustification
= lsmash_bs_get_be32( bs
);
1388 for( int i
= 0; i
< 3; i
++ )
1389 text
->bgColor
[i
] = lsmash_bs_get_be16( bs
);
1390 text
->top
= lsmash_bs_get_be16( bs
);
1391 text
->left
= lsmash_bs_get_be16( bs
);
1392 text
->bottom
= lsmash_bs_get_be16( bs
);
1393 text
->right
= lsmash_bs_get_be16( bs
);
1394 text
->scrpStartChar
= lsmash_bs_get_be32( bs
);
1395 text
->scrpHeight
= lsmash_bs_get_be16( bs
);
1396 text
->scrpAscent
= lsmash_bs_get_be16( bs
);
1397 text
->scrpFont
= lsmash_bs_get_be16( bs
);
1398 text
->scrpFace
= lsmash_bs_get_be16( bs
);
1399 text
->scrpSize
= lsmash_bs_get_be16( bs
);
1400 for( int i
= 0; i
< 3; i
++ )
1401 text
->scrpColor
[i
] = lsmash_bs_get_be16( bs
);
1402 text
->font_name_length
= lsmash_bs_get_byte( bs
);
1403 if( text
->font_name_length
)
1405 text
->font_name
= lsmash_malloc( text
->font_name_length
+ 1 );
1406 if( !text
->font_name
)
1407 return LSMASH_ERR_MEMORY_ALLOC
;
1408 for( uint8_t i
= 0; i
< text
->font_name_length
; i
++ )
1409 text
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1410 text
->font_name
[text
->font_name_length
] = '\0';
1412 box
->parent
= parent
;
1413 isom_box_common_copy( text
, box
);
1414 int ret
= isom_add_print_func( file
, text
, level
);
1417 return isom_read_children( file
, box
, text
, level
);
1420 static int isom_read_tx3g_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1422 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1423 return isom_read_unknown_box( file
, box
, parent
, level
);
1424 isom_tx3g_entry_t
*tx3g
= (isom_tx3g_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1425 if( LSMASH_IS_NON_EXISTING_BOX( tx3g
) )
1426 return LSMASH_ERR_MEMORY_ALLOC
;
1427 lsmash_bs_t
*bs
= file
->bs
;
1428 for( int i
= 0; i
< 6; i
++ )
1429 tx3g
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1430 tx3g
->data_reference_index
= lsmash_bs_get_be16( bs
);
1431 tx3g
->displayFlags
= lsmash_bs_get_be32( bs
);
1432 tx3g
->horizontal_justification
= lsmash_bs_get_byte( bs
);
1433 tx3g
->vertical_justification
= lsmash_bs_get_byte( bs
);
1434 for( int i
= 0; i
< 4; i
++ )
1435 tx3g
->background_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1436 tx3g
->top
= lsmash_bs_get_be16( bs
);
1437 tx3g
->left
= lsmash_bs_get_be16( bs
);
1438 tx3g
->bottom
= lsmash_bs_get_be16( bs
);
1439 tx3g
->right
= lsmash_bs_get_be16( bs
);
1440 tx3g
->startChar
= lsmash_bs_get_be16( bs
);
1441 tx3g
->endChar
= lsmash_bs_get_be16( bs
);
1442 tx3g
->font_ID
= lsmash_bs_get_be16( bs
);
1443 tx3g
->face_style_flags
= lsmash_bs_get_byte( bs
);
1444 tx3g
->font_size
= lsmash_bs_get_byte( bs
);
1445 for( int i
= 0; i
< 4; i
++ )
1446 tx3g
->text_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1447 box
->parent
= parent
;
1448 isom_box_common_copy( tx3g
, box
);
1449 int ret
= isom_add_print_func( file
, tx3g
, level
);
1452 return isom_read_children( file
, box
, tx3g
, level
);
1455 static int isom_read_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1457 if( lsmash_check_codec_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1458 return isom_read_qt_text_description( file
, box
, parent
, level
);
1459 else if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1460 return isom_read_tx3g_description( file
, box
, parent
, level
);
1462 return isom_read_unknown_box( file
, box
, parent
, level
);
1465 static int isom_read_ftab( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1467 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
)
1468 || LSMASH_IS_EXISTING_BOX( ((isom_tx3g_entry_t
*)parent
)->ftab
) )
1469 return isom_read_codec_specific( file
, box
, parent
, level
);
1470 ADD_BOX( ftab
, isom_tx3g_entry_t
);
1471 lsmash_bs_t
*bs
= file
->bs
;
1472 uint32_t entry_count
= lsmash_bs_get_be16( bs
);
1473 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ftab
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1475 isom_font_record_t
*data
= lsmash_malloc_zero( sizeof(isom_font_record_t
) );
1477 return LSMASH_ERR_MEMORY_ALLOC
;
1478 if( lsmash_list_add_entry( ftab
->list
, data
) < 0 )
1480 lsmash_free( data
);
1481 return LSMASH_ERR_MEMORY_ALLOC
;
1483 data
->font_ID
= lsmash_bs_get_be16( bs
);
1484 data
->font_name_length
= lsmash_bs_get_byte( bs
);
1485 if( data
->font_name_length
)
1487 data
->font_name
= lsmash_malloc( data
->font_name_length
+ 1 );
1488 if( !data
->font_name
)
1489 return LSMASH_ERR_MEMORY_ALLOC
;
1490 for( uint8_t i
= 0; i
< data
->font_name_length
; i
++ )
1491 data
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1492 data
->font_name
[data
->font_name_length
] = '\0';
1495 return isom_read_leaf_box_common_last_process( file
, box
, level
, ftab
);
1498 static int isom_read_mp4s_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1500 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1501 return isom_read_unknown_box( file
, box
, parent
, level
);
1502 isom_mp4s_entry_t
*mp4s
= (isom_mp4s_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1503 if( LSMASH_IS_NON_EXISTING_BOX( mp4s
) )
1504 return LSMASH_ERR_MEMORY_ALLOC
;
1505 lsmash_bs_t
*bs
= file
->bs
;
1506 for( int i
= 0; i
< 6; i
++ )
1507 mp4s
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1508 mp4s
->data_reference_index
= lsmash_bs_get_be16( bs
);
1509 box
->parent
= parent
;
1510 isom_box_common_copy( mp4s
, box
);
1511 int ret
= isom_add_print_func( file
, mp4s
, level
);
1514 return isom_read_children( file
, box
, mp4s
, level
);
1517 static int isom_read_other_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1519 if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
) )
1520 return isom_read_mp4s_description( file
, box
, parent
, level
);
1521 return isom_read_unknown_box( file
, box
, parent
, level
);
1524 static int isom_read_stts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1526 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1527 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stts
) )
1528 return isom_read_unknown_box( file
, box
, parent
, level
);
1529 ADD_BOX( stts
, isom_stbl_t
);
1530 lsmash_bs_t
*bs
= file
->bs
;
1531 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1532 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1534 isom_stts_entry_t
*data
= lsmash_malloc( sizeof(isom_stts_entry_t
) );
1536 return LSMASH_ERR_MEMORY_ALLOC
;
1537 if( lsmash_list_add_entry( stts
->list
, data
) < 0 )
1539 lsmash_free( data
);
1540 return LSMASH_ERR_MEMORY_ALLOC
;
1542 data
->sample_count
= lsmash_bs_get_be32( bs
);
1543 data
->sample_delta
= lsmash_bs_get_be32( bs
);
1545 return isom_read_leaf_box_common_last_process( file
, box
, level
, stts
);
1548 static int isom_read_ctts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1550 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1551 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->ctts
) )
1552 return isom_read_unknown_box( file
, box
, parent
, level
);
1553 ADD_BOX( ctts
, isom_stbl_t
);
1554 lsmash_bs_t
*bs
= file
->bs
;
1555 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1556 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ctts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1558 isom_ctts_entry_t
*data
= lsmash_malloc( sizeof(isom_ctts_entry_t
) );
1560 return LSMASH_ERR_MEMORY_ALLOC
;
1561 if( lsmash_list_add_entry( ctts
->list
, data
) < 0 )
1563 lsmash_free( data
);
1564 return LSMASH_ERR_MEMORY_ALLOC
;
1566 data
->sample_count
= lsmash_bs_get_be32( bs
);
1567 data
->sample_offset
= lsmash_bs_get_be32( bs
);
1569 return isom_read_leaf_box_common_last_process( file
, box
, level
, ctts
);
1572 static int isom_read_cslg( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1574 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1575 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->cslg
) )
1576 return isom_read_unknown_box( file
, box
, parent
, level
);
1577 ADD_BOX( cslg
, isom_stbl_t
);
1578 lsmash_bs_t
*bs
= file
->bs
;
1579 cslg
->compositionToDTSShift
= lsmash_bs_get_be32( bs
);
1580 cslg
->leastDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1581 cslg
->greatestDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1582 cslg
->compositionStartTime
= lsmash_bs_get_be32( bs
);
1583 cslg
->compositionEndTime
= lsmash_bs_get_be32( bs
);
1584 return isom_read_leaf_box_common_last_process( file
, box
, level
, cslg
);
1587 static int isom_read_stss( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1589 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1590 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stss
) )
1591 return isom_read_unknown_box( file
, box
, parent
, level
);
1592 ADD_BOX( stss
, isom_stbl_t
);
1593 lsmash_bs_t
*bs
= file
->bs
;
1594 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1595 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stss
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1597 isom_stss_entry_t
*data
= lsmash_malloc( sizeof(isom_stss_entry_t
) );
1599 return LSMASH_ERR_MEMORY_ALLOC
;
1600 if( lsmash_list_add_entry( stss
->list
, data
) < 0 )
1602 lsmash_free( data
);
1603 return LSMASH_ERR_MEMORY_ALLOC
;
1605 data
->sample_number
= lsmash_bs_get_be32( bs
);
1607 return isom_read_leaf_box_common_last_process( file
, box
, level
, stss
);
1610 static int isom_read_stps( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1612 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1613 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stps
) )
1614 return isom_read_unknown_box( file
, box
, parent
, level
);
1615 ADD_BOX( stps
, isom_stbl_t
);
1616 lsmash_bs_t
*bs
= file
->bs
;
1617 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1618 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stps
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1620 isom_stps_entry_t
*data
= lsmash_malloc( sizeof(isom_stps_entry_t
) );
1622 return LSMASH_ERR_MEMORY_ALLOC
;
1623 if( lsmash_list_add_entry( stps
->list
, data
) < 0 )
1625 lsmash_free( data
);
1626 return LSMASH_ERR_MEMORY_ALLOC
;
1628 data
->sample_number
= lsmash_bs_get_be32( bs
);
1630 return isom_read_leaf_box_common_last_process( file
, box
, level
, stps
);
1633 static int isom_read_sdtp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1635 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1636 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
))
1637 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) && LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->sdtp
))
1638 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) && LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->sdtp
)) )
1639 return isom_read_unknown_box( file
, box
, parent
, level
);
1640 ADD_BOX( sdtp
, isom_box_t
);
1641 lsmash_bs_t
*bs
= file
->bs
;
1642 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
; pos
= lsmash_bs_count( bs
) )
1644 isom_sdtp_entry_t
*data
= lsmash_malloc( sizeof(isom_sdtp_entry_t
) );
1646 return LSMASH_ERR_MEMORY_ALLOC
;
1647 if( lsmash_list_add_entry( sdtp
->list
, data
) < 0 )
1649 lsmash_free( data
);
1650 return LSMASH_ERR_MEMORY_ALLOC
;
1652 uint8_t temp
= lsmash_bs_get_byte( bs
);
1653 data
->is_leading
= (temp
>> 6) & 0x3;
1654 data
->sample_depends_on
= (temp
>> 4) & 0x3;
1655 data
->sample_is_depended_on
= (temp
>> 2) & 0x3;
1656 data
->sample_has_redundancy
= temp
& 0x3;
1658 return isom_read_leaf_box_common_last_process( file
, box
, level
, sdtp
);
1661 static int isom_read_stsc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1663 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1664 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stsc
) )
1665 return isom_read_unknown_box( file
, box
, parent
, level
);
1666 ADD_BOX( stsc
, isom_stbl_t
);
1667 lsmash_bs_t
*bs
= file
->bs
;
1668 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1669 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stsc
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1671 isom_stsc_entry_t
*data
= lsmash_malloc( sizeof(isom_stsc_entry_t
) );
1673 return LSMASH_ERR_MEMORY_ALLOC
;
1674 if( lsmash_list_add_entry( stsc
->list
, data
) < 0 )
1676 lsmash_free( data
);
1677 return LSMASH_ERR_MEMORY_ALLOC
;
1679 data
->first_chunk
= lsmash_bs_get_be32( bs
);
1680 data
->samples_per_chunk
= lsmash_bs_get_be32( bs
);
1681 data
->sample_description_index
= lsmash_bs_get_be32( bs
);
1683 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsc
);
1686 static int isom_read_stsz( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1688 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1689 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stsz
) )
1690 return isom_read_unknown_box( file
, box
, parent
, level
);
1691 ADD_BOX( stsz
, isom_stbl_t
);
1692 lsmash_bs_t
*bs
= file
->bs
;
1693 stsz
->sample_size
= lsmash_bs_get_be32( bs
);
1694 stsz
->sample_count
= lsmash_bs_get_be32( bs
);
1695 uint64_t pos
= lsmash_bs_count( bs
);
1696 if( pos
< box
->size
)
1698 stsz
->list
= lsmash_list_create_simple();
1700 return LSMASH_ERR_MEMORY_ALLOC
;
1701 for( ; pos
< box
->size
&& stsz
->list
->entry_count
< stsz
->sample_count
; pos
= lsmash_bs_count( bs
) )
1703 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1705 return LSMASH_ERR_MEMORY_ALLOC
;
1706 if( lsmash_list_add_entry( stsz
->list
, data
) < 0 )
1708 lsmash_free( data
);
1709 return LSMASH_ERR_MEMORY_ALLOC
;
1711 data
->entry_size
= lsmash_bs_get_be32( bs
);
1714 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsz
);
1717 static int isom_read_stz2( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1719 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1720 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stz2
) )
1721 return isom_read_unknown_box( file
, box
, parent
, level
);
1722 ADD_BOX( stz2
, isom_stbl_t
);
1723 lsmash_bs_t
*bs
= file
->bs
;
1724 uint32_t temp32
= lsmash_bs_get_be32( bs
);
1725 stz2
->reserved
= temp32
>> 24;
1726 stz2
->field_size
= temp32
& 0xff;
1727 stz2
->sample_count
= lsmash_bs_get_be32( bs
);
1728 uint64_t pos
= lsmash_bs_count( bs
);
1729 if( pos
< box
->size
)
1731 if( stz2
->field_size
== 16 || stz2
->field_size
== 8 )
1733 uint64_t (*bs_get_funcs
[2])( lsmash_bs_t
* ) =
1735 lsmash_bs_get_byte_to_64
,
1736 lsmash_bs_get_be16_to_64
1738 uint64_t (*bs_get_entry_size
)( lsmash_bs_t
* ) = bs_get_funcs
[ stz2
->field_size
== 16 ? 1 : 0 ];
1739 for( ; pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
; pos
= lsmash_bs_count( bs
) )
1741 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1743 return LSMASH_ERR_MEMORY_ALLOC
;
1744 if( lsmash_list_add_entry( stz2
->list
, data
) < 0 )
1746 lsmash_free( data
);
1747 return LSMASH_ERR_MEMORY_ALLOC
;
1749 data
->entry_size
= bs_get_entry_size( bs
);
1752 else if( stz2
->field_size
== 4 )
1756 while( pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
)
1758 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1760 return LSMASH_ERR_MEMORY_ALLOC
;
1761 if( lsmash_list_add_entry( stz2
->list
, data
) < 0 )
1763 lsmash_free( data
);
1764 return LSMASH_ERR_MEMORY_ALLOC
;
1766 /* Read a byte by two entries. */
1769 temp8
= lsmash_bs_get_byte( bs
);
1770 data
->entry_size
= (temp8
>> 4) & 0xf;
1774 pos
= lsmash_bs_count( bs
);
1775 data
->entry_size
= temp8
& 0xf;
1781 return LSMASH_ERR_INVALID_DATA
;
1783 return isom_read_leaf_box_common_last_process( file
, box
, level
, stz2
);
1786 static int isom_read_stco( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1788 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1789 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stco
) )
1790 return isom_read_unknown_box( file
, box
, parent
, level
);
1791 box
->type
= lsmash_form_iso_box_type( box
->type
.fourcc
);
1792 int is_stco
= lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_STCO
);
1793 isom_stco_t
*stco
= is_stco
1794 ? isom_add_stco( (isom_stbl_t
*)parent
)
1795 : isom_add_co64( (isom_stbl_t
*)parent
);
1797 return LSMASH_ERR_NAMELESS
;
1798 lsmash_bs_t
*bs
= file
->bs
;
1799 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1801 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1803 isom_stco_entry_t
*data
= lsmash_malloc( sizeof(isom_stco_entry_t
) );
1805 return LSMASH_ERR_MEMORY_ALLOC
;
1806 if( lsmash_list_add_entry( stco
->list
, data
) < 0 )
1808 lsmash_free( data
);
1809 return LSMASH_ERR_MEMORY_ALLOC
;
1811 data
->chunk_offset
= lsmash_bs_get_be32( bs
);
1815 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1817 isom_co64_entry_t
*data
= lsmash_malloc( sizeof(isom_co64_entry_t
) );
1819 return LSMASH_ERR_MEMORY_ALLOC
;
1820 if( lsmash_list_add_entry( stco
->list
, data
) < 0 )
1822 lsmash_free( data
);
1823 return LSMASH_ERR_MEMORY_ALLOC
;
1825 data
->chunk_offset
= lsmash_bs_get_be64( bs
);
1828 return isom_read_leaf_box_common_last_process( file
, box
, level
, stco
);
1831 static int isom_read_sgpd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1833 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1834 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1835 return isom_read_unknown_box( file
, box
, parent
, level
);
1836 ADD_BOX( sgpd
, void );
1837 lsmash_bs_t
*bs
= file
->bs
;
1838 sgpd
->grouping_type
= lsmash_bs_get_be32( bs
);
1839 if( box
->version
== 1 )
1840 sgpd
->default_length
= lsmash_bs_get_be32( bs
);
1841 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1842 switch( sgpd
->grouping_type
)
1844 case ISOM_GROUP_TYPE_RAP
:
1846 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sgpd
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1848 isom_rap_entry_t
*data
= lsmash_malloc( sizeof(isom_rap_entry_t
) );
1850 return LSMASH_ERR_MEMORY_ALLOC
;
1851 if( lsmash_list_add_entry( sgpd
->list
, data
) < 0 )
1853 lsmash_free( data
);
1854 return LSMASH_ERR_MEMORY_ALLOC
;
1856 memset( data
, 0, sizeof(isom_rap_entry_t
) );
1857 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1858 if( box
->version
== 1 && !sgpd
->default_length
)
1859 data
->description_length
= lsmash_bs_get_be32( bs
);
1862 uint8_t temp
= lsmash_bs_get_byte( bs
);
1863 data
->num_leading_samples_known
= (temp
>> 7) & 0x01;
1864 data
->num_leading_samples
= temp
& 0x7f;
1869 case ISOM_GROUP_TYPE_ROLL
:
1870 case ISOM_GROUP_TYPE_PROL
:
1872 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sgpd
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1874 isom_roll_entry_t
*data
= lsmash_malloc( sizeof(isom_roll_entry_t
) );
1876 return LSMASH_ERR_MEMORY_ALLOC
;
1877 if( lsmash_list_add_entry( sgpd
->list
, data
) < 0 )
1879 lsmash_free( data
);
1880 return LSMASH_ERR_MEMORY_ALLOC
;
1882 memset( data
, 0, sizeof(isom_roll_entry_t
) );
1883 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1884 if( box
->version
== 1 && !sgpd
->default_length
)
1885 data
->description_length
= lsmash_bs_get_be32( bs
);
1887 data
->roll_distance
= lsmash_bs_get_be16( bs
);
1894 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgpd
);
1897 static int isom_read_sbgp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1899 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1900 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1901 return isom_read_unknown_box( file
, box
, parent
, level
);
1902 ADD_BOX( sbgp
, void );
1903 lsmash_bs_t
*bs
= file
->bs
;
1904 sbgp
->grouping_type
= lsmash_bs_get_be32( bs
);
1905 if( box
->version
== 1 )
1906 sbgp
->grouping_type_parameter
= lsmash_bs_get_be32( bs
);
1907 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1908 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sbgp
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1910 isom_group_assignment_entry_t
*data
= lsmash_malloc( sizeof(isom_group_assignment_entry_t
) );
1912 return LSMASH_ERR_MEMORY_ALLOC
;
1913 if( lsmash_list_add_entry( sbgp
->list
, data
) < 0 )
1915 lsmash_free( data
);
1916 return LSMASH_ERR_MEMORY_ALLOC
;
1918 data
->sample_count
= lsmash_bs_get_be32( bs
);
1919 data
->group_description_index
= lsmash_bs_get_be32( bs
);
1921 return isom_read_leaf_box_common_last_process( file
, box
, level
,sbgp
);
1924 static int isom_read_udta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1926 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
1927 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
))
1928 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->udta
))
1929 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->udta
)) )
1930 return isom_read_unknown_box( file
, box
, parent
, level
);
1931 ADD_BOX( udta
, void );
1932 isom_box_common_copy( udta
, box
);
1933 int ret
= isom_add_print_func( file
, udta
, level
);
1936 return isom_read_children( file
, box
, udta
, level
);
1939 static int isom_read_chpl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1941 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
1942 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->chpl
) )
1943 return isom_read_unknown_box( file
, box
, parent
, level
);
1944 ADD_BOX( chpl
, isom_udta_t
);
1945 lsmash_bs_t
*bs
= file
->bs
;
1946 uint32_t entry_count
;
1947 if( box
->version
== 1 )
1949 chpl
->unknown
= lsmash_bs_get_byte( bs
);
1950 entry_count
= lsmash_bs_get_be32( bs
);
1953 entry_count
= lsmash_bs_get_byte( bs
);
1954 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& chpl
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1956 isom_chpl_entry_t
*data
= lsmash_malloc( sizeof(isom_chpl_entry_t
) );
1958 return LSMASH_ERR_MEMORY_ALLOC
;
1959 if( lsmash_list_add_entry( chpl
->list
, data
) < 0 )
1961 lsmash_free( data
);
1962 return LSMASH_ERR_MEMORY_ALLOC
;
1964 data
->start_time
= lsmash_bs_get_be64( bs
);
1965 data
->chapter_name_length
= lsmash_bs_get_byte( bs
);
1966 data
->chapter_name
= lsmash_malloc( data
->chapter_name_length
+ 1 );
1967 if( !data
->chapter_name
)
1969 lsmash_free( data
);
1970 return LSMASH_ERR_MEMORY_ALLOC
;
1972 for( uint8_t i
= 0; i
< data
->chapter_name_length
; i
++ )
1973 data
->chapter_name
[i
] = lsmash_bs_get_byte( bs
);
1974 data
->chapter_name
[data
->chapter_name_length
] = '\0';
1976 return isom_read_leaf_box_common_last_process( file
, box
, level
, chpl
);
1979 static int isom_read_mvex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1981 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
1982 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->mvex
) )
1983 return isom_read_unknown_box( file
, box
, parent
, level
);
1984 ADD_BOX( mvex
, isom_moov_t
);
1985 file
->flags
|= LSMASH_FILE_MODE_FRAGMENTED
;
1986 isom_box_common_copy( mvex
, box
);
1987 int ret
= isom_add_print_func( file
, mvex
, level
);
1990 return isom_read_children( file
, box
, mvex
, level
);
1993 static int isom_read_mehd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1995 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
)
1996 || LSMASH_IS_EXISTING_BOX( ((isom_mvex_t
*)parent
)->mehd
) )
1997 return isom_read_unknown_box( file
, box
, parent
, level
);
1998 ADD_BOX( mehd
, isom_mvex_t
);
1999 lsmash_bs_t
*bs
= file
->bs
;
2000 if( box
->version
== 1 )
2001 mehd
->fragment_duration
= lsmash_bs_get_be64( bs
);
2003 mehd
->fragment_duration
= lsmash_bs_get_be32( bs
);
2004 return isom_read_leaf_box_common_last_process( file
, box
, level
, mehd
);
2007 static isom_sample_flags_t
isom_bs_get_sample_flags( lsmash_bs_t
*bs
)
2009 uint32_t temp
= lsmash_bs_get_be32( bs
);
2010 isom_sample_flags_t flags
;
2011 flags
.reserved
= (temp
>> 28) & 0xf;
2012 flags
.is_leading
= (temp
>> 26) & 0x3;
2013 flags
.sample_depends_on
= (temp
>> 24) & 0x3;
2014 flags
.sample_is_depended_on
= (temp
>> 22) & 0x3;
2015 flags
.sample_has_redundancy
= (temp
>> 20) & 0x3;
2016 flags
.sample_padding_value
= (temp
>> 17) & 0x7;
2017 flags
.sample_is_non_sync_sample
= (temp
>> 16) & 0x1;
2018 flags
.sample_degradation_priority
= temp
& 0xffff;
2022 static int isom_read_trex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2024 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
) )
2025 return isom_read_unknown_box( file
, box
, parent
, level
);
2026 ADD_BOX( trex
, isom_mvex_t
);
2027 box
->parent
= parent
;
2028 lsmash_bs_t
*bs
= file
->bs
;
2029 trex
->track_ID
= lsmash_bs_get_be32( bs
);
2030 trex
->default_sample_description_index
= lsmash_bs_get_be32( bs
);
2031 trex
->default_sample_duration
= lsmash_bs_get_be32( bs
);
2032 trex
->default_sample_size
= lsmash_bs_get_be32( bs
);
2033 trex
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
2034 return isom_read_leaf_box_common_last_process( file
, box
, level
, trex
);
2037 static int isom_read_moof( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2039 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
2040 return isom_read_unknown_box( file
, box
, parent
, level
);
2041 ADD_BOX( moof
, lsmash_file_t
);
2042 box
->parent
= parent
;
2043 isom_box_common_copy( moof
, box
);
2044 int ret
= isom_add_print_func( file
, moof
, level
);
2047 return isom_read_children( file
, box
, moof
, level
);
2050 static int isom_read_mfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2052 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
)
2053 || LSMASH_IS_EXISTING_BOX( ((isom_moof_t
*)parent
)->mfhd
) )
2054 return isom_read_unknown_box( file
, box
, parent
, level
);
2055 ADD_BOX( mfhd
, isom_moof_t
);
2056 lsmash_bs_t
*bs
= file
->bs
;
2057 mfhd
->sequence_number
= lsmash_bs_get_be32( bs
);
2058 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfhd
);
2061 static int isom_read_traf( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2063 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
) )
2064 return isom_read_unknown_box( file
, box
, parent
, level
);
2065 ADD_BOX( traf
, isom_moof_t
);
2066 box
->parent
= parent
;
2067 isom_box_common_copy( traf
, box
);
2068 int ret
= isom_add_print_func( file
, traf
, level
);
2071 return isom_read_children( file
, box
, traf
, level
);
2074 static int isom_read_tfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2076 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
)
2077 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->tfhd
) )
2078 return isom_read_unknown_box( file
, box
, parent
, level
);
2079 ADD_BOX( tfhd
, isom_traf_t
);
2080 lsmash_bs_t
*bs
= file
->bs
;
2081 tfhd
->track_ID
= lsmash_bs_get_be32( bs
);
2082 if( box
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) tfhd
->base_data_offset
= lsmash_bs_get_be64( bs
);
2083 if( box
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) tfhd
->sample_description_index
= lsmash_bs_get_be32( bs
);
2084 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) tfhd
->default_sample_duration
= lsmash_bs_get_be32( bs
);
2085 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) tfhd
->default_sample_size
= lsmash_bs_get_be32( bs
);
2086 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) tfhd
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
2087 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfhd
);
2090 static int isom_read_tfdt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2092 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
)
2093 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->tfdt
) )
2094 return isom_read_unknown_box( file
, box
, parent
, level
);
2095 ADD_BOX( tfdt
, isom_traf_t
);
2096 lsmash_bs_t
*bs
= file
->bs
;
2097 if( box
->version
== 1 )
2098 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be64( bs
);
2100 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be32( bs
);
2101 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfdt
);
2104 static int isom_read_trun( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2106 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
2107 return isom_read_unknown_box( file
, box
, parent
, level
);
2108 ADD_BOX( trun
, isom_traf_t
);
2109 box
->parent
= parent
;
2110 lsmash_bs_t
*bs
= file
->bs
;
2111 int has_optional_rows
= ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2112 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2113 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2114 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
;
2115 has_optional_rows
&= box
->flags
;
2116 trun
->sample_count
= lsmash_bs_get_be32( bs
);
2117 if( box
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) trun
->data_offset
= lsmash_bs_get_be32( bs
);
2118 if( box
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) trun
->first_sample_flags
= isom_bs_get_sample_flags( bs
);
2119 if( trun
->sample_count
&& has_optional_rows
)
2121 trun
->optional
= lsmash_list_create_simple();
2122 if( !trun
->optional
)
2123 return LSMASH_ERR_MEMORY_ALLOC
;
2124 for( uint32_t i
= 0; i
< trun
->sample_count
; i
++ )
2126 isom_trun_optional_row_t
*data
= lsmash_malloc( sizeof(isom_trun_optional_row_t
) );
2128 return LSMASH_ERR_MEMORY_ALLOC
;
2129 if( lsmash_list_add_entry( trun
->optional
, data
) < 0 )
2131 lsmash_free( data
);
2132 return LSMASH_ERR_MEMORY_ALLOC
;
2134 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) data
->sample_duration
= lsmash_bs_get_be32( bs
);
2135 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) data
->sample_size
= lsmash_bs_get_be32( bs
);
2136 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) data
->sample_flags
= isom_bs_get_sample_flags( bs
);
2137 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) data
->sample_composition_time_offset
= lsmash_bs_get_be32( bs
);
2140 return isom_read_leaf_box_common_last_process( file
, box
, level
, trun
);
2143 static int isom_read_free( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2145 if( file
->fake_file_mode
)
2146 return isom_read_unknown_box( file
, box
, parent
, level
);
2147 isom_skip_t
*skip
= ALLOCATE_BOX( skip
);
2148 if( LSMASH_IS_NON_EXISTING_BOX( skip
) )
2149 return LSMASH_ERR_MEMORY_ALLOC
;
2150 isom_skip_box_rest( file
->bs
, box
);
2151 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2152 isom_box_common_copy( skip
, box
);
2153 int ret
= isom_add_print_func( file
, skip
, level
);
2156 isom_remove_box_by_itself( skip
);
2162 static int isom_read_mdat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2164 if( file
->fake_file_mode
|| !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
2165 return isom_read_unknown_box( file
, box
, parent
, level
);
2166 isom_mdat_t
*mdat
= ALLOCATE_BOX( mdat
);
2167 if( LSMASH_IS_NON_EXISTING_BOX( mdat
) )
2168 return LSMASH_ERR_MEMORY_ALLOC
;
2169 isom_skip_box_rest( file
->bs
, box
);
2170 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2171 file
->flags
|= LSMASH_FILE_MODE_MEDIA
;
2172 isom_box_common_copy( mdat
, box
);
2173 int ret
= isom_add_print_func( file
, mdat
, level
);
2176 isom_remove_box_by_itself( mdat
);
2182 static int isom_read_meta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2184 if( (!lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
2185 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
2186 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
2187 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
))
2188 || (lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) && LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->meta
))
2189 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->meta
))
2190 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->meta
))
2191 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) && LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->meta
)) )
2192 return isom_read_unknown_box( file
, box
, parent
, level
);
2193 ADD_BOX( meta
, void );
2194 isom_box_common_copy( meta
, box
);
2195 int is_qtff
= lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_META
);
2198 box
->manager
|= LSMASH_QTFF_BASE
;
2199 meta
->manager
|= LSMASH_QTFF_BASE
;
2201 int ret
= isom_add_print_func( file
, meta
, level
);
2204 return isom_read_children( file
, box
, meta
, level
);
2207 static int isom_read_keys( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2209 if( (!lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) && !(parent
->manager
& LSMASH_QTFF_BASE
))
2210 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->keys
) )
2211 return isom_read_unknown_box( file
, box
, parent
, level
);
2212 ADD_BOX( keys
, isom_meta_t
);
2213 lsmash_bs_t
*bs
= file
->bs
;
2214 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
2215 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& keys
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
2217 isom_keys_entry_t
*data
= lsmash_malloc( sizeof(isom_keys_entry_t
) );
2219 return LSMASH_ERR_MEMORY_ALLOC
;
2220 if( lsmash_list_add_entry( keys
->list
, data
) < 0 )
2222 lsmash_free( data
);
2223 return LSMASH_ERR_MEMORY_ALLOC
;
2225 data
->key_size
= lsmash_bs_get_be32( bs
);
2226 data
->key_namespace
= lsmash_bs_get_be32( bs
);
2227 if( data
->key_size
> 8 )
2229 data
->key_value
= lsmash_bs_get_bytes( bs
, data
->key_size
- 8 );
2230 if( !data
->key_value
)
2231 return LSMASH_ERR_NAMELESS
;
2234 data
->key_value
= NULL
;
2236 return isom_read_leaf_box_common_last_process( file
, box
, level
, keys
);
2239 static int isom_read_ilst( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2241 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
2242 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
))
2243 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->ilst
) )
2244 return isom_read_unknown_box( file
, box
, parent
, level
);
2245 ADD_BOX( ilst
, isom_meta_t
);
2246 isom_box_common_copy( ilst
, box
);
2247 int ret
= isom_add_print_func( file
, ilst
, level
);
2250 return isom_read_children( file
, box
, ilst
, level
);
2253 static int isom_read_metaitem( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2255 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
2256 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2257 return isom_read_unknown_box( file
, box
, parent
, level
);
2258 isom_metaitem_t
*metaitem
= isom_add_metaitem( (isom_ilst_t
*)parent
, box
->type
.fourcc
);
2261 box
->parent
= parent
;
2262 isom_box_common_copy( metaitem
, box
);
2263 int ret
= isom_add_print_func( file
, metaitem
, level
);
2266 return isom_read_children( file
, box
, metaitem
, level
);
2269 static int isom_read_mean( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2271 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
2272 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->mean
) )
2273 return isom_read_unknown_box( file
, box
, parent
, level
);
2274 ADD_BOX( mean
, isom_metaitem_t
);
2275 lsmash_bs_t
*bs
= file
->bs
;
2276 mean
->meaning_string_length
= box
->size
- lsmash_bs_count( bs
);
2277 mean
->meaning_string
= lsmash_bs_get_bytes( bs
, mean
->meaning_string_length
);
2278 if( !mean
->meaning_string
)
2279 return LSMASH_ERR_NAMELESS
;
2280 return isom_read_leaf_box_common_last_process( file
, box
, level
, mean
);
2283 static int isom_read_name( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2285 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
2286 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->name
) )
2287 return isom_read_unknown_box( file
, box
, parent
, level
);
2288 ADD_BOX( name
, isom_metaitem_t
);
2289 lsmash_bs_t
*bs
= file
->bs
;
2290 name
->name_length
= box
->size
- lsmash_bs_count( bs
);
2291 name
->name
= lsmash_bs_get_bytes( bs
, name
->name_length
);
2293 return LSMASH_ERR_NAMELESS
;
2294 return isom_read_leaf_box_common_last_process( file
, box
, level
, name
);
2297 static int isom_read_data( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2299 if( LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->data
) )
2300 return isom_read_unknown_box( file
, box
, parent
, level
);
2301 ADD_BOX( data
, isom_metaitem_t
);
2302 lsmash_bs_t
*bs
= file
->bs
;
2303 data
->value_length
= box
->size
- lsmash_bs_count( bs
) - 8;
2304 data
->reserved
= lsmash_bs_get_be16( bs
);
2305 data
->type_set_identifier
= lsmash_bs_get_byte( bs
);
2306 data
->type_code
= lsmash_bs_get_byte( bs
);
2307 data
->the_locale
= lsmash_bs_get_be32( bs
);
2308 if( data
->value_length
)
2310 data
->value
= lsmash_bs_get_bytes( bs
, data
->value_length
);
2312 return LSMASH_ERR_NAMELESS
;
2314 return isom_read_leaf_box_common_last_process( file
, box
, level
, data
);
2317 static int isom_read_WLOC( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2319 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2320 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->WLOC
) )
2321 return isom_read_unknown_box( file
, box
, parent
, level
);
2322 ADD_BOX( WLOC
, isom_udta_t
);
2323 lsmash_bs_t
*bs
= file
->bs
;
2324 WLOC
->x
= lsmash_bs_get_be16( bs
);
2325 WLOC
->y
= lsmash_bs_get_be16( bs
);
2326 return isom_read_leaf_box_common_last_process( file
, box
, level
, WLOC
);
2329 static int isom_read_LOOP( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2331 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2332 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->LOOP
) )
2333 return isom_read_unknown_box( file
, box
, parent
, level
);
2334 ADD_BOX( LOOP
, isom_udta_t
);
2335 lsmash_bs_t
*bs
= file
->bs
;
2336 LOOP
->looping_mode
= lsmash_bs_get_be32( bs
);
2337 return isom_read_leaf_box_common_last_process( file
, box
, level
, LOOP
);
2340 static int isom_read_SelO( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2342 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2343 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->SelO
) )
2344 return isom_read_unknown_box( file
, box
, parent
, level
);
2345 ADD_BOX( SelO
, isom_udta_t
);
2346 lsmash_bs_t
*bs
= file
->bs
;
2347 SelO
->selection_only
= lsmash_bs_get_byte( bs
);
2348 return isom_read_leaf_box_common_last_process( file
, box
, level
, SelO
);
2351 static int isom_read_AllF( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2353 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2354 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->AllF
) )
2355 return isom_read_unknown_box( file
, box
, parent
, level
);
2356 ADD_BOX( AllF
, isom_udta_t
);
2357 lsmash_bs_t
*bs
= file
->bs
;
2358 AllF
->play_all_frames
= lsmash_bs_get_byte( bs
);
2359 return isom_read_leaf_box_common_last_process( file
, box
, level
, AllF
);
2362 static int isom_read_cprt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2364 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
2365 return isom_read_unknown_box( file
, box
, parent
, level
);
2366 ADD_BOX( cprt
, isom_udta_t
);
2367 box
->parent
= parent
;
2368 lsmash_bs_t
*bs
= file
->bs
;
2369 cprt
->language
= lsmash_bs_get_be16( bs
);
2370 cprt
->notice_length
= box
->size
- (ISOM_FULLBOX_COMMON_SIZE
+ 2);
2371 if( cprt
->notice_length
)
2373 cprt
->notice
= lsmash_bs_get_bytes( bs
, cprt
->notice_length
);
2376 cprt
->notice_length
= 0;
2377 return LSMASH_ERR_NAMELESS
;
2380 return isom_read_leaf_box_common_last_process( file
, box
, level
, cprt
);
2383 static int isom_read_mfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2385 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
2386 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->mfra
) )
2387 return isom_read_unknown_box( file
, box
, parent
, level
);
2388 ADD_BOX( mfra
, lsmash_file_t
);
2389 isom_box_common_copy( mfra
, box
);
2390 int ret
= isom_add_print_func( file
, mfra
, level
);
2393 return isom_read_children( file
, box
, mfra
, level
);
2396 static int isom_read_tfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2398 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
) )
2399 return isom_read_unknown_box( file
, box
, parent
, level
);
2400 ADD_BOX( tfra
, isom_mfra_t
);
2401 box
->parent
= parent
;
2402 lsmash_bs_t
*bs
= file
->bs
;
2403 tfra
->track_ID
= lsmash_bs_get_be32( bs
);
2404 uint32_t temp
= lsmash_bs_get_be32( bs
);
2405 tfra
->number_of_entry
= lsmash_bs_get_be32( bs
);
2406 tfra
->reserved
= (temp
>> 6) & 0x3ffffff;
2407 tfra
->length_size_of_traf_num
= (temp
>> 4) & 0x3;
2408 tfra
->length_size_of_trun_num
= (temp
>> 2) & 0x3;
2409 tfra
->length_size_of_sample_num
= temp
& 0x3;
2410 if( tfra
->number_of_entry
)
2412 tfra
->list
= lsmash_list_create_simple();
2414 return LSMASH_ERR_MEMORY_ALLOC
;
2415 uint64_t (*bs_get_funcs
[5])( lsmash_bs_t
* ) =
2417 lsmash_bs_get_byte_to_64
,
2418 lsmash_bs_get_be16_to_64
,
2419 lsmash_bs_get_be24_to_64
,
2420 lsmash_bs_get_be32_to_64
,
2423 uint64_t (*bs_put_time
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2424 uint64_t (*bs_put_moof_offset
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2425 uint64_t (*bs_put_traf_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_traf_num
];
2426 uint64_t (*bs_put_trun_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_trun_num
];
2427 uint64_t (*bs_put_sample_number
)( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_sample_num
];
2428 for( uint32_t i
= 0; i
< tfra
->number_of_entry
; i
++ )
2430 isom_tfra_location_time_entry_t
*data
= lsmash_malloc( sizeof(isom_tfra_location_time_entry_t
) );
2432 return LSMASH_ERR_MEMORY_ALLOC
;
2433 if( lsmash_list_add_entry( tfra
->list
, data
) < 0 )
2435 lsmash_free( data
);
2436 return LSMASH_ERR_MEMORY_ALLOC
;
2438 data
->time
= bs_put_time ( bs
);
2439 data
->moof_offset
= bs_put_moof_offset ( bs
);
2440 data
->traf_number
= bs_put_traf_number ( bs
);
2441 data
->trun_number
= bs_put_trun_number ( bs
);
2442 data
->sample_number
= bs_put_sample_number( bs
);
2445 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfra
);
2448 static int isom_read_mfro( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2450 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
)
2451 || LSMASH_IS_EXISTING_BOX( ((isom_mfra_t
*)parent
)->mfro
) )
2452 return isom_read_unknown_box( file
, box
, parent
, level
);
2453 ADD_BOX( mfro
, isom_mfra_t
);
2454 lsmash_bs_t
*bs
= file
->bs
;
2455 mfro
->length
= lsmash_bs_get_be32( bs
);
2456 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfro
);
2459 static void isom_read_skip_extra_bytes( lsmash_bs_t
*bs
, uint64_t size
)
2461 if( !bs
->unseekable
)
2463 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2464 while( size
> (INT64_MAX
>> 1) )
2466 lsmash_bs_read_seek( bs
, INT64_MAX
>> 1, SEEK_CUR
);
2467 if( lsmash_bs_is_end( bs
, 0 ) )
2469 size
-= (INT64_MAX
>> 1);
2471 lsmash_bs_read_seek( bs
, size
, SEEK_CUR
);
2474 lsmash_bs_skip_bytes_64( bs
, size
);
2477 static int isom_read_skip_box_extra_bytes( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
)
2479 lsmash_bs_t
*bs
= file
->bs
;
2480 /* Skip extra bytes of the parent box if any. */
2481 if( parent
->size
< parent_pos
+ ISOM_BASEBOX_COMMON_SIZE
)
2483 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2484 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2485 /* This is not the size of a box but makes sense in isom_read_children(). */
2486 box
->size
= extra_bytes
;
2489 /* Check if the size is valid or not. */
2490 if( lsmash_bs_is_end( bs
, 3 ) == 0 )
2492 uint64_t size
= (uint64_t)lsmash_bs_show_be32( bs
, 0 );
2494 && size
< ISOM_BASEBOX_COMMON_SIZE
)
2496 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2497 * Skip bytes up to the next box of the parent box. */
2498 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2499 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2500 box
->size
= extra_bytes
;
2503 if( size
== 1 && lsmash_bs_is_end( bs
, 15 ) == 0 )
2504 size
= lsmash_bs_show_be64( bs
, 8 ); /* large size */
2505 if( size
== 0 && parent
!= (isom_box_t
*)file
)
2507 /* Check if this box is actually the last box or not. */
2508 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2509 if( !bs
->unseekable
)
2510 size
= bs
->written
- lsmash_bs_get_stream_pos( bs
);
2513 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2514 while( size
<= extra_bytes
)
2516 int ret
= lsmash_bs_read( bs
, 1 );
2517 if( bs
->eof
|| ret
< 0 )
2519 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2522 if( size
!= extra_bytes
)
2524 /* This is not the size of the last box.
2525 * It seems we are still within the box considered as the previous or the parent box.
2526 * Skip bytes up to the next box. */
2527 if( box
->size
> lsmash_bs_count( bs
) )
2529 /* within the previous */
2530 isom_read_skip_extra_bytes( bs
, box
->size
- lsmash_bs_count( bs
) );
2531 box
->size
= 0; /* already added to the size of the parent box */
2535 /* within the parent */
2536 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2537 box
->size
= extra_bytes
;
2546 int isom_read_box( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
, int level
)
2548 assert( parent
&& parent
->root
&& parent
->file
);
2549 if( isom_read_skip_box_extra_bytes( file
, box
, parent
, parent_pos
) != 0 )
2551 memset( box
, 0, sizeof(isom_box_t
) );
2552 box
->root
= parent
->root
;
2553 box
->file
= parent
->file
;
2554 box
->parent
= parent
;
2555 lsmash_bs_t
*bs
= file
->bs
;
2556 int ret
= isom_bs_read_box_common( bs
, box
);
2558 return ret
; /* return if reached EOF */
2560 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
) = NULL
;
2561 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int ) = NULL
;
2562 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
2564 /* OK, this box is a sample entry.
2565 * Here, determine the suitable sample entry reader by media type if possible. */
2566 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
2568 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
2569 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
2570 reader_func
= isom_read_visual_description
;
2571 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
2572 reader_func
= isom_read_audio_description
;
2573 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
2574 reader_func
= isom_read_text_description
;
2576 reader_func
= isom_read_other_description
;
2577 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2578 static struct description_reader_table_tag
2580 lsmash_compact_box_type_t fourcc
;
2581 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2582 } description_reader_table
[160] = { { 0, NULL
} };
2583 if( !description_reader_table
[0].form_box_type_func
)
2585 /* Initialize the table. */
2587 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2588 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, lsmash_form_iso_box_type
);
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, lsmash_form_iso_box_type
);
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, lsmash_form_iso_box_type
);
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, lsmash_form_iso_box_type
);
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, lsmash_form_iso_box_type
);
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, lsmash_form_iso_box_type
);
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, lsmash_form_iso_box_type
);
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, lsmash_form_iso_box_type
);
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, lsmash_form_iso_box_type
);
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, lsmash_form_iso_box_type
);
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, lsmash_form_iso_box_type
);
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, lsmash_form_iso_box_type
);
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, lsmash_form_iso_box_type
);
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, lsmash_form_iso_box_type
);
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, lsmash_form_iso_box_type
);
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, lsmash_form_iso_box_type
);
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, lsmash_form_qtff_box_type
);
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, lsmash_form_qtff_box_type
);
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, lsmash_form_qtff_box_type
);
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, lsmash_form_qtff_box_type
);
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, lsmash_form_qtff_box_type
);
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, lsmash_form_qtff_box_type
);
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, lsmash_form_qtff_box_type
);
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, lsmash_form_qtff_box_type
);
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, lsmash_form_qtff_box_type
);
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, lsmash_form_qtff_box_type
);
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, lsmash_form_qtff_box_type
);
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, lsmash_form_qtff_box_type
);
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, lsmash_form_qtff_box_type
);
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, lsmash_form_qtff_box_type
);
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, lsmash_form_qtff_box_type
);
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, lsmash_form_qtff_box_type
);
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, lsmash_form_qtff_box_type
);
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, lsmash_form_qtff_box_type
);
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, lsmash_form_qtff_box_type
);
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, lsmash_form_qtff_box_type
);
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, lsmash_form_qtff_box_type
);
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, lsmash_form_qtff_box_type
);
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, lsmash_form_qtff_box_type
);
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO
, lsmash_form_qtff_box_type
);
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, lsmash_form_qtff_box_type
);
2630 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, lsmash_form_qtff_box_type
);
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, lsmash_form_qtff_box_type
);
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, lsmash_form_qtff_box_type
);
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, lsmash_form_qtff_box_type
);
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, lsmash_form_qtff_box_type
);
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, lsmash_form_qtff_box_type
);
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, lsmash_form_qtff_box_type
);
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, lsmash_form_qtff_box_type
);
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, lsmash_form_qtff_box_type
);
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, lsmash_form_qtff_box_type
);
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, lsmash_form_qtff_box_type
);
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, lsmash_form_qtff_box_type
);
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, lsmash_form_qtff_box_type
);
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, lsmash_form_qtff_box_type
);
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, lsmash_form_qtff_box_type
);
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, lsmash_form_qtff_box_type
);
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, lsmash_form_qtff_box_type
);
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, lsmash_form_qtff_box_type
);
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, lsmash_form_qtff_box_type
);
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, lsmash_form_qtff_box_type
);
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, lsmash_form_qtff_box_type
);
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, lsmash_form_qtff_box_type
);
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, lsmash_form_qtff_box_type
);
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, lsmash_form_qtff_box_type
);
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, lsmash_form_qtff_box_type
);
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, lsmash_form_qtff_box_type
);
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, lsmash_form_qtff_box_type
);
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, lsmash_form_qtff_box_type
);
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, lsmash_form_qtff_box_type
);
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO
, lsmash_form_qtff_box_type
);
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, lsmash_form_qtff_box_type
);
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, lsmash_form_qtff_box_type
);
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, lsmash_form_qtff_box_type
);
2664 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, lsmash_form_qtff_box_type
);
2665 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, lsmash_form_qtff_box_type
);
2666 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, lsmash_form_qtff_box_type
);
2667 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, lsmash_form_iso_box_type
);
2668 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, lsmash_form_iso_box_type
);
2669 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, lsmash_form_iso_box_type
);
2670 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSEL_AUDIO
, lsmash_form_iso_box_type
);
2671 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSDL_AUDIO
, lsmash_form_iso_box_type
);
2672 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, lsmash_form_iso_box_type
);
2673 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, lsmash_form_iso_box_type
);
2674 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, lsmash_form_iso_box_type
);
2675 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, lsmash_form_iso_box_type
);
2676 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSX_AUDIO
, lsmash_form_iso_box_type
);
2677 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, lsmash_form_iso_box_type
);
2678 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, lsmash_form_iso_box_type
);
2679 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, lsmash_form_iso_box_type
);
2680 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, lsmash_form_iso_box_type
);
2681 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, lsmash_form_iso_box_type
);
2682 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, lsmash_form_iso_box_type
);
2683 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, lsmash_form_iso_box_type
);
2684 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, lsmash_form_iso_box_type
);
2685 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, lsmash_form_iso_box_type
);
2686 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, lsmash_form_iso_box_type
);
2687 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, lsmash_form_iso_box_type
);
2688 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, lsmash_form_iso_box_type
);
2689 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, lsmash_form_iso_box_type
);
2690 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2691 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO
, lsmash_form_iso_box_type
);
2692 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, lsmash_form_qtff_box_type
);
2693 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO
, lsmash_form_qtff_box_type
);
2694 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO
, lsmash_form_qtff_box_type
);
2695 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, lsmash_form_qtff_box_type
);
2696 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO
, lsmash_form_qtff_box_type
);
2697 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO
, lsmash_form_qtff_box_type
);
2698 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO
, lsmash_form_qtff_box_type
);
2699 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO
, lsmash_form_qtff_box_type
);
2700 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO
, lsmash_form_qtff_box_type
);
2701 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO
, lsmash_form_qtff_box_type
);
2702 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO
, lsmash_form_qtff_box_type
);
2703 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO
, lsmash_form_qtff_box_type
);
2704 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO
, lsmash_form_qtff_box_type
);
2705 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, lsmash_form_qtff_box_type
);
2706 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, lsmash_form_qtff_box_type
);
2707 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO
, lsmash_form_qtff_box_type
);
2708 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, lsmash_form_qtff_box_type
);
2709 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, lsmash_form_qtff_box_type
);
2710 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, lsmash_form_qtff_box_type
);
2711 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, lsmash_form_qtff_box_type
);
2712 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, lsmash_form_qtff_box_type
);
2713 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO
, lsmash_form_qtff_box_type
);
2714 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO
, lsmash_form_qtff_box_type
);
2715 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO
, lsmash_form_qtff_box_type
);
2716 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO
, lsmash_form_qtff_box_type
);
2717 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO
, lsmash_form_qtff_box_type
);
2718 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO
, lsmash_form_qtff_box_type
);
2719 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO
, lsmash_form_qtff_box_type
);
2720 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, lsmash_form_qtff_box_type
);
2721 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, lsmash_form_qtff_box_type
);
2722 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, lsmash_form_iso_box_type
);
2723 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, lsmash_form_iso_box_type
);
2724 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW
, lsmash_form_qtff_box_type
);
2725 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
2726 assert( sizeof(description_reader_table
) >= (size_t)i
* sizeof(description_reader_table
[0]) );
2727 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2729 for( int i
= 0; description_reader_table
[i
].form_box_type_func
; i
++ )
2730 if( box
->type
.fourcc
== description_reader_table
[i
].fourcc
)
2732 form_box_type_func
= description_reader_table
[i
].form_box_type_func
;
2737 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
2739 form_box_type_func
= lsmash_form_qtff_box_type
;
2740 if( box
->type
.fourcc
== QT_BOX_TYPE_FRMA
.fourcc
) reader_func
= isom_read_frma
;
2741 else if( box
->type
.fourcc
== QT_BOX_TYPE_ENDA
.fourcc
) reader_func
= isom_read_enda
;
2742 else if( box
->type
.fourcc
== QT_BOX_TYPE_ESDS
.fourcc
) reader_func
= isom_read_esds
;
2743 else if( box
->type
.fourcc
== QT_BOX_TYPE_CHAN
.fourcc
) reader_func
= isom_read_chan
;
2744 else if( box
->type
.fourcc
== QT_BOX_TYPE_TERMINATOR
.fourcc
) reader_func
= isom_read_terminator
;
2745 else reader_func
= isom_read_codec_specific
;
2748 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
2750 form_box_type_func
= lsmash_form_iso_box_type
;
2751 reader_func
= isom_read_track_reference_type
;
2754 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_DREF
) )
2756 if( box
->type
.fourcc
== ISOM_BOX_TYPE_URL
.fourcc
2757 || box
->type
.fourcc
== ISOM_BOX_TYPE_URN
.fourcc
)
2758 form_box_type_func
= lsmash_form_iso_box_type
;
2759 else if( box
->type
.fourcc
== QT_BOX_TYPE_ALIS
.fourcc
2760 || box
->type
.fourcc
== QT_BOX_TYPE_RSRC
.fourcc
)
2761 form_box_type_func
= lsmash_form_qtff_box_type
;
2762 reader_func
= isom_read_dref_entry
;
2765 static struct box_reader_table_tag
2767 lsmash_compact_box_type_t fourcc
;
2768 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2769 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int );
2770 } box_reader_table
[128] = { { 0, NULL
, NULL
} };
2771 if( !box_reader_table
[0].reader_func
)
2773 /* Initialize the table. */
2775 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2776 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2777 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, lsmash_form_iso_box_type
, isom_read_ftyp
);
2778 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, lsmash_form_iso_box_type
, isom_read_styp
);
2779 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, lsmash_form_iso_box_type
, isom_read_sidx
);
2780 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, lsmash_form_iso_box_type
, isom_read_moov
);
2781 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, lsmash_form_iso_box_type
, isom_read_mvhd
);
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, lsmash_form_iso_box_type
, isom_read_iods
);
2783 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, lsmash_form_qtff_box_type
, isom_read_ctab
);
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, lsmash_form_iso_box_type
, isom_read_trak
);
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, lsmash_form_iso_box_type
, isom_read_tkhd
);
2786 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, lsmash_form_qtff_box_type
, isom_read_tapt
);
2787 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, lsmash_form_qtff_box_type
, isom_read_clef
);
2788 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, lsmash_form_qtff_box_type
, isom_read_prof
);
2789 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, lsmash_form_qtff_box_type
, isom_read_enof
);
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, lsmash_form_iso_box_type
, isom_read_edts
);
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, lsmash_form_iso_box_type
, isom_read_elst
);
2792 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, lsmash_form_iso_box_type
, isom_read_tref
);
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, lsmash_form_iso_box_type
, isom_read_mdia
);
2794 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, lsmash_form_iso_box_type
, isom_read_mdhd
);
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, lsmash_form_iso_box_type
, isom_read_hdlr
);
2796 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, lsmash_form_iso_box_type
, isom_read_minf
);
2797 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, lsmash_form_iso_box_type
, isom_read_vmhd
);
2798 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, lsmash_form_iso_box_type
, isom_read_smhd
);
2799 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, lsmash_form_iso_box_type
, isom_read_hmhd
);
2800 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, lsmash_form_iso_box_type
, isom_read_nmhd
);
2801 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, lsmash_form_qtff_box_type
, isom_read_gmhd
);
2802 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, lsmash_form_qtff_box_type
, isom_read_gmin
);
2803 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, lsmash_form_qtff_box_type
, isom_read_text
);
2804 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, lsmash_form_iso_box_type
, isom_read_dinf
);
2805 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, lsmash_form_iso_box_type
, isom_read_dref
);
2806 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, lsmash_form_iso_box_type
, isom_read_stbl
);
2807 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, lsmash_form_iso_box_type
, isom_read_stsd
);
2808 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, lsmash_form_iso_box_type
, isom_read_stts
);
2809 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, lsmash_form_iso_box_type
, isom_read_ctts
);
2810 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, lsmash_form_iso_box_type
, isom_read_cslg
);
2811 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, lsmash_form_iso_box_type
, isom_read_stss
);
2812 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, lsmash_form_qtff_box_type
, isom_read_stps
);
2813 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, lsmash_form_iso_box_type
, isom_read_sdtp
);
2814 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, lsmash_form_iso_box_type
, isom_read_stsc
);
2815 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, lsmash_form_iso_box_type
, isom_read_stsz
);
2816 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, lsmash_form_iso_box_type
, isom_read_stz2
);
2817 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, lsmash_form_iso_box_type
, isom_read_stco
);
2818 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, lsmash_form_iso_box_type
, isom_read_stco
);
2819 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, lsmash_form_iso_box_type
, isom_read_sgpd
);
2820 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, lsmash_form_iso_box_type
, isom_read_sbgp
);
2821 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, lsmash_form_iso_box_type
, isom_read_udta
);
2822 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, lsmash_form_iso_box_type
, isom_read_chpl
);
2823 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC
, lsmash_form_qtff_box_type
, isom_read_WLOC
);
2824 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP
, lsmash_form_qtff_box_type
, isom_read_LOOP
);
2825 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO
, lsmash_form_qtff_box_type
, isom_read_SelO
);
2826 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF
, lsmash_form_qtff_box_type
, isom_read_AllF
);
2827 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, lsmash_form_iso_box_type
, isom_read_mvex
);
2828 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, lsmash_form_iso_box_type
, isom_read_mehd
);
2829 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, lsmash_form_iso_box_type
, isom_read_trex
);
2830 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, lsmash_form_iso_box_type
, isom_read_moof
);
2831 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, lsmash_form_iso_box_type
, isom_read_mfhd
);
2832 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, lsmash_form_iso_box_type
, isom_read_traf
);
2833 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, lsmash_form_iso_box_type
, isom_read_tfhd
);
2834 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, lsmash_form_iso_box_type
, isom_read_tfdt
);
2835 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, lsmash_form_iso_box_type
, isom_read_trun
);
2836 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, lsmash_form_iso_box_type
, isom_read_free
);
2837 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, lsmash_form_iso_box_type
, isom_read_free
);
2838 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, lsmash_form_iso_box_type
, isom_read_mdat
);
2839 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS
, lsmash_form_qtff_box_type
, isom_read_keys
);
2840 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, lsmash_form_iso_box_type
, isom_read_mfra
);
2841 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, lsmash_form_iso_box_type
, isom_read_tfra
);
2842 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, lsmash_form_iso_box_type
, isom_read_mfro
);
2843 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
, NULL
);
2844 assert( sizeof(box_reader_table
) >= (size_t)i
* sizeof(box_reader_table
[0]) );
2845 #undef ADD_BOX_READER_TABLE_ELEMENT
2847 for( int i
= 0; box_reader_table
[i
].reader_func
; i
++ )
2848 if( box
->type
.fourcc
== box_reader_table
[i
].fourcc
)
2850 form_box_type_func
= box_reader_table
[i
].form_box_type_func
;
2851 reader_func
= box_reader_table
[i
].reader_func
;
2854 if( box
->type
.fourcc
== ISOM_BOX_TYPE_META
.fourcc
)
2856 if( lsmash_bs_is_end ( bs
, 3 ) == 0
2857 && lsmash_bs_show_be32( bs
, 0 ) == 0 )
2858 form_box_type_func
= lsmash_form_iso_box_type
;
2860 form_box_type_func
= lsmash_form_qtff_box_type
;
2861 reader_func
= isom_read_meta
;
2864 if( box
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2866 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
) )
2867 form_box_type_func
= lsmash_form_iso_box_type
;
2868 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
2869 form_box_type_func
= lsmash_form_qtff_box_type
;
2870 if( form_box_type_func
)
2872 reader_func
= isom_read_ilst
;
2876 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
) )
2877 form_box_type_func
= lsmash_form_iso_box_type
;
2878 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2879 form_box_type_func
= lsmash_form_qtff_box_type
;
2880 if( form_box_type_func
)
2882 reader_func
= isom_read_metaitem
;
2885 if( parent
->parent
&& parent
->parent
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2887 if( box
->type
.fourcc
== ISOM_BOX_TYPE_MEAN
.fourcc
)
2888 reader_func
= isom_read_mean
;
2889 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_NAME
.fourcc
)
2890 reader_func
= isom_read_name
;
2891 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_DATA
.fourcc
)
2892 reader_func
= isom_read_data
;
2895 form_box_type_func
= lsmash_form_iso_box_type
;
2899 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_CPRT
.fourcc
)
2901 /* Avoid confusing udta.cprt with ilst.cprt. */
2902 form_box_type_func
= lsmash_form_iso_box_type
;
2903 reader_func
= isom_read_cprt
;
2906 if( parent
->parent
&& lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_STSD
) )
2908 static struct sample_description_extension_reader_table_tag
2910 lsmash_compact_box_type_t fourcc
;
2911 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2912 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int );
2913 } extension_reader_table
[32] = { { 0, NULL
, NULL
} };
2914 if( !extension_reader_table
[0].reader_func
)
2916 /* Initialize the table. */
2918 #define ADD_EXTENSION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2919 extension_reader_table[i++] = (struct sample_description_extension_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2921 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2922 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2923 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2924 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2925 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2926 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT
, lsmash_form_iso_box_type
, isom_read_srat
);
2927 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2928 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, lsmash_form_qtff_box_type
, isom_read_chan
);
2929 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, lsmash_form_qtff_box_type
, isom_read_wave
);
2931 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2932 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, lsmash_form_iso_box_type
, isom_read_btrt
);
2933 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, lsmash_form_iso_box_type
, isom_read_colr
);
2934 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, lsmash_form_iso_box_type
, isom_read_clap
);
2935 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2936 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2937 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, lsmash_form_iso_box_type
, isom_read_pasp
);
2938 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, lsmash_form_iso_box_type
, isom_read_stsl
);
2939 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLLI
, lsmash_form_qtff_box_type
, isom_read_clli
);
2940 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, lsmash_form_qtff_box_type
, isom_read_cspc
);
2941 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_MDCV
, lsmash_form_qtff_box_type
, isom_read_mdcv
);
2942 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, lsmash_form_qtff_box_type
, isom_read_fiel
);
2943 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, lsmash_form_qtff_box_type
, isom_read_gama
);
2944 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, lsmash_form_qtff_box_type
, isom_read_glbl
);
2945 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, lsmash_form_qtff_box_type
, isom_read_sgbt
);
2947 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, lsmash_form_iso_box_type
, isom_read_esds
);
2948 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, lsmash_form_iso_box_type
, isom_read_ftab
);
2949 ADD_EXTENSION_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
, NULL
);
2950 assert( sizeof(extension_reader_table
) >= (size_t)i
* sizeof(extension_reader_table
[0]) );
2951 #undef ADD_EXTENSION_READER_TABLE_ELEMENT
2953 for( int i
= 0; extension_reader_table
[i
].reader_func
; i
++ )
2954 if( box
->type
.fourcc
== extension_reader_table
[i
].fourcc
)
2956 form_box_type_func
= extension_reader_table
[i
].form_box_type_func
;
2957 reader_func
= extension_reader_table
[i
].reader_func
;
2960 reader_func
= isom_read_codec_specific
;
2963 if( form_box_type_func
)
2964 box
->type
= form_box_type_func( box
->type
.fourcc
);
2965 if( (ret
= isom_read_fullbox_common_extension( bs
, box
)) < 0 )
2968 ? reader_func( file
, box
, parent
, level
)
2969 : isom_read_unknown_box( file
, box
, parent
, level
);
2972 int isom_read_file( lsmash_file_t
*file
)
2974 lsmash_bs_t
*bs
= file
->bs
;
2976 return LSMASH_ERR_NAMELESS
;
2977 /* Reset the counter so that we can use it to get position within the box. */
2978 lsmash_bs_reset_counter( bs
);
2979 if( file
->flags
& LSMASH_FILE_MODE_DUMP
)
2981 file
->print
= isom_printer_create_list();
2983 return LSMASH_ERR_MEMORY_ALLOC
;
2985 file
->size
= UINT64_MAX
;
2987 int ret
= isom_read_children( file
, &box
, file
, 0 );
2988 file
->size
= box
.size
;
2989 lsmash_bs_empty( bs
);
2990 bs
->error
= 0; /* Clear error flag. */
2993 return isom_check_compatibility( file
);