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_cspc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1184 ADD_BOX( cspc
, isom_visual_entry_t
);
1185 lsmash_bs_t
*bs
= file
->bs
;
1186 cspc
->pixel_format
= lsmash_bs_get_be32( bs
);
1187 return isom_read_leaf_box_common_last_process( file
, box
, level
, cspc
);
1190 static int isom_read_sgbt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1192 ADD_BOX( sgbt
, isom_visual_entry_t
);
1193 lsmash_bs_t
*bs
= file
->bs
;
1194 sgbt
->significantBits
= lsmash_bs_get_byte( bs
);
1195 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgbt
);
1198 static int isom_read_stsl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1200 ADD_BOX( stsl
, isom_visual_entry_t
);
1201 lsmash_bs_t
*bs
= file
->bs
;
1202 stsl
->constraint_flag
= lsmash_bs_get_byte( bs
);
1203 stsl
->scale_method
= lsmash_bs_get_byte( bs
);
1204 stsl
->display_center_x
= lsmash_bs_get_be16( bs
);
1205 stsl
->display_center_y
= lsmash_bs_get_be16( bs
);
1206 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsl
);
1209 static int isom_read_audio_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1211 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1212 return isom_read_unknown_box( file
, box
, parent
, level
);
1213 isom_audio_entry_t
*audio
= (isom_audio_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1214 if( LSMASH_IS_NON_EXISTING_BOX( audio
) )
1215 return LSMASH_ERR_MEMORY_ALLOC
;
1216 lsmash_bs_t
*bs
= file
->bs
;
1217 for( int i
= 0; i
< 6; i
++ )
1218 audio
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1219 audio
->data_reference_index
= lsmash_bs_get_be16( bs
);
1220 audio
->version
= lsmash_bs_get_be16( bs
);
1221 audio
->revision_level
= lsmash_bs_get_be16( bs
);
1222 audio
->vendor
= lsmash_bs_get_be32( bs
);
1223 audio
->channelcount
= lsmash_bs_get_be16( bs
);
1224 audio
->samplesize
= lsmash_bs_get_be16( bs
);
1225 audio
->compression_ID
= lsmash_bs_get_be16( bs
);
1226 audio
->packet_size
= lsmash_bs_get_be16( bs
);
1227 audio
->samplerate
= lsmash_bs_get_be32( bs
);
1228 if( audio
->version
== 0 && isom_is_qt_audio( box
->type
) )
1230 /* Skip weird extra bytes.
1231 * About QTFF, extensions were first added with Sound Sample Description v1. */
1232 while( lsmash_bs_count( bs
) + ISOM_BASEBOX_COMMON_SIZE
<= box
->size
)
1234 uint32_t size
= lsmash_bs_show_be32( bs
, 0 );
1235 if( size
== 0 || lsmash_bs_count( bs
) + size
> box
->size
)
1236 lsmash_bs_skip_bytes( bs
, 1 );
1241 else if( audio
->version
== 1 )
1243 if( ((isom_stsd_t
*)parent
)->version
== 0 )
1245 audio
->samplesPerPacket
= lsmash_bs_get_be32( bs
);
1246 audio
->bytesPerPacket
= lsmash_bs_get_be32( bs
);
1247 audio
->bytesPerFrame
= lsmash_bs_get_be32( bs
);
1248 audio
->bytesPerSample
= lsmash_bs_get_be32( bs
);
1249 box
->manager
|= LSMASH_QTFF_BASE
;
1252 /* AudioSampleEntryV1 has no additional fields. */
1253 box
->manager
&= ~LSMASH_QTFF_BASE
;
1255 else if( audio
->version
== 2 )
1257 audio
->sizeOfStructOnly
= lsmash_bs_get_be32( bs
);
1258 audio
->audioSampleRate
= lsmash_bs_get_be64( bs
);
1259 audio
->numAudioChannels
= lsmash_bs_get_be32( bs
);
1260 audio
->always7F000000
= lsmash_bs_get_be32( bs
);
1261 audio
->constBitsPerChannel
= lsmash_bs_get_be32( bs
);
1262 audio
->formatSpecificFlags
= lsmash_bs_get_be32( bs
);
1263 audio
->constBytesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1264 audio
->constLPCMFramesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1265 box
->manager
|= LSMASH_QTFF_BASE
;
1267 box
->parent
= parent
;
1268 box
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1269 isom_box_common_copy( audio
, box
);
1270 int ret
= isom_add_print_func( file
, audio
, level
);
1273 return isom_read_children( file
, box
, audio
, level
);
1276 static int isom_read_wave( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1278 ADD_BOX( wave
, isom_audio_entry_t
);
1279 isom_box_common_copy( wave
, box
);
1280 int ret
= isom_add_print_func( file
, wave
, level
);
1283 return isom_read_children( file
, box
, wave
, level
);
1286 static int isom_read_frma( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1288 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1289 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->frma
) )
1290 return isom_read_unknown_box( file
, box
, parent
, level
);
1291 ADD_BOX( frma
, isom_wave_t
);
1292 lsmash_bs_t
*bs
= file
->bs
;
1293 frma
->data_format
= lsmash_bs_get_be32( bs
);
1294 return isom_read_leaf_box_common_last_process( file
, box
, level
, frma
);
1297 static int isom_read_enda( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1299 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1300 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->enda
) )
1301 return isom_read_unknown_box( file
, box
, parent
, level
);
1302 ADD_BOX( enda
, isom_wave_t
);
1303 lsmash_bs_t
*bs
= file
->bs
;
1304 enda
->littleEndian
= lsmash_bs_get_be16( bs
);
1305 return isom_read_leaf_box_common_last_process( file
, box
, level
, enda
);
1308 static int isom_read_terminator( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1310 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
)
1311 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t
*)parent
)->terminator
) )
1312 return isom_read_unknown_box( file
, box
, parent
, level
);
1313 ADD_BOX( terminator
, isom_wave_t
);
1314 return isom_read_leaf_box_common_last_process( file
, box
, level
, terminator
);
1317 static int isom_read_chan( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1319 ADD_BOX( chan
, isom_audio_entry_t
);
1320 lsmash_bs_t
*bs
= file
->bs
;
1321 chan
->channelLayoutTag
= lsmash_bs_get_be32( bs
);
1322 chan
->channelBitmap
= lsmash_bs_get_be32( bs
);
1323 chan
->numberChannelDescriptions
= lsmash_bs_get_be32( bs
);
1324 if( chan
->numberChannelDescriptions
)
1326 isom_channel_description_t
*desc
= lsmash_malloc( chan
->numberChannelDescriptions
* sizeof(isom_channel_description_t
) );
1328 return LSMASH_ERR_MEMORY_ALLOC
;
1329 chan
->channelDescriptions
= desc
;
1330 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
1332 desc
->channelLabel
= lsmash_bs_get_be32( bs
);
1333 desc
->channelFlags
= lsmash_bs_get_be32( bs
);
1334 for( int j
= 0; j
< 3; j
++ )
1335 desc
->coordinates
[j
] = lsmash_bs_get_be32( bs
);
1338 return isom_read_leaf_box_common_last_process( file
, box
, level
, chan
);
1341 static int isom_read_srat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1343 ADD_BOX( srat
, isom_audio_entry_t
);
1344 lsmash_bs_t
*bs
= file
->bs
;
1345 srat
->sampling_rate
= lsmash_bs_get_be32( bs
);
1346 return isom_read_leaf_box_common_last_process( file
, box
, level
, srat
);
1349 static int isom_read_qt_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1351 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1352 return isom_read_unknown_box( file
, box
, parent
, level
);
1353 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1354 if( LSMASH_IS_NON_EXISTING_BOX( text
) )
1355 return LSMASH_ERR_MEMORY_ALLOC
;
1356 lsmash_bs_t
*bs
= file
->bs
;
1357 for( int i
= 0; i
< 6; i
++ )
1358 text
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1359 text
->data_reference_index
= lsmash_bs_get_be16( bs
);
1360 text
->displayFlags
= lsmash_bs_get_be32( bs
);
1361 text
->textJustification
= lsmash_bs_get_be32( bs
);
1362 for( int i
= 0; i
< 3; i
++ )
1363 text
->bgColor
[i
] = lsmash_bs_get_be16( bs
);
1364 text
->top
= lsmash_bs_get_be16( bs
);
1365 text
->left
= lsmash_bs_get_be16( bs
);
1366 text
->bottom
= lsmash_bs_get_be16( bs
);
1367 text
->right
= lsmash_bs_get_be16( bs
);
1368 text
->scrpStartChar
= lsmash_bs_get_be32( bs
);
1369 text
->scrpHeight
= lsmash_bs_get_be16( bs
);
1370 text
->scrpAscent
= lsmash_bs_get_be16( bs
);
1371 text
->scrpFont
= lsmash_bs_get_be16( bs
);
1372 text
->scrpFace
= lsmash_bs_get_be16( bs
);
1373 text
->scrpSize
= lsmash_bs_get_be16( bs
);
1374 for( int i
= 0; i
< 3; i
++ )
1375 text
->scrpColor
[i
] = lsmash_bs_get_be16( bs
);
1376 text
->font_name_length
= lsmash_bs_get_byte( bs
);
1377 if( text
->font_name_length
)
1379 text
->font_name
= lsmash_malloc( text
->font_name_length
+ 1 );
1380 if( !text
->font_name
)
1381 return LSMASH_ERR_MEMORY_ALLOC
;
1382 for( uint8_t i
= 0; i
< text
->font_name_length
; i
++ )
1383 text
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1384 text
->font_name
[text
->font_name_length
] = '\0';
1386 box
->parent
= parent
;
1387 isom_box_common_copy( text
, box
);
1388 int ret
= isom_add_print_func( file
, text
, level
);
1391 return isom_read_children( file
, box
, text
, level
);
1394 static int isom_read_tx3g_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1396 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1397 return isom_read_unknown_box( file
, box
, parent
, level
);
1398 isom_tx3g_entry_t
*tx3g
= (isom_tx3g_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1399 if( LSMASH_IS_NON_EXISTING_BOX( tx3g
) )
1400 return LSMASH_ERR_MEMORY_ALLOC
;
1401 lsmash_bs_t
*bs
= file
->bs
;
1402 for( int i
= 0; i
< 6; i
++ )
1403 tx3g
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1404 tx3g
->data_reference_index
= lsmash_bs_get_be16( bs
);
1405 tx3g
->displayFlags
= lsmash_bs_get_be32( bs
);
1406 tx3g
->horizontal_justification
= lsmash_bs_get_byte( bs
);
1407 tx3g
->vertical_justification
= lsmash_bs_get_byte( bs
);
1408 for( int i
= 0; i
< 4; i
++ )
1409 tx3g
->background_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1410 tx3g
->top
= lsmash_bs_get_be16( bs
);
1411 tx3g
->left
= lsmash_bs_get_be16( bs
);
1412 tx3g
->bottom
= lsmash_bs_get_be16( bs
);
1413 tx3g
->right
= lsmash_bs_get_be16( bs
);
1414 tx3g
->startChar
= lsmash_bs_get_be16( bs
);
1415 tx3g
->endChar
= lsmash_bs_get_be16( bs
);
1416 tx3g
->font_ID
= lsmash_bs_get_be16( bs
);
1417 tx3g
->face_style_flags
= lsmash_bs_get_byte( bs
);
1418 tx3g
->font_size
= lsmash_bs_get_byte( bs
);
1419 for( int i
= 0; i
< 4; i
++ )
1420 tx3g
->text_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1421 box
->parent
= parent
;
1422 isom_box_common_copy( tx3g
, box
);
1423 int ret
= isom_add_print_func( file
, tx3g
, level
);
1426 return isom_read_children( file
, box
, tx3g
, level
);
1429 static int isom_read_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1431 if( lsmash_check_codec_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1432 return isom_read_qt_text_description( file
, box
, parent
, level
);
1433 else if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1434 return isom_read_tx3g_description( file
, box
, parent
, level
);
1436 return isom_read_unknown_box( file
, box
, parent
, level
);
1439 static int isom_read_ftab( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1441 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
)
1442 || LSMASH_IS_EXISTING_BOX( ((isom_tx3g_entry_t
*)parent
)->ftab
) )
1443 return isom_read_codec_specific( file
, box
, parent
, level
);
1444 ADD_BOX( ftab
, isom_tx3g_entry_t
);
1445 lsmash_bs_t
*bs
= file
->bs
;
1446 uint32_t entry_count
= lsmash_bs_get_be16( bs
);
1447 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ftab
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1449 isom_font_record_t
*data
= lsmash_malloc_zero( sizeof(isom_font_record_t
) );
1451 return LSMASH_ERR_MEMORY_ALLOC
;
1452 if( lsmash_list_add_entry( ftab
->list
, data
) < 0 )
1454 lsmash_free( data
);
1455 return LSMASH_ERR_MEMORY_ALLOC
;
1457 data
->font_ID
= lsmash_bs_get_be16( bs
);
1458 data
->font_name_length
= lsmash_bs_get_byte( bs
);
1459 if( data
->font_name_length
)
1461 data
->font_name
= lsmash_malloc( data
->font_name_length
+ 1 );
1462 if( !data
->font_name
)
1463 return LSMASH_ERR_MEMORY_ALLOC
;
1464 for( uint8_t i
= 0; i
< data
->font_name_length
; i
++ )
1465 data
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1466 data
->font_name
[data
->font_name_length
] = '\0';
1469 return isom_read_leaf_box_common_last_process( file
, box
, level
, ftab
);
1472 static int isom_read_mp4s_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1474 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1475 return isom_read_unknown_box( file
, box
, parent
, level
);
1476 isom_mp4s_entry_t
*mp4s
= (isom_mp4s_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1477 if( LSMASH_IS_NON_EXISTING_BOX( mp4s
) )
1478 return LSMASH_ERR_MEMORY_ALLOC
;
1479 lsmash_bs_t
*bs
= file
->bs
;
1480 for( int i
= 0; i
< 6; i
++ )
1481 mp4s
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1482 mp4s
->data_reference_index
= lsmash_bs_get_be16( bs
);
1483 box
->parent
= parent
;
1484 isom_box_common_copy( mp4s
, box
);
1485 int ret
= isom_add_print_func( file
, mp4s
, level
);
1488 return isom_read_children( file
, box
, mp4s
, level
);
1491 static int isom_read_other_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1493 if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
) )
1494 return isom_read_mp4s_description( file
, box
, parent
, level
);
1495 return isom_read_unknown_box( file
, box
, parent
, level
);
1498 static int isom_read_stts( 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_STBL
)
1501 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stts
) )
1502 return isom_read_unknown_box( file
, box
, parent
, level
);
1503 ADD_BOX( stts
, isom_stbl_t
);
1504 lsmash_bs_t
*bs
= file
->bs
;
1505 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1506 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1508 isom_stts_entry_t
*data
= lsmash_malloc( sizeof(isom_stts_entry_t
) );
1510 return LSMASH_ERR_MEMORY_ALLOC
;
1511 if( lsmash_list_add_entry( stts
->list
, data
) < 0 )
1513 lsmash_free( data
);
1514 return LSMASH_ERR_MEMORY_ALLOC
;
1516 data
->sample_count
= lsmash_bs_get_be32( bs
);
1517 data
->sample_delta
= lsmash_bs_get_be32( bs
);
1519 return isom_read_leaf_box_common_last_process( file
, box
, level
, stts
);
1522 static int isom_read_ctts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1524 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1525 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->ctts
) )
1526 return isom_read_unknown_box( file
, box
, parent
, level
);
1527 ADD_BOX( ctts
, isom_stbl_t
);
1528 lsmash_bs_t
*bs
= file
->bs
;
1529 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1530 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ctts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1532 isom_ctts_entry_t
*data
= lsmash_malloc( sizeof(isom_ctts_entry_t
) );
1534 return LSMASH_ERR_MEMORY_ALLOC
;
1535 if( lsmash_list_add_entry( ctts
->list
, data
) < 0 )
1537 lsmash_free( data
);
1538 return LSMASH_ERR_MEMORY_ALLOC
;
1540 data
->sample_count
= lsmash_bs_get_be32( bs
);
1541 data
->sample_offset
= lsmash_bs_get_be32( bs
);
1543 return isom_read_leaf_box_common_last_process( file
, box
, level
, ctts
);
1546 static int isom_read_cslg( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1548 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1549 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->cslg
) )
1550 return isom_read_unknown_box( file
, box
, parent
, level
);
1551 ADD_BOX( cslg
, isom_stbl_t
);
1552 lsmash_bs_t
*bs
= file
->bs
;
1553 cslg
->compositionToDTSShift
= lsmash_bs_get_be32( bs
);
1554 cslg
->leastDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1555 cslg
->greatestDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1556 cslg
->compositionStartTime
= lsmash_bs_get_be32( bs
);
1557 cslg
->compositionEndTime
= lsmash_bs_get_be32( bs
);
1558 return isom_read_leaf_box_common_last_process( file
, box
, level
, cslg
);
1561 static int isom_read_stss( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1563 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1564 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stss
) )
1565 return isom_read_unknown_box( file
, box
, parent
, level
);
1566 ADD_BOX( stss
, isom_stbl_t
);
1567 lsmash_bs_t
*bs
= file
->bs
;
1568 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1569 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stss
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1571 isom_stss_entry_t
*data
= lsmash_malloc( sizeof(isom_stss_entry_t
) );
1573 return LSMASH_ERR_MEMORY_ALLOC
;
1574 if( lsmash_list_add_entry( stss
->list
, data
) < 0 )
1576 lsmash_free( data
);
1577 return LSMASH_ERR_MEMORY_ALLOC
;
1579 data
->sample_number
= lsmash_bs_get_be32( bs
);
1581 return isom_read_leaf_box_common_last_process( file
, box
, level
, stss
);
1584 static int isom_read_stps( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1586 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1587 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stps
) )
1588 return isom_read_unknown_box( file
, box
, parent
, level
);
1589 ADD_BOX( stps
, isom_stbl_t
);
1590 lsmash_bs_t
*bs
= file
->bs
;
1591 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1592 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stps
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1594 isom_stps_entry_t
*data
= lsmash_malloc( sizeof(isom_stps_entry_t
) );
1596 return LSMASH_ERR_MEMORY_ALLOC
;
1597 if( lsmash_list_add_entry( stps
->list
, data
) < 0 )
1599 lsmash_free( data
);
1600 return LSMASH_ERR_MEMORY_ALLOC
;
1602 data
->sample_number
= lsmash_bs_get_be32( bs
);
1604 return isom_read_leaf_box_common_last_process( file
, box
, level
, stps
);
1607 static int isom_read_sdtp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1609 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1610 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
))
1611 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) && LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->sdtp
))
1612 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) && LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->sdtp
)) )
1613 return isom_read_unknown_box( file
, box
, parent
, level
);
1614 ADD_BOX( sdtp
, isom_box_t
);
1615 lsmash_bs_t
*bs
= file
->bs
;
1616 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
; pos
= lsmash_bs_count( bs
) )
1618 isom_sdtp_entry_t
*data
= lsmash_malloc( sizeof(isom_sdtp_entry_t
) );
1620 return LSMASH_ERR_MEMORY_ALLOC
;
1621 if( lsmash_list_add_entry( sdtp
->list
, data
) < 0 )
1623 lsmash_free( data
);
1624 return LSMASH_ERR_MEMORY_ALLOC
;
1626 uint8_t temp
= lsmash_bs_get_byte( bs
);
1627 data
->is_leading
= (temp
>> 6) & 0x3;
1628 data
->sample_depends_on
= (temp
>> 4) & 0x3;
1629 data
->sample_is_depended_on
= (temp
>> 2) & 0x3;
1630 data
->sample_has_redundancy
= temp
& 0x3;
1632 return isom_read_leaf_box_common_last_process( file
, box
, level
, sdtp
);
1635 static int isom_read_stsc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1637 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1638 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stsc
) )
1639 return isom_read_unknown_box( file
, box
, parent
, level
);
1640 ADD_BOX( stsc
, isom_stbl_t
);
1641 lsmash_bs_t
*bs
= file
->bs
;
1642 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1643 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stsc
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1645 isom_stsc_entry_t
*data
= lsmash_malloc( sizeof(isom_stsc_entry_t
) );
1647 return LSMASH_ERR_MEMORY_ALLOC
;
1648 if( lsmash_list_add_entry( stsc
->list
, data
) < 0 )
1650 lsmash_free( data
);
1651 return LSMASH_ERR_MEMORY_ALLOC
;
1653 data
->first_chunk
= lsmash_bs_get_be32( bs
);
1654 data
->samples_per_chunk
= lsmash_bs_get_be32( bs
);
1655 data
->sample_description_index
= lsmash_bs_get_be32( bs
);
1657 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsc
);
1660 static int isom_read_stsz( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1662 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1663 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stsz
) )
1664 return isom_read_unknown_box( file
, box
, parent
, level
);
1665 ADD_BOX( stsz
, isom_stbl_t
);
1666 lsmash_bs_t
*bs
= file
->bs
;
1667 stsz
->sample_size
= lsmash_bs_get_be32( bs
);
1668 stsz
->sample_count
= lsmash_bs_get_be32( bs
);
1669 uint64_t pos
= lsmash_bs_count( bs
);
1670 if( pos
< box
->size
)
1672 stsz
->list
= lsmash_list_create_simple();
1674 return LSMASH_ERR_MEMORY_ALLOC
;
1675 for( ; pos
< box
->size
&& stsz
->list
->entry_count
< stsz
->sample_count
; pos
= lsmash_bs_count( bs
) )
1677 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1679 return LSMASH_ERR_MEMORY_ALLOC
;
1680 if( lsmash_list_add_entry( stsz
->list
, data
) < 0 )
1682 lsmash_free( data
);
1683 return LSMASH_ERR_MEMORY_ALLOC
;
1685 data
->entry_size
= lsmash_bs_get_be32( bs
);
1688 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsz
);
1691 static int isom_read_stz2( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1693 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1694 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stz2
) )
1695 return isom_read_unknown_box( file
, box
, parent
, level
);
1696 ADD_BOX( stz2
, isom_stbl_t
);
1697 lsmash_bs_t
*bs
= file
->bs
;
1698 uint32_t temp32
= lsmash_bs_get_be32( bs
);
1699 stz2
->reserved
= temp32
>> 24;
1700 stz2
->field_size
= temp32
& 0xff;
1701 stz2
->sample_count
= lsmash_bs_get_be32( bs
);
1702 uint64_t pos
= lsmash_bs_count( bs
);
1703 if( pos
< box
->size
)
1705 if( stz2
->field_size
== 16 || stz2
->field_size
== 8 )
1707 uint64_t (*bs_get_funcs
[2])( lsmash_bs_t
* ) =
1709 lsmash_bs_get_byte_to_64
,
1710 lsmash_bs_get_be16_to_64
1712 uint64_t (*bs_get_entry_size
)( lsmash_bs_t
* ) = bs_get_funcs
[ stz2
->field_size
== 16 ? 1 : 0 ];
1713 for( ; pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
; pos
= lsmash_bs_count( bs
) )
1715 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1717 return LSMASH_ERR_MEMORY_ALLOC
;
1718 if( lsmash_list_add_entry( stz2
->list
, data
) < 0 )
1720 lsmash_free( data
);
1721 return LSMASH_ERR_MEMORY_ALLOC
;
1723 data
->entry_size
= bs_get_entry_size( bs
);
1726 else if( stz2
->field_size
== 4 )
1730 while( pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
)
1732 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1734 return LSMASH_ERR_MEMORY_ALLOC
;
1735 if( lsmash_list_add_entry( stz2
->list
, data
) < 0 )
1737 lsmash_free( data
);
1738 return LSMASH_ERR_MEMORY_ALLOC
;
1740 /* Read a byte by two entries. */
1743 temp8
= lsmash_bs_get_byte( bs
);
1744 data
->entry_size
= (temp8
>> 4) & 0xf;
1748 pos
= lsmash_bs_count( bs
);
1749 data
->entry_size
= temp8
& 0xf;
1755 return LSMASH_ERR_INVALID_DATA
;
1757 return isom_read_leaf_box_common_last_process( file
, box
, level
, stz2
);
1760 static int isom_read_stco( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1762 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1763 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t
*)parent
)->stco
) )
1764 return isom_read_unknown_box( file
, box
, parent
, level
);
1765 box
->type
= lsmash_form_iso_box_type( box
->type
.fourcc
);
1766 int is_stco
= lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_STCO
);
1767 isom_stco_t
*stco
= is_stco
1768 ? isom_add_stco( (isom_stbl_t
*)parent
)
1769 : isom_add_co64( (isom_stbl_t
*)parent
);
1771 return LSMASH_ERR_NAMELESS
;
1772 lsmash_bs_t
*bs
= file
->bs
;
1773 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1775 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1777 isom_stco_entry_t
*data
= lsmash_malloc( sizeof(isom_stco_entry_t
) );
1779 return LSMASH_ERR_MEMORY_ALLOC
;
1780 if( lsmash_list_add_entry( stco
->list
, data
) < 0 )
1782 lsmash_free( data
);
1783 return LSMASH_ERR_MEMORY_ALLOC
;
1785 data
->chunk_offset
= lsmash_bs_get_be32( bs
);
1789 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1791 isom_co64_entry_t
*data
= lsmash_malloc( sizeof(isom_co64_entry_t
) );
1793 return LSMASH_ERR_MEMORY_ALLOC
;
1794 if( lsmash_list_add_entry( stco
->list
, data
) < 0 )
1796 lsmash_free( data
);
1797 return LSMASH_ERR_MEMORY_ALLOC
;
1799 data
->chunk_offset
= lsmash_bs_get_be64( bs
);
1802 return isom_read_leaf_box_common_last_process( file
, box
, level
, stco
);
1805 static int isom_read_sgpd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1807 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1808 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1809 return isom_read_unknown_box( file
, box
, parent
, level
);
1810 ADD_BOX( sgpd
, void );
1811 lsmash_bs_t
*bs
= file
->bs
;
1812 sgpd
->grouping_type
= lsmash_bs_get_be32( bs
);
1813 if( box
->version
== 1 )
1814 sgpd
->default_length
= lsmash_bs_get_be32( bs
);
1815 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1816 switch( sgpd
->grouping_type
)
1818 case ISOM_GROUP_TYPE_RAP
:
1820 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sgpd
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1822 isom_rap_entry_t
*data
= lsmash_malloc( sizeof(isom_rap_entry_t
) );
1824 return LSMASH_ERR_MEMORY_ALLOC
;
1825 if( lsmash_list_add_entry( sgpd
->list
, data
) < 0 )
1827 lsmash_free( data
);
1828 return LSMASH_ERR_MEMORY_ALLOC
;
1830 memset( data
, 0, sizeof(isom_rap_entry_t
) );
1831 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1832 if( box
->version
== 1 && !sgpd
->default_length
)
1833 data
->description_length
= lsmash_bs_get_be32( bs
);
1836 uint8_t temp
= lsmash_bs_get_byte( bs
);
1837 data
->num_leading_samples_known
= (temp
>> 7) & 0x01;
1838 data
->num_leading_samples
= temp
& 0x7f;
1843 case ISOM_GROUP_TYPE_ROLL
:
1844 case ISOM_GROUP_TYPE_PROL
:
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_roll_entry_t
*data
= lsmash_malloc( sizeof(isom_roll_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_roll_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
);
1861 data
->roll_distance
= lsmash_bs_get_be16( bs
);
1868 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgpd
);
1871 static int isom_read_sbgp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1873 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1874 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1875 return isom_read_unknown_box( file
, box
, parent
, level
);
1876 ADD_BOX( sbgp
, void );
1877 lsmash_bs_t
*bs
= file
->bs
;
1878 sbgp
->grouping_type
= lsmash_bs_get_be32( bs
);
1879 if( box
->version
== 1 )
1880 sbgp
->grouping_type_parameter
= lsmash_bs_get_be32( bs
);
1881 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1882 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sbgp
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1884 isom_group_assignment_entry_t
*data
= lsmash_malloc( sizeof(isom_group_assignment_entry_t
) );
1886 return LSMASH_ERR_MEMORY_ALLOC
;
1887 if( lsmash_list_add_entry( sbgp
->list
, data
) < 0 )
1889 lsmash_free( data
);
1890 return LSMASH_ERR_MEMORY_ALLOC
;
1892 data
->sample_count
= lsmash_bs_get_be32( bs
);
1893 data
->group_description_index
= lsmash_bs_get_be32( bs
);
1895 return isom_read_leaf_box_common_last_process( file
, box
, level
,sbgp
);
1898 static int isom_read_udta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1900 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
1901 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
))
1902 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->udta
))
1903 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->udta
)) )
1904 return isom_read_unknown_box( file
, box
, parent
, level
);
1905 ADD_BOX( udta
, void );
1906 isom_box_common_copy( udta
, box
);
1907 int ret
= isom_add_print_func( file
, udta
, level
);
1910 return isom_read_children( file
, box
, udta
, level
);
1913 static int isom_read_chpl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1915 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
1916 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->chpl
) )
1917 return isom_read_unknown_box( file
, box
, parent
, level
);
1918 ADD_BOX( chpl
, isom_udta_t
);
1919 lsmash_bs_t
*bs
= file
->bs
;
1920 uint32_t entry_count
;
1921 if( box
->version
== 1 )
1923 chpl
->unknown
= lsmash_bs_get_byte( bs
);
1924 entry_count
= lsmash_bs_get_be32( bs
);
1927 entry_count
= lsmash_bs_get_byte( bs
);
1928 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& chpl
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1930 isom_chpl_entry_t
*data
= lsmash_malloc( sizeof(isom_chpl_entry_t
) );
1932 return LSMASH_ERR_MEMORY_ALLOC
;
1933 if( lsmash_list_add_entry( chpl
->list
, data
) < 0 )
1935 lsmash_free( data
);
1936 return LSMASH_ERR_MEMORY_ALLOC
;
1938 data
->start_time
= lsmash_bs_get_be64( bs
);
1939 data
->chapter_name_length
= lsmash_bs_get_byte( bs
);
1940 data
->chapter_name
= lsmash_malloc( data
->chapter_name_length
+ 1 );
1941 if( !data
->chapter_name
)
1943 lsmash_free( data
);
1944 return LSMASH_ERR_MEMORY_ALLOC
;
1946 for( uint8_t i
= 0; i
< data
->chapter_name_length
; i
++ )
1947 data
->chapter_name
[i
] = lsmash_bs_get_byte( bs
);
1948 data
->chapter_name
[data
->chapter_name_length
] = '\0';
1950 return isom_read_leaf_box_common_last_process( file
, box
, level
, chpl
);
1953 static int isom_read_mvex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1955 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
1956 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->mvex
) )
1957 return isom_read_unknown_box( file
, box
, parent
, level
);
1958 ADD_BOX( mvex
, isom_moov_t
);
1959 file
->flags
|= LSMASH_FILE_MODE_FRAGMENTED
;
1960 isom_box_common_copy( mvex
, box
);
1961 int ret
= isom_add_print_func( file
, mvex
, level
);
1964 return isom_read_children( file
, box
, mvex
, level
);
1967 static int isom_read_mehd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1969 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
)
1970 || LSMASH_IS_EXISTING_BOX( ((isom_mvex_t
*)parent
)->mehd
) )
1971 return isom_read_unknown_box( file
, box
, parent
, level
);
1972 ADD_BOX( mehd
, isom_mvex_t
);
1973 lsmash_bs_t
*bs
= file
->bs
;
1974 if( box
->version
== 1 )
1975 mehd
->fragment_duration
= lsmash_bs_get_be64( bs
);
1977 mehd
->fragment_duration
= lsmash_bs_get_be32( bs
);
1978 return isom_read_leaf_box_common_last_process( file
, box
, level
, mehd
);
1981 static isom_sample_flags_t
isom_bs_get_sample_flags( lsmash_bs_t
*bs
)
1983 uint32_t temp
= lsmash_bs_get_be32( bs
);
1984 isom_sample_flags_t flags
;
1985 flags
.reserved
= (temp
>> 28) & 0xf;
1986 flags
.is_leading
= (temp
>> 26) & 0x3;
1987 flags
.sample_depends_on
= (temp
>> 24) & 0x3;
1988 flags
.sample_is_depended_on
= (temp
>> 22) & 0x3;
1989 flags
.sample_has_redundancy
= (temp
>> 20) & 0x3;
1990 flags
.sample_padding_value
= (temp
>> 17) & 0x7;
1991 flags
.sample_is_non_sync_sample
= (temp
>> 16) & 0x1;
1992 flags
.sample_degradation_priority
= temp
& 0xffff;
1996 static int isom_read_trex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1998 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
) )
1999 return isom_read_unknown_box( file
, box
, parent
, level
);
2000 ADD_BOX( trex
, isom_mvex_t
);
2001 box
->parent
= parent
;
2002 lsmash_bs_t
*bs
= file
->bs
;
2003 trex
->track_ID
= lsmash_bs_get_be32( bs
);
2004 trex
->default_sample_description_index
= lsmash_bs_get_be32( bs
);
2005 trex
->default_sample_duration
= lsmash_bs_get_be32( bs
);
2006 trex
->default_sample_size
= lsmash_bs_get_be32( bs
);
2007 trex
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
2008 return isom_read_leaf_box_common_last_process( file
, box
, level
, trex
);
2011 static int isom_read_moof( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2013 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
2014 return isom_read_unknown_box( file
, box
, parent
, level
);
2015 ADD_BOX( moof
, lsmash_file_t
);
2016 box
->parent
= parent
;
2017 isom_box_common_copy( moof
, box
);
2018 int ret
= isom_add_print_func( file
, moof
, level
);
2021 return isom_read_children( file
, box
, moof
, level
);
2024 static int isom_read_mfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2026 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
)
2027 || LSMASH_IS_EXISTING_BOX( ((isom_moof_t
*)parent
)->mfhd
) )
2028 return isom_read_unknown_box( file
, box
, parent
, level
);
2029 ADD_BOX( mfhd
, isom_moof_t
);
2030 lsmash_bs_t
*bs
= file
->bs
;
2031 mfhd
->sequence_number
= lsmash_bs_get_be32( bs
);
2032 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfhd
);
2035 static int isom_read_traf( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2037 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
) )
2038 return isom_read_unknown_box( file
, box
, parent
, level
);
2039 ADD_BOX( traf
, isom_moof_t
);
2040 box
->parent
= parent
;
2041 isom_box_common_copy( traf
, box
);
2042 int ret
= isom_add_print_func( file
, traf
, level
);
2045 return isom_read_children( file
, box
, traf
, level
);
2048 static int isom_read_tfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2050 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
)
2051 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->tfhd
) )
2052 return isom_read_unknown_box( file
, box
, parent
, level
);
2053 ADD_BOX( tfhd
, isom_traf_t
);
2054 lsmash_bs_t
*bs
= file
->bs
;
2055 tfhd
->track_ID
= lsmash_bs_get_be32( bs
);
2056 if( box
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) tfhd
->base_data_offset
= lsmash_bs_get_be64( bs
);
2057 if( box
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) tfhd
->sample_description_index
= lsmash_bs_get_be32( bs
);
2058 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) tfhd
->default_sample_duration
= lsmash_bs_get_be32( bs
);
2059 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) tfhd
->default_sample_size
= lsmash_bs_get_be32( bs
);
2060 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) tfhd
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
2061 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfhd
);
2064 static int isom_read_tfdt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2066 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
)
2067 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t
*)parent
)->tfdt
) )
2068 return isom_read_unknown_box( file
, box
, parent
, level
);
2069 ADD_BOX( tfdt
, isom_traf_t
);
2070 lsmash_bs_t
*bs
= file
->bs
;
2071 if( box
->version
== 1 )
2072 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be64( bs
);
2074 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be32( bs
);
2075 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfdt
);
2078 static int isom_read_trun( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2080 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
2081 return isom_read_unknown_box( file
, box
, parent
, level
);
2082 ADD_BOX( trun
, isom_traf_t
);
2083 box
->parent
= parent
;
2084 lsmash_bs_t
*bs
= file
->bs
;
2085 int has_optional_rows
= ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2086 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2087 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2088 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
;
2089 has_optional_rows
&= box
->flags
;
2090 trun
->sample_count
= lsmash_bs_get_be32( bs
);
2091 if( box
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) trun
->data_offset
= lsmash_bs_get_be32( bs
);
2092 if( box
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) trun
->first_sample_flags
= isom_bs_get_sample_flags( bs
);
2093 if( trun
->sample_count
&& has_optional_rows
)
2095 trun
->optional
= lsmash_list_create_simple();
2096 if( !trun
->optional
)
2097 return LSMASH_ERR_MEMORY_ALLOC
;
2098 for( uint32_t i
= 0; i
< trun
->sample_count
; i
++ )
2100 isom_trun_optional_row_t
*data
= lsmash_malloc( sizeof(isom_trun_optional_row_t
) );
2102 return LSMASH_ERR_MEMORY_ALLOC
;
2103 if( lsmash_list_add_entry( trun
->optional
, data
) < 0 )
2105 lsmash_free( data
);
2106 return LSMASH_ERR_MEMORY_ALLOC
;
2108 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) data
->sample_duration
= lsmash_bs_get_be32( bs
);
2109 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) data
->sample_size
= lsmash_bs_get_be32( bs
);
2110 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) data
->sample_flags
= isom_bs_get_sample_flags( bs
);
2111 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) data
->sample_composition_time_offset
= lsmash_bs_get_be32( bs
);
2114 return isom_read_leaf_box_common_last_process( file
, box
, level
, trun
);
2117 static int isom_read_free( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2119 if( file
->fake_file_mode
)
2120 return isom_read_unknown_box( file
, box
, parent
, level
);
2121 isom_skip_t
*skip
= ALLOCATE_BOX( skip
);
2122 if( LSMASH_IS_NON_EXISTING_BOX( skip
) )
2123 return LSMASH_ERR_MEMORY_ALLOC
;
2124 isom_skip_box_rest( file
->bs
, box
);
2125 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2126 isom_box_common_copy( skip
, box
);
2127 int ret
= isom_add_print_func( file
, skip
, level
);
2130 isom_remove_box_by_itself( skip
);
2136 static int isom_read_mdat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2138 if( file
->fake_file_mode
|| !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
2139 return isom_read_unknown_box( file
, box
, parent
, level
);
2140 isom_mdat_t
*mdat
= ALLOCATE_BOX( mdat
);
2141 if( LSMASH_IS_NON_EXISTING_BOX( mdat
) )
2142 return LSMASH_ERR_MEMORY_ALLOC
;
2143 isom_skip_box_rest( file
->bs
, box
);
2144 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2145 file
->flags
|= LSMASH_FILE_MODE_MEDIA
;
2146 isom_box_common_copy( mdat
, box
);
2147 int ret
= isom_add_print_func( file
, mdat
, level
);
2150 isom_remove_box_by_itself( mdat
);
2156 static int isom_read_meta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2158 if( (!lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
2159 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
2160 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
2161 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
))
2162 || (lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) && LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->meta
))
2163 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t
*)parent
)->meta
))
2164 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t
*)parent
)->meta
))
2165 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) && LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->meta
)) )
2166 return isom_read_unknown_box( file
, box
, parent
, level
);
2167 ADD_BOX( meta
, void );
2168 isom_box_common_copy( meta
, box
);
2169 int is_qtff
= lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_META
);
2172 box
->manager
|= LSMASH_QTFF_BASE
;
2173 meta
->manager
|= LSMASH_QTFF_BASE
;
2175 int ret
= isom_add_print_func( file
, meta
, level
);
2178 return isom_read_children( file
, box
, meta
, level
);
2181 static int isom_read_keys( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2183 if( (!lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) && !(parent
->manager
& LSMASH_QTFF_BASE
))
2184 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->keys
) )
2185 return isom_read_unknown_box( file
, box
, parent
, level
);
2186 ADD_BOX( keys
, isom_meta_t
);
2187 lsmash_bs_t
*bs
= file
->bs
;
2188 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
2189 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& keys
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
2191 isom_keys_entry_t
*data
= lsmash_malloc( sizeof(isom_keys_entry_t
) );
2193 return LSMASH_ERR_MEMORY_ALLOC
;
2194 if( lsmash_list_add_entry( keys
->list
, data
) < 0 )
2196 lsmash_free( data
);
2197 return LSMASH_ERR_MEMORY_ALLOC
;
2199 data
->key_size
= lsmash_bs_get_be32( bs
);
2200 data
->key_namespace
= lsmash_bs_get_be32( bs
);
2201 if( data
->key_size
> 8 )
2203 data
->key_value
= lsmash_bs_get_bytes( bs
, data
->key_size
- 8 );
2204 if( !data
->key_value
)
2205 return LSMASH_ERR_NAMELESS
;
2208 data
->key_value
= NULL
;
2210 return isom_read_leaf_box_common_last_process( file
, box
, level
, keys
);
2213 static int isom_read_ilst( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2215 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
2216 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
))
2217 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t
*)parent
)->ilst
) )
2218 return isom_read_unknown_box( file
, box
, parent
, level
);
2219 ADD_BOX( ilst
, isom_meta_t
);
2220 isom_box_common_copy( ilst
, box
);
2221 int ret
= isom_add_print_func( file
, ilst
, level
);
2224 return isom_read_children( file
, box
, ilst
, level
);
2227 static int isom_read_metaitem( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2229 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
2230 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2231 return isom_read_unknown_box( file
, box
, parent
, level
);
2232 isom_metaitem_t
*metaitem
= isom_add_metaitem( (isom_ilst_t
*)parent
, box
->type
.fourcc
);
2235 box
->parent
= parent
;
2236 isom_box_common_copy( metaitem
, box
);
2237 int ret
= isom_add_print_func( file
, metaitem
, level
);
2240 return isom_read_children( file
, box
, metaitem
, level
);
2243 static int isom_read_mean( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2245 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
2246 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->mean
) )
2247 return isom_read_unknown_box( file
, box
, parent
, level
);
2248 ADD_BOX( mean
, isom_metaitem_t
);
2249 lsmash_bs_t
*bs
= file
->bs
;
2250 mean
->meaning_string_length
= box
->size
- lsmash_bs_count( bs
);
2251 mean
->meaning_string
= lsmash_bs_get_bytes( bs
, mean
->meaning_string_length
);
2252 if( !mean
->meaning_string
)
2253 return LSMASH_ERR_NAMELESS
;
2254 return isom_read_leaf_box_common_last_process( file
, box
, level
, mean
);
2257 static int isom_read_name( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2259 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
2260 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->name
) )
2261 return isom_read_unknown_box( file
, box
, parent
, level
);
2262 ADD_BOX( name
, isom_metaitem_t
);
2263 lsmash_bs_t
*bs
= file
->bs
;
2264 name
->name_length
= box
->size
- lsmash_bs_count( bs
);
2265 name
->name
= lsmash_bs_get_bytes( bs
, name
->name_length
);
2267 return LSMASH_ERR_NAMELESS
;
2268 return isom_read_leaf_box_common_last_process( file
, box
, level
, name
);
2271 static int isom_read_data( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2273 if( LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t
*)parent
)->data
) )
2274 return isom_read_unknown_box( file
, box
, parent
, level
);
2275 ADD_BOX( data
, isom_metaitem_t
);
2276 lsmash_bs_t
*bs
= file
->bs
;
2277 data
->value_length
= box
->size
- lsmash_bs_count( bs
) - 8;
2278 data
->reserved
= lsmash_bs_get_be16( bs
);
2279 data
->type_set_identifier
= lsmash_bs_get_byte( bs
);
2280 data
->type_code
= lsmash_bs_get_byte( bs
);
2281 data
->the_locale
= lsmash_bs_get_be32( bs
);
2282 if( data
->value_length
)
2284 data
->value
= lsmash_bs_get_bytes( bs
, data
->value_length
);
2286 return LSMASH_ERR_NAMELESS
;
2288 return isom_read_leaf_box_common_last_process( file
, box
, level
, data
);
2291 static int isom_read_WLOC( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2293 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2294 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->WLOC
) )
2295 return isom_read_unknown_box( file
, box
, parent
, level
);
2296 ADD_BOX( WLOC
, isom_udta_t
);
2297 lsmash_bs_t
*bs
= file
->bs
;
2298 WLOC
->x
= lsmash_bs_get_be16( bs
);
2299 WLOC
->y
= lsmash_bs_get_be16( bs
);
2300 return isom_read_leaf_box_common_last_process( file
, box
, level
, WLOC
);
2303 static int isom_read_LOOP( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2305 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2306 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->LOOP
) )
2307 return isom_read_unknown_box( file
, box
, parent
, level
);
2308 ADD_BOX( LOOP
, isom_udta_t
);
2309 lsmash_bs_t
*bs
= file
->bs
;
2310 LOOP
->looping_mode
= lsmash_bs_get_be32( bs
);
2311 return isom_read_leaf_box_common_last_process( file
, box
, level
, LOOP
);
2314 static int isom_read_SelO( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2316 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2317 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->SelO
) )
2318 return isom_read_unknown_box( file
, box
, parent
, level
);
2319 ADD_BOX( SelO
, isom_udta_t
);
2320 lsmash_bs_t
*bs
= file
->bs
;
2321 SelO
->selection_only
= lsmash_bs_get_byte( bs
);
2322 return isom_read_leaf_box_common_last_process( file
, box
, level
, SelO
);
2325 static int isom_read_AllF( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2327 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
)
2328 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t
*)parent
)->AllF
) )
2329 return isom_read_unknown_box( file
, box
, parent
, level
);
2330 ADD_BOX( AllF
, isom_udta_t
);
2331 lsmash_bs_t
*bs
= file
->bs
;
2332 AllF
->play_all_frames
= lsmash_bs_get_byte( bs
);
2333 return isom_read_leaf_box_common_last_process( file
, box
, level
, AllF
);
2336 static int isom_read_cprt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2338 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
2339 return isom_read_unknown_box( file
, box
, parent
, level
);
2340 ADD_BOX( cprt
, isom_udta_t
);
2341 box
->parent
= parent
;
2342 lsmash_bs_t
*bs
= file
->bs
;
2343 cprt
->language
= lsmash_bs_get_be16( bs
);
2344 cprt
->notice_length
= box
->size
- (ISOM_FULLBOX_COMMON_SIZE
+ 2);
2345 if( cprt
->notice_length
)
2347 cprt
->notice
= lsmash_bs_get_bytes( bs
, cprt
->notice_length
);
2350 cprt
->notice_length
= 0;
2351 return LSMASH_ERR_NAMELESS
;
2354 return isom_read_leaf_box_common_last_process( file
, box
, level
, cprt
);
2357 static int isom_read_mfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2359 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
2360 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t
*)parent
)->mfra
) )
2361 return isom_read_unknown_box( file
, box
, parent
, level
);
2362 ADD_BOX( mfra
, lsmash_file_t
);
2363 isom_box_common_copy( mfra
, box
);
2364 int ret
= isom_add_print_func( file
, mfra
, level
);
2367 return isom_read_children( file
, box
, mfra
, level
);
2370 static int isom_read_tfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2372 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
) )
2373 return isom_read_unknown_box( file
, box
, parent
, level
);
2374 ADD_BOX( tfra
, isom_mfra_t
);
2375 box
->parent
= parent
;
2376 lsmash_bs_t
*bs
= file
->bs
;
2377 tfra
->track_ID
= lsmash_bs_get_be32( bs
);
2378 uint32_t temp
= lsmash_bs_get_be32( bs
);
2379 tfra
->number_of_entry
= lsmash_bs_get_be32( bs
);
2380 tfra
->reserved
= (temp
>> 6) & 0x3ffffff;
2381 tfra
->length_size_of_traf_num
= (temp
>> 4) & 0x3;
2382 tfra
->length_size_of_trun_num
= (temp
>> 2) & 0x3;
2383 tfra
->length_size_of_sample_num
= temp
& 0x3;
2384 if( tfra
->number_of_entry
)
2386 tfra
->list
= lsmash_list_create_simple();
2388 return LSMASH_ERR_MEMORY_ALLOC
;
2389 uint64_t (*bs_get_funcs
[5])( lsmash_bs_t
* ) =
2391 lsmash_bs_get_byte_to_64
,
2392 lsmash_bs_get_be16_to_64
,
2393 lsmash_bs_get_be24_to_64
,
2394 lsmash_bs_get_be32_to_64
,
2397 uint64_t (*bs_put_time
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2398 uint64_t (*bs_put_moof_offset
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2399 uint64_t (*bs_put_traf_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_traf_num
];
2400 uint64_t (*bs_put_trun_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_trun_num
];
2401 uint64_t (*bs_put_sample_number
)( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_sample_num
];
2402 for( uint32_t i
= 0; i
< tfra
->number_of_entry
; i
++ )
2404 isom_tfra_location_time_entry_t
*data
= lsmash_malloc( sizeof(isom_tfra_location_time_entry_t
) );
2406 return LSMASH_ERR_MEMORY_ALLOC
;
2407 if( lsmash_list_add_entry( tfra
->list
, data
) < 0 )
2409 lsmash_free( data
);
2410 return LSMASH_ERR_MEMORY_ALLOC
;
2412 data
->time
= bs_put_time ( bs
);
2413 data
->moof_offset
= bs_put_moof_offset ( bs
);
2414 data
->traf_number
= bs_put_traf_number ( bs
);
2415 data
->trun_number
= bs_put_trun_number ( bs
);
2416 data
->sample_number
= bs_put_sample_number( bs
);
2419 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfra
);
2422 static int isom_read_mfro( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2424 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
)
2425 || LSMASH_IS_EXISTING_BOX( ((isom_mfra_t
*)parent
)->mfro
) )
2426 return isom_read_unknown_box( file
, box
, parent
, level
);
2427 ADD_BOX( mfro
, isom_mfra_t
);
2428 lsmash_bs_t
*bs
= file
->bs
;
2429 mfro
->length
= lsmash_bs_get_be32( bs
);
2430 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfro
);
2433 static void isom_read_skip_extra_bytes( lsmash_bs_t
*bs
, uint64_t size
)
2435 if( !bs
->unseekable
)
2437 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2438 while( size
> (INT64_MAX
>> 1) )
2440 lsmash_bs_read_seek( bs
, INT64_MAX
>> 1, SEEK_CUR
);
2441 if( lsmash_bs_is_end( bs
, 0 ) )
2443 size
-= (INT64_MAX
>> 1);
2445 lsmash_bs_read_seek( bs
, size
, SEEK_CUR
);
2448 lsmash_bs_skip_bytes_64( bs
, size
);
2451 static int isom_read_skip_box_extra_bytes( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
)
2453 lsmash_bs_t
*bs
= file
->bs
;
2454 /* Skip extra bytes of the parent box if any. */
2455 if( parent
->size
< parent_pos
+ ISOM_BASEBOX_COMMON_SIZE
)
2457 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2458 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2459 /* This is not the size of a box but makes sense in isom_read_children(). */
2460 box
->size
= extra_bytes
;
2463 /* Check if the size is valid or not. */
2464 if( lsmash_bs_is_end( bs
, 3 ) == 0 )
2466 uint64_t size
= (uint64_t)lsmash_bs_show_be32( bs
, 0 );
2468 && size
< ISOM_BASEBOX_COMMON_SIZE
)
2470 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2471 * Skip bytes up to the next box of the parent box. */
2472 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2473 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2474 box
->size
= extra_bytes
;
2477 if( size
== 1 && lsmash_bs_is_end( bs
, 15 ) == 0 )
2478 size
= lsmash_bs_show_be64( bs
, 8 ); /* large size */
2479 if( size
== 0 && parent
!= (isom_box_t
*)file
)
2481 /* Check if this box is actually the last box or not. */
2482 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2483 if( !bs
->unseekable
)
2484 size
= bs
->written
- lsmash_bs_get_stream_pos( bs
);
2487 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2488 while( size
<= extra_bytes
)
2490 int ret
= lsmash_bs_read( bs
, 1 );
2491 if( bs
->eof
|| ret
< 0 )
2493 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2496 if( size
!= extra_bytes
)
2498 /* This is not the size of the last box.
2499 * It seems we are still within the box considered as the previous or the parent box.
2500 * Skip bytes up to the next box. */
2501 if( box
->size
> lsmash_bs_count( bs
) )
2503 /* within the previous */
2504 isom_read_skip_extra_bytes( bs
, box
->size
- lsmash_bs_count( bs
) );
2505 box
->size
= 0; /* already added to the size of the parent box */
2509 /* within the parent */
2510 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2511 box
->size
= extra_bytes
;
2520 int isom_read_box( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
, int level
)
2522 assert( parent
&& parent
->root
&& parent
->file
);
2523 if( isom_read_skip_box_extra_bytes( file
, box
, parent
, parent_pos
) != 0 )
2525 memset( box
, 0, sizeof(isom_box_t
) );
2526 box
->root
= parent
->root
;
2527 box
->file
= parent
->file
;
2528 box
->parent
= parent
;
2529 lsmash_bs_t
*bs
= file
->bs
;
2530 int ret
= isom_bs_read_box_common( bs
, box
);
2532 return ret
; /* return if reached EOF */
2534 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
) = NULL
;
2535 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int ) = NULL
;
2536 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
2538 /* OK, this box is a sample entry.
2539 * Here, determine the suitable sample entry reader by media type if possible. */
2540 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
2542 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
2543 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
2544 reader_func
= isom_read_visual_description
;
2545 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
2546 reader_func
= isom_read_audio_description
;
2547 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
2548 reader_func
= isom_read_text_description
;
2550 reader_func
= isom_read_other_description
;
2551 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2552 static struct description_reader_table_tag
2554 lsmash_compact_box_type_t fourcc
;
2555 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2556 } description_reader_table
[160] = { { 0, NULL
} };
2557 if( !description_reader_table
[0].form_box_type_func
)
2559 /* Initialize the table. */
2561 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2562 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, lsmash_form_iso_box_type
);
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, lsmash_form_iso_box_type
);
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, lsmash_form_iso_box_type
);
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, lsmash_form_iso_box_type
);
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, lsmash_form_iso_box_type
);
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, lsmash_form_iso_box_type
);
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, lsmash_form_iso_box_type
);
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, lsmash_form_iso_box_type
);
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, lsmash_form_iso_box_type
);
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, lsmash_form_iso_box_type
);
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, lsmash_form_iso_box_type
);
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, lsmash_form_iso_box_type
);
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, lsmash_form_iso_box_type
);
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, lsmash_form_iso_box_type
);
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, lsmash_form_iso_box_type
);
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, lsmash_form_iso_box_type
);
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, lsmash_form_qtff_box_type
);
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, lsmash_form_qtff_box_type
);
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, lsmash_form_qtff_box_type
);
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, lsmash_form_qtff_box_type
);
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, lsmash_form_qtff_box_type
);
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, lsmash_form_qtff_box_type
);
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, lsmash_form_qtff_box_type
);
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, lsmash_form_qtff_box_type
);
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, lsmash_form_qtff_box_type
);
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, lsmash_form_qtff_box_type
);
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, lsmash_form_qtff_box_type
);
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, lsmash_form_qtff_box_type
);
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, lsmash_form_qtff_box_type
);
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, lsmash_form_qtff_box_type
);
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, lsmash_form_qtff_box_type
);
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, lsmash_form_qtff_box_type
);
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, lsmash_form_qtff_box_type
);
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, lsmash_form_qtff_box_type
);
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, lsmash_form_qtff_box_type
);
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, lsmash_form_qtff_box_type
);
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, lsmash_form_qtff_box_type
);
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, lsmash_form_qtff_box_type
);
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, lsmash_form_qtff_box_type
);
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO
, lsmash_form_qtff_box_type
);
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, lsmash_form_qtff_box_type
);
2604 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, lsmash_form_qtff_box_type
);
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, lsmash_form_qtff_box_type
);
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, lsmash_form_qtff_box_type
);
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, lsmash_form_qtff_box_type
);
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, lsmash_form_qtff_box_type
);
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, lsmash_form_qtff_box_type
);
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, lsmash_form_qtff_box_type
);
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, lsmash_form_qtff_box_type
);
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, lsmash_form_qtff_box_type
);
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, lsmash_form_qtff_box_type
);
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, lsmash_form_qtff_box_type
);
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, lsmash_form_qtff_box_type
);
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, lsmash_form_qtff_box_type
);
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, lsmash_form_qtff_box_type
);
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, lsmash_form_qtff_box_type
);
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, lsmash_form_qtff_box_type
);
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, lsmash_form_qtff_box_type
);
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, lsmash_form_qtff_box_type
);
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, lsmash_form_qtff_box_type
);
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, lsmash_form_qtff_box_type
);
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, lsmash_form_qtff_box_type
);
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, lsmash_form_qtff_box_type
);
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, lsmash_form_qtff_box_type
);
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, lsmash_form_qtff_box_type
);
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, lsmash_form_qtff_box_type
);
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, lsmash_form_qtff_box_type
);
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, lsmash_form_qtff_box_type
);
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, lsmash_form_qtff_box_type
);
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, lsmash_form_qtff_box_type
);
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO
, lsmash_form_qtff_box_type
);
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, lsmash_form_qtff_box_type
);
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, lsmash_form_qtff_box_type
);
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, lsmash_form_qtff_box_type
);
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, lsmash_form_qtff_box_type
);
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, lsmash_form_qtff_box_type
);
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, lsmash_form_qtff_box_type
);
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, lsmash_form_iso_box_type
);
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, lsmash_form_iso_box_type
);
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, lsmash_form_iso_box_type
);
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSEL_AUDIO
, lsmash_form_iso_box_type
);
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSDL_AUDIO
, lsmash_form_iso_box_type
);
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, lsmash_form_iso_box_type
);
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, lsmash_form_iso_box_type
);
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, lsmash_form_iso_box_type
);
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, lsmash_form_iso_box_type
);
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSX_AUDIO
, lsmash_form_iso_box_type
);
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, lsmash_form_iso_box_type
);
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, lsmash_form_iso_box_type
);
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, lsmash_form_iso_box_type
);
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, lsmash_form_iso_box_type
);
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, lsmash_form_iso_box_type
);
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, lsmash_form_iso_box_type
);
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, lsmash_form_iso_box_type
);
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, lsmash_form_iso_box_type
);
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, lsmash_form_iso_box_type
);
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, lsmash_form_iso_box_type
);
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, lsmash_form_iso_box_type
);
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, lsmash_form_iso_box_type
);
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, lsmash_form_iso_box_type
);
2664 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2665 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO
, lsmash_form_iso_box_type
);
2666 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, lsmash_form_qtff_box_type
);
2667 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO
, lsmash_form_qtff_box_type
);
2668 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO
, lsmash_form_qtff_box_type
);
2669 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, lsmash_form_qtff_box_type
);
2670 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO
, lsmash_form_qtff_box_type
);
2671 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO
, lsmash_form_qtff_box_type
);
2672 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO
, lsmash_form_qtff_box_type
);
2673 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO
, lsmash_form_qtff_box_type
);
2674 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO
, lsmash_form_qtff_box_type
);
2675 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO
, lsmash_form_qtff_box_type
);
2676 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO
, lsmash_form_qtff_box_type
);
2677 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO
, lsmash_form_qtff_box_type
);
2678 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO
, lsmash_form_qtff_box_type
);
2679 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, lsmash_form_qtff_box_type
);
2680 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, lsmash_form_qtff_box_type
);
2681 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO
, lsmash_form_qtff_box_type
);
2682 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, lsmash_form_qtff_box_type
);
2683 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, lsmash_form_qtff_box_type
);
2684 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, lsmash_form_qtff_box_type
);
2685 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, lsmash_form_qtff_box_type
);
2686 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, lsmash_form_qtff_box_type
);
2687 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO
, lsmash_form_qtff_box_type
);
2688 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO
, lsmash_form_qtff_box_type
);
2689 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO
, lsmash_form_qtff_box_type
);
2690 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO
, lsmash_form_qtff_box_type
);
2691 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO
, lsmash_form_qtff_box_type
);
2692 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO
, lsmash_form_qtff_box_type
);
2693 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO
, lsmash_form_qtff_box_type
);
2694 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, lsmash_form_qtff_box_type
);
2695 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, lsmash_form_qtff_box_type
);
2696 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, lsmash_form_iso_box_type
);
2697 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, lsmash_form_iso_box_type
);
2698 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW
, lsmash_form_qtff_box_type
);
2699 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
2700 assert( sizeof(description_reader_table
) >= (size_t)i
* sizeof(description_reader_table
[0]) );
2701 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2703 for( int i
= 0; description_reader_table
[i
].form_box_type_func
; i
++ )
2704 if( box
->type
.fourcc
== description_reader_table
[i
].fourcc
)
2706 form_box_type_func
= description_reader_table
[i
].form_box_type_func
;
2711 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
2713 form_box_type_func
= lsmash_form_qtff_box_type
;
2714 if( box
->type
.fourcc
== QT_BOX_TYPE_FRMA
.fourcc
) reader_func
= isom_read_frma
;
2715 else if( box
->type
.fourcc
== QT_BOX_TYPE_ENDA
.fourcc
) reader_func
= isom_read_enda
;
2716 else if( box
->type
.fourcc
== QT_BOX_TYPE_ESDS
.fourcc
) reader_func
= isom_read_esds
;
2717 else if( box
->type
.fourcc
== QT_BOX_TYPE_CHAN
.fourcc
) reader_func
= isom_read_chan
;
2718 else if( box
->type
.fourcc
== QT_BOX_TYPE_TERMINATOR
.fourcc
) reader_func
= isom_read_terminator
;
2719 else reader_func
= isom_read_codec_specific
;
2722 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
2724 form_box_type_func
= lsmash_form_iso_box_type
;
2725 reader_func
= isom_read_track_reference_type
;
2728 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_DREF
) )
2730 if( box
->type
.fourcc
== ISOM_BOX_TYPE_URL
.fourcc
2731 || box
->type
.fourcc
== ISOM_BOX_TYPE_URN
.fourcc
)
2732 form_box_type_func
= lsmash_form_iso_box_type
;
2733 else if( box
->type
.fourcc
== QT_BOX_TYPE_ALIS
.fourcc
2734 || box
->type
.fourcc
== QT_BOX_TYPE_RSRC
.fourcc
)
2735 form_box_type_func
= lsmash_form_qtff_box_type
;
2736 reader_func
= isom_read_dref_entry
;
2739 static struct box_reader_table_tag
2741 lsmash_compact_box_type_t fourcc
;
2742 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2743 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int );
2744 } box_reader_table
[128] = { { 0, NULL
, NULL
} };
2745 if( !box_reader_table
[0].reader_func
)
2747 /* Initialize the table. */
2749 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2750 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, lsmash_form_iso_box_type
, isom_read_ftyp
);
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, lsmash_form_iso_box_type
, isom_read_styp
);
2753 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, lsmash_form_iso_box_type
, isom_read_sidx
);
2754 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, lsmash_form_iso_box_type
, isom_read_moov
);
2755 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, lsmash_form_iso_box_type
, isom_read_mvhd
);
2756 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, lsmash_form_iso_box_type
, isom_read_iods
);
2757 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, lsmash_form_qtff_box_type
, isom_read_ctab
);
2758 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, lsmash_form_iso_box_type
, isom_read_trak
);
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, lsmash_form_iso_box_type
, isom_read_tkhd
);
2760 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, lsmash_form_qtff_box_type
, isom_read_tapt
);
2761 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, lsmash_form_qtff_box_type
, isom_read_clef
);
2762 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, lsmash_form_qtff_box_type
, isom_read_prof
);
2763 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, lsmash_form_qtff_box_type
, isom_read_enof
);
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, lsmash_form_iso_box_type
, isom_read_edts
);
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, lsmash_form_iso_box_type
, isom_read_elst
);
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, lsmash_form_iso_box_type
, isom_read_tref
);
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, lsmash_form_iso_box_type
, isom_read_mdia
);
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, lsmash_form_iso_box_type
, isom_read_mdhd
);
2769 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, lsmash_form_iso_box_type
, isom_read_hdlr
);
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, lsmash_form_iso_box_type
, isom_read_minf
);
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, lsmash_form_iso_box_type
, isom_read_vmhd
);
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, lsmash_form_iso_box_type
, isom_read_smhd
);
2773 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, lsmash_form_iso_box_type
, isom_read_hmhd
);
2774 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, lsmash_form_iso_box_type
, isom_read_nmhd
);
2775 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, lsmash_form_qtff_box_type
, isom_read_gmhd
);
2776 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, lsmash_form_qtff_box_type
, isom_read_gmin
);
2777 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, lsmash_form_qtff_box_type
, isom_read_text
);
2778 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, lsmash_form_iso_box_type
, isom_read_dinf
);
2779 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, lsmash_form_iso_box_type
, isom_read_dref
);
2780 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, lsmash_form_iso_box_type
, isom_read_stbl
);
2781 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, lsmash_form_iso_box_type
, isom_read_stsd
);
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, lsmash_form_iso_box_type
, isom_read_stts
);
2783 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, lsmash_form_iso_box_type
, isom_read_ctts
);
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, lsmash_form_iso_box_type
, isom_read_cslg
);
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, lsmash_form_iso_box_type
, isom_read_stss
);
2786 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, lsmash_form_qtff_box_type
, isom_read_stps
);
2787 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, lsmash_form_iso_box_type
, isom_read_sdtp
);
2788 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, lsmash_form_iso_box_type
, isom_read_stsc
);
2789 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, lsmash_form_iso_box_type
, isom_read_stsz
);
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, lsmash_form_iso_box_type
, isom_read_stz2
);
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, lsmash_form_iso_box_type
, isom_read_stco
);
2792 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, lsmash_form_iso_box_type
, isom_read_stco
);
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, lsmash_form_iso_box_type
, isom_read_sgpd
);
2794 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, lsmash_form_iso_box_type
, isom_read_sbgp
);
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, lsmash_form_iso_box_type
, isom_read_udta
);
2796 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, lsmash_form_iso_box_type
, isom_read_chpl
);
2797 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC
, lsmash_form_qtff_box_type
, isom_read_WLOC
);
2798 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP
, lsmash_form_qtff_box_type
, isom_read_LOOP
);
2799 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO
, lsmash_form_qtff_box_type
, isom_read_SelO
);
2800 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF
, lsmash_form_qtff_box_type
, isom_read_AllF
);
2801 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, lsmash_form_iso_box_type
, isom_read_mvex
);
2802 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, lsmash_form_iso_box_type
, isom_read_mehd
);
2803 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, lsmash_form_iso_box_type
, isom_read_trex
);
2804 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, lsmash_form_iso_box_type
, isom_read_moof
);
2805 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, lsmash_form_iso_box_type
, isom_read_mfhd
);
2806 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, lsmash_form_iso_box_type
, isom_read_traf
);
2807 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, lsmash_form_iso_box_type
, isom_read_tfhd
);
2808 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, lsmash_form_iso_box_type
, isom_read_tfdt
);
2809 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, lsmash_form_iso_box_type
, isom_read_trun
);
2810 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, lsmash_form_iso_box_type
, isom_read_free
);
2811 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, lsmash_form_iso_box_type
, isom_read_free
);
2812 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, lsmash_form_iso_box_type
, isom_read_mdat
);
2813 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS
, lsmash_form_qtff_box_type
, isom_read_keys
);
2814 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, lsmash_form_iso_box_type
, isom_read_mfra
);
2815 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, lsmash_form_iso_box_type
, isom_read_tfra
);
2816 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, lsmash_form_iso_box_type
, isom_read_mfro
);
2817 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
, NULL
);
2818 assert( sizeof(box_reader_table
) >= (size_t)i
* sizeof(box_reader_table
[0]) );
2819 #undef ADD_BOX_READER_TABLE_ELEMENT
2821 for( int i
= 0; box_reader_table
[i
].reader_func
; i
++ )
2822 if( box
->type
.fourcc
== box_reader_table
[i
].fourcc
)
2824 form_box_type_func
= box_reader_table
[i
].form_box_type_func
;
2825 reader_func
= box_reader_table
[i
].reader_func
;
2828 if( box
->type
.fourcc
== ISOM_BOX_TYPE_META
.fourcc
)
2830 if( lsmash_bs_is_end ( bs
, 3 ) == 0
2831 && lsmash_bs_show_be32( bs
, 0 ) == 0 )
2832 form_box_type_func
= lsmash_form_iso_box_type
;
2834 form_box_type_func
= lsmash_form_qtff_box_type
;
2835 reader_func
= isom_read_meta
;
2838 if( box
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2840 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
) )
2841 form_box_type_func
= lsmash_form_iso_box_type
;
2842 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
2843 form_box_type_func
= lsmash_form_qtff_box_type
;
2844 if( form_box_type_func
)
2846 reader_func
= isom_read_ilst
;
2850 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
) )
2851 form_box_type_func
= lsmash_form_iso_box_type
;
2852 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2853 form_box_type_func
= lsmash_form_qtff_box_type
;
2854 if( form_box_type_func
)
2856 reader_func
= isom_read_metaitem
;
2859 if( parent
->parent
&& parent
->parent
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2861 if( box
->type
.fourcc
== ISOM_BOX_TYPE_MEAN
.fourcc
)
2862 reader_func
= isom_read_mean
;
2863 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_NAME
.fourcc
)
2864 reader_func
= isom_read_name
;
2865 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_DATA
.fourcc
)
2866 reader_func
= isom_read_data
;
2869 form_box_type_func
= lsmash_form_iso_box_type
;
2873 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_CPRT
.fourcc
)
2875 /* Avoid confusing udta.cprt with ilst.cprt. */
2876 form_box_type_func
= lsmash_form_iso_box_type
;
2877 reader_func
= isom_read_cprt
;
2880 if( parent
->parent
&& lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_STSD
) )
2882 static struct sample_description_extension_reader_table_tag
2884 lsmash_compact_box_type_t fourcc
;
2885 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2886 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int );
2887 } extension_reader_table
[32] = { { 0, NULL
, NULL
} };
2888 if( !extension_reader_table
[0].reader_func
)
2890 /* Initialize the table. */
2892 #define ADD_EXTENSION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2893 extension_reader_table[i++] = (struct sample_description_extension_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2895 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2896 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2897 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2898 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2899 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2900 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT
, lsmash_form_iso_box_type
, isom_read_srat
);
2901 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2902 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, lsmash_form_qtff_box_type
, isom_read_chan
);
2903 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, lsmash_form_qtff_box_type
, isom_read_wave
);
2905 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2906 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, lsmash_form_iso_box_type
, isom_read_btrt
);
2907 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, lsmash_form_iso_box_type
, isom_read_colr
);
2908 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, lsmash_form_iso_box_type
, isom_read_clap
);
2909 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2910 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC
, lsmash_form_iso_box_type
, isom_read_codec_specific
);
2911 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, lsmash_form_iso_box_type
, isom_read_pasp
);
2912 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, lsmash_form_iso_box_type
, isom_read_stsl
);
2913 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, lsmash_form_qtff_box_type
, isom_read_cspc
);
2914 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, lsmash_form_qtff_box_type
, isom_read_fiel
);
2915 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, lsmash_form_qtff_box_type
, isom_read_gama
);
2916 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, lsmash_form_qtff_box_type
, isom_read_glbl
);
2917 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, lsmash_form_qtff_box_type
, isom_read_sgbt
);
2919 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, lsmash_form_iso_box_type
, isom_read_esds
);
2920 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, lsmash_form_iso_box_type
, isom_read_ftab
);
2921 ADD_EXTENSION_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
, NULL
);
2922 assert( sizeof(extension_reader_table
) >= (size_t)i
* sizeof(extension_reader_table
[0]) );
2923 #undef ADD_EXTENSION_READER_TABLE_ELEMENT
2925 for( int i
= 0; extension_reader_table
[i
].reader_func
; i
++ )
2926 if( box
->type
.fourcc
== extension_reader_table
[i
].fourcc
)
2928 form_box_type_func
= extension_reader_table
[i
].form_box_type_func
;
2929 reader_func
= extension_reader_table
[i
].reader_func
;
2932 reader_func
= isom_read_codec_specific
;
2935 if( form_box_type_func
)
2936 box
->type
= form_box_type_func( box
->type
.fourcc
);
2937 if( (ret
= isom_read_fullbox_common_extension( bs
, box
)) < 0 )
2940 ? reader_func( file
, box
, parent
, level
)
2941 : isom_read_unknown_box( file
, box
, parent
, level
);
2944 int isom_read_file( lsmash_file_t
*file
)
2946 lsmash_bs_t
*bs
= file
->bs
;
2948 return LSMASH_ERR_NAMELESS
;
2949 /* Reset the counter so that we can use it to get position within the box. */
2950 lsmash_bs_reset_counter( bs
);
2951 if( file
->flags
& LSMASH_FILE_MODE_DUMP
)
2953 file
->print
= isom_printer_create_list();
2955 return LSMASH_ERR_MEMORY_ALLOC
;
2957 file
->size
= UINT64_MAX
;
2959 int ret
= isom_read_children( file
, &box
, file
, 0 );
2960 file
->size
= box
.size
;
2961 lsmash_bs_empty( bs
);
2962 bs
->error
= 0; /* Clear error flag. */
2965 return isom_check_compatibility( file
);