Allow esds in 'enca' Audio Description for encrypted audio
[L-SMASH.git] / core / read.c
blobf3ded1c5a52b3c6fbdb79bffb3c8704cf54f08b2
1 /*****************************************************************************
2 * read.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2015 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "box.h"
30 #include "file.h"
31 #include "print.h"
32 #include "read.h"
33 #include "write.h"
35 #include "codecs/mp4a.h"
36 #include "codecs/mp4sys.h"
37 #include "codecs/description.h"
39 static int isom_bs_read_box_common( lsmash_bs_t *bs, isom_box_t *box )
41 assert( bs && box && box->file );
42 /* Reset the counter so that we can use it to get position within the box. */
43 lsmash_bs_reset_counter( bs );
44 /* Read the common fields of box. */
45 box->pos = lsmash_bs_get_stream_pos( bs );
46 if( bs->eob )
47 /* No more read. */
48 return 1;
49 /* Read size and type. */
50 box->size = lsmash_bs_get_be32( bs );
51 box->type.fourcc = lsmash_bs_get_be32( bs );
52 /* If size is set to 1, the actual size is repersented in the next 8 bytes.
53 * If size is set to 0, this box ends at the end of the stream. */
54 if( box->size == 1 )
55 box->size = lsmash_bs_get_be64( bs );
56 if( box->size == 0 )
58 /* This box is the last box in the stream. */
59 box->manager |= LSMASH_LAST_BOX;
60 if( !bs->unseekable )
61 box->size = bs->written - (lsmash_bs_get_stream_pos( bs ) - lsmash_bs_count( bs ));
62 else
63 /* We haven't known the box size yet.
64 * To get the box size, read the stream until the end of the stream. */
65 while( 1 )
67 int ret = lsmash_bs_read( bs, 1 );
68 if( bs->eof || ret < 0 )
70 /* OK, now we know the box size. */
71 box->size = lsmash_bs_count( bs ) + lsmash_bs_get_remaining_buffer_size( bs );
72 if( ret < 0 )
73 /* This box may end incompletely at the end of the stream. */
74 box->manager |= LSMASH_INCOMPLETE_BOX;
75 break;
79 /* Here, we don't set up extended box type fields if this box is not a UUID Box. */
80 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc
81 && box->size >= lsmash_bs_count( bs ) + 16 )
83 /* Get UUID. */
84 lsmash_box_type_t *type = &box->type;
85 uint64_t temp64 = lsmash_bs_get_be64( bs );
86 type->user.fourcc = (temp64 >> 32) & 0xffffffff;
87 LSMASH_SET_BE32( &type->user.id[0], temp64 );
88 temp64 = lsmash_bs_get_be64( bs );
89 LSMASH_SET_BE64( &type->user.id[4], temp64 );
91 return bs->eob;
94 static int isom_read_fullbox_common_extension( lsmash_bs_t *bs, isom_box_t *box )
96 if( !isom_is_fullbox( box ) )
97 return 0;
98 /* Get version and flags. */
99 box->version = lsmash_bs_get_byte( bs );
100 box->flags = lsmash_bs_get_be24( bs );
101 box->manager |= LSMASH_FULLBOX;
102 return 0;
105 /* Don't copy destructor since a destructor is defined as box specific. */
106 static void isom_basebox_common_copy( isom_box_t *dst, isom_box_t *src )
108 dst->root = src->root;
109 dst->file = src->file;
110 dst->parent = src->parent;
111 dst->manager = src->manager;
112 dst->pos = src->pos;
113 dst->size = src->size;
114 dst->type = src->type;
117 static void isom_fullbox_common_copy( isom_box_t *dst, isom_box_t *src )
119 dst->root = src->root;
120 dst->file = src->file;
121 dst->parent = src->parent;
122 dst->manager = src->manager;
123 dst->pos = src->pos;
124 dst->size = src->size;
125 dst->type = src->type;
126 dst->version = src->version;
127 dst->flags = src->flags;
130 static void isom_box_common_copy( void *dst, void *src )
132 if( src && lsmash_check_box_type_identical( ((isom_box_t *)src)->type, ISOM_BOX_TYPE_STSD ) )
134 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
135 return;
137 if( isom_is_fullbox( src ) )
138 isom_fullbox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
139 else
140 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
143 static void isom_skip_box_rest( lsmash_bs_t *bs, isom_box_t *box )
145 if( box->manager & LSMASH_LAST_BOX )
147 box->size = (box->manager & LSMASH_FULLBOX) ? ISOM_FULLBOX_COMMON_SIZE : ISOM_BASEBOX_COMMON_SIZE;
148 uint64_t start = lsmash_bs_get_stream_pos( bs );
149 if( !bs->unseekable )
150 lsmash_bs_read_seek( bs, 0, SEEK_END );
151 else
152 while( !bs->eob )
153 lsmash_bs_skip_bytes( bs, UINT32_MAX );
154 uint64_t end = lsmash_bs_get_stream_pos( bs );
155 box->size += end - start;
156 return;
158 uint64_t skip_bytes = box->size - lsmash_bs_count( bs );
159 if( !bs->unseekable )
161 /* The stream is seekable. So, skip by seeking the stream. */
162 uint64_t start = lsmash_bs_get_stream_pos( bs );
163 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
164 uint64_t end = lsmash_bs_get_stream_pos( bs );
165 if( end - start != skip_bytes )
166 /* not match size */
167 box->manager |= LSMASH_INCOMPLETE_BOX;
168 return;
170 /* The stream is unseekable. So, skip by reading the stream. */
171 lsmash_bs_skip_bytes_64( bs, skip_bytes );
172 if( box->size > lsmash_bs_count( bs ) )
173 box->manager |= LSMASH_INCOMPLETE_BOX;
176 static void isom_validate_box_size( lsmash_bs_t *bs, isom_box_t *box )
178 uint64_t pos = lsmash_bs_count( bs );
179 if( box->manager & LSMASH_LAST_BOX )
181 box->size = pos;
182 return;
184 if( box->size < pos )
186 printf( "[%s] box has less bytes than expected: %"PRId64"\n", isom_4cc2str( box->type.fourcc ), pos - box->size );
187 box->size = pos;
189 else if( box->size > pos )
191 /* The box probably has extra padding bytes at the end. */
192 printf( "[%s] box has more bytes than expected: %"PRId64"\n", isom_4cc2str( box->type.fourcc ), box->size - pos );
193 isom_skip_box_rest( bs, box );
197 static int isom_read_children( lsmash_file_t *file, isom_box_t *box, void *parent, int level )
199 int ret;
200 lsmash_bs_t *bs = file->bs;
201 isom_box_t *parent_box = (isom_box_t *)parent;
202 uint64_t parent_pos = lsmash_bs_count( bs );
203 while( !(ret = isom_read_box( file, box, parent_box, parent_pos, level )) )
205 parent_pos += box->size;
206 if( parent_box->size <= parent_pos || bs->eob || bs->error )
207 break;
209 box->size = parent_pos; /* for file size */
210 return ret;
213 static int isom_read_leaf_box_common_last_process( lsmash_file_t *file, isom_box_t *box, int level, void *instance )
215 isom_validate_box_size( file->bs, box );
216 isom_box_common_copy( instance, box );
217 return isom_add_print_func( file, instance, level );
220 static int isom_read_unknown_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
222 lsmash_bs_t *bs = file->bs;
223 uint64_t read_size = box->size - lsmash_bs_count( bs );
224 if( box->manager & LSMASH_INCOMPLETE_BOX )
225 return LSMASH_ERR_INVALID_DATA;
226 isom_unknown_box_t *unknown = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
227 if( !unknown )
228 return LSMASH_ERR_MEMORY_ALLOC;
229 if( lsmash_add_entry( &parent->extensions, unknown ) < 0 )
231 lsmash_free( unknown );
232 return LSMASH_ERR_MEMORY_ALLOC;
234 isom_box_common_copy( unknown, box );
235 unknown->manager |= LSMASH_UNKNOWN_BOX;
236 unknown->destruct = (isom_extension_destructor_t)isom_remove_unknown_box;
237 isom_set_box_writer( (isom_box_t *)unknown );
238 if( read_size )
240 unknown->unknown_field = lsmash_bs_get_bytes( bs, read_size );
241 if( unknown->unknown_field )
242 unknown->unknown_size = read_size;
243 else
244 unknown->manager |= LSMASH_INCOMPLETE_BOX;
246 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
247 return 0;
248 /* Create a dummy for dump. */
249 isom_box_t *dummy = lsmash_malloc_zero( sizeof(isom_box_t) );
250 if( !dummy )
251 return LSMASH_ERR_MEMORY_ALLOC;
252 box->manager |= LSMASH_ABSENT_IN_FILE | LSMASH_UNKNOWN_BOX;
253 isom_box_common_copy( dummy, box );
254 int ret = isom_add_print_func( file, dummy, level );
255 if( ret < 0 )
257 lsmash_free( dummy );
258 return ret;
260 return 0;
263 #define ADD_BOX( box_name, parent_type ) \
264 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
265 if( !box_name ) \
266 return LSMASH_ERR_NAMELESS
268 static int isom_read_ftyp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
270 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->ftyp )
271 return isom_read_unknown_box( file, box, parent, level );
272 ADD_BOX( ftyp, lsmash_file_t );
273 lsmash_bs_t *bs = file->bs;
274 ftyp->major_brand = lsmash_bs_get_be32( bs );
275 ftyp->minor_version = lsmash_bs_get_be32( bs );
276 uint64_t pos = lsmash_bs_count( bs );
277 ftyp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
278 size_t alloc_size = ftyp->brand_count * sizeof(uint32_t);
279 ftyp->compatible_brands = ftyp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
280 if( ftyp->brand_count && !ftyp->compatible_brands )
281 return LSMASH_ERR_MEMORY_ALLOC;
282 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
283 ftyp->compatible_brands[i] = lsmash_bs_get_be32( bs );
284 if( !file->compatible_brands && ftyp->compatible_brands )
286 file->compatible_brands = lsmash_memdup( ftyp->compatible_brands, alloc_size );
287 if( !file->compatible_brands )
288 return LSMASH_ERR_MEMORY_ALLOC;
289 file->brand_count = ftyp->brand_count;
291 return isom_read_leaf_box_common_last_process( file, box, level, ftyp );
294 static int isom_read_styp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
296 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
297 return isom_read_unknown_box( file, box, parent, level );
298 ADD_BOX( styp, lsmash_file_t );
299 lsmash_bs_t *bs = file->bs;
300 styp->major_brand = lsmash_bs_get_be32( bs );
301 styp->minor_version = lsmash_bs_get_be32( bs );
302 uint64_t pos = lsmash_bs_count( bs );
303 styp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
304 size_t alloc_size = styp->brand_count * sizeof(uint32_t);
305 styp->compatible_brands = styp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
306 if( styp->brand_count && !styp->compatible_brands )
307 return LSMASH_ERR_MEMORY_ALLOC;
308 for( uint32_t i = 0; i < styp->brand_count; i++ )
309 styp->compatible_brands[i] = lsmash_bs_get_be32( bs );
310 if( !file->compatible_brands && styp->compatible_brands )
312 file->compatible_brands = lsmash_memdup( styp->compatible_brands, alloc_size );
313 if( !file->compatible_brands )
314 return LSMASH_ERR_MEMORY_ALLOC;
315 file->brand_count = styp->brand_count;
317 file->flags |= LSMASH_FILE_MODE_SEGMENT;
318 return isom_read_leaf_box_common_last_process( file, box, level, styp );
321 static int isom_read_sidx( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
323 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
324 return isom_read_unknown_box( file, box, parent, level );
325 ADD_BOX( sidx, lsmash_file_t );
326 lsmash_bs_t *bs = file->bs;
327 sidx->reference_ID = lsmash_bs_get_be32( bs );
328 sidx->timescale = lsmash_bs_get_be32( bs );
329 if( box->version == 0 )
331 sidx->earliest_presentation_time = lsmash_bs_get_be32( bs );
332 sidx->first_offset = lsmash_bs_get_be32( bs );
334 else
336 sidx->earliest_presentation_time = lsmash_bs_get_be64( bs );
337 sidx->first_offset = lsmash_bs_get_be64( bs );
339 sidx->reserved = lsmash_bs_get_be16( bs );
340 sidx->reference_count = lsmash_bs_get_be16( bs );
341 for( uint64_t pos = lsmash_bs_count( bs );
342 pos < box->size && sidx->list->entry_count < sidx->reference_count;
343 pos = lsmash_bs_count( bs ) )
345 isom_sidx_referenced_item_t *data = lsmash_malloc( sizeof(isom_sidx_referenced_item_t) );
346 if( !data )
347 return LSMASH_ERR_MEMORY_ALLOC;
348 if( lsmash_add_entry( sidx->list, data ) < 0 )
350 lsmash_free( data );
351 return LSMASH_ERR_MEMORY_ALLOC;
353 uint32_t temp32;
354 temp32 = lsmash_bs_get_be32( bs );
355 data->reference_type = (temp32 >> 31) & 0x00000001;
356 data->reference_size = temp32 & 0x7FFFFFFF;
357 data->subsegment_duration = lsmash_bs_get_be32( bs );
358 temp32 = lsmash_bs_get_be32( bs );
359 data->starts_with_SAP = (temp32 >> 31) & 0x00000001;
360 data->SAP_type = (temp32 >> 28) & 0x00000007;
361 data->SAP_delta_time = temp32 & 0x0FFFFFFF;
363 file->flags |= LSMASH_FILE_MODE_INDEX;
364 return isom_read_leaf_box_common_last_process( file, box, level, sidx );
367 static int isom_read_moov( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
369 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->moov )
370 return isom_read_unknown_box( file, box, parent, level );
371 ADD_BOX( moov, lsmash_file_t );
372 file->flags |= LSMASH_FILE_MODE_INITIALIZATION;
373 file->initializer = file;
374 isom_box_common_copy( moov, box );
375 int ret = isom_add_print_func( file, moov, level );
376 if( ret < 0 )
377 return ret;
378 return isom_read_children( file, box, moov, level );
381 static int isom_read_mvhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
383 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvhd )
384 return isom_read_unknown_box( file, box, parent, level );
385 ADD_BOX( mvhd, isom_moov_t );
386 lsmash_bs_t *bs = file->bs;
387 if( box->version )
389 mvhd->creation_time = lsmash_bs_get_be64( bs );
390 mvhd->modification_time = lsmash_bs_get_be64( bs );
391 mvhd->timescale = lsmash_bs_get_be32( bs );
392 mvhd->duration = lsmash_bs_get_be64( bs );
394 else
396 mvhd->creation_time = lsmash_bs_get_be32( bs );
397 mvhd->modification_time = lsmash_bs_get_be32( bs );
398 mvhd->timescale = lsmash_bs_get_be32( bs );
399 mvhd->duration = lsmash_bs_get_be32( bs );
401 mvhd->rate = lsmash_bs_get_be32( bs );
402 mvhd->volume = lsmash_bs_get_be16( bs );
403 mvhd->reserved = lsmash_bs_get_be16( bs );
404 mvhd->preferredLong[0] = lsmash_bs_get_be32( bs );
405 mvhd->preferredLong[1] = lsmash_bs_get_be32( bs );
406 for( int i = 0; i < 9; i++ )
407 mvhd->matrix[i] = lsmash_bs_get_be32( bs );
408 mvhd->previewTime = lsmash_bs_get_be32( bs );
409 mvhd->previewDuration = lsmash_bs_get_be32( bs );
410 mvhd->posterTime = lsmash_bs_get_be32( bs );
411 mvhd->selectionTime = lsmash_bs_get_be32( bs );
412 mvhd->selectionDuration = lsmash_bs_get_be32( bs );
413 mvhd->currentTime = lsmash_bs_get_be32( bs );
414 mvhd->next_track_ID = lsmash_bs_get_be32( bs );
415 return isom_read_leaf_box_common_last_process( file, box, level, mvhd );
418 static int isom_read_iods( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
420 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
421 return isom_read_unknown_box( file, box, parent, level );
422 ADD_BOX( iods, isom_moov_t );
423 lsmash_bs_t *bs = file->bs;
424 iods->OD = mp4sys_get_descriptor( bs, NULL );
425 if( !iods->OD )
426 return LSMASH_ERR_INVALID_DATA;
427 return isom_read_leaf_box_common_last_process( file, box, level, iods );
430 static int isom_read_qt_color_table( lsmash_bs_t *bs, isom_qt_color_table_t *color_table )
432 color_table->seed = lsmash_bs_get_be32( bs );
433 color_table->flags = lsmash_bs_get_be16( bs );
434 color_table->size = lsmash_bs_get_be16( bs );
435 if( bs->eob )
436 return LSMASH_ERR_INVALID_DATA;
437 isom_qt_color_array_t *array = lsmash_malloc_zero( (color_table->size + 1) * sizeof(isom_qt_color_array_t) );
438 if( !array )
439 return LSMASH_ERR_MEMORY_ALLOC;
440 color_table->array = array;
441 for( uint16_t i = 0; i <= color_table->size; i++ )
443 uint64_t color = lsmash_bs_get_be64( bs );
444 array[i].value = (color >> 48) & 0xffff;
445 array[i].r = (color >> 32) & 0xffff;
446 array[i].g = (color >> 16) & 0xffff;
447 array[i].b = color & 0xffff;
449 return 0;
452 static int isom_read_ctab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
454 ADD_BOX( ctab, isom_moov_t );
455 lsmash_bs_t *bs = file->bs;
456 int ret = isom_read_qt_color_table( bs, &ctab->color_table );
457 if( ret < 0 )
458 return ret;
459 return isom_read_leaf_box_common_last_process( file, box, level, ctab );
462 static int isom_read_trak( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
464 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
465 return isom_read_unknown_box( file, box, parent, level );
466 ADD_BOX( trak, isom_moov_t );
467 box->parent = parent;
468 box->root = file->root;
469 box->file = file;
470 isom_box_common_copy( trak, box );
471 int ret = isom_add_print_func( file, trak, level );
472 if( ret < 0 )
473 return ret;
474 return isom_read_children( file, box, trak, level );
477 static int isom_read_tkhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
479 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tkhd )
480 return isom_read_unknown_box( file, box, parent, level );
481 ADD_BOX( tkhd, isom_trak_t );
482 lsmash_bs_t *bs = file->bs;
483 if( box->version )
485 tkhd->creation_time = lsmash_bs_get_be64( bs );
486 tkhd->modification_time = lsmash_bs_get_be64( bs );
487 tkhd->track_ID = lsmash_bs_get_be32( bs );
488 tkhd->reserved1 = lsmash_bs_get_be32( bs );
489 tkhd->duration = lsmash_bs_get_be64( bs );
491 else
493 tkhd->creation_time = lsmash_bs_get_be32( bs );
494 tkhd->modification_time = lsmash_bs_get_be32( bs );
495 tkhd->track_ID = lsmash_bs_get_be32( bs );
496 tkhd->reserved1 = lsmash_bs_get_be32( bs );
497 tkhd->duration = lsmash_bs_get_be32( bs );
499 tkhd->reserved2[0] = lsmash_bs_get_be32( bs );
500 tkhd->reserved2[1] = lsmash_bs_get_be32( bs );
501 tkhd->layer = lsmash_bs_get_be16( bs );
502 tkhd->alternate_group = lsmash_bs_get_be16( bs );
503 tkhd->volume = lsmash_bs_get_be16( bs );
504 tkhd->reserved3 = lsmash_bs_get_be16( bs );
505 for( int i = 0; i < 9; i++ )
506 tkhd->matrix[i] = lsmash_bs_get_be32( bs );
507 tkhd->width = lsmash_bs_get_be32( bs );
508 tkhd->height = lsmash_bs_get_be32( bs );
509 return isom_read_leaf_box_common_last_process( file, box, level, tkhd );
512 static int isom_read_tapt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
514 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tapt )
515 return isom_read_unknown_box( file, box, parent, level );
516 ADD_BOX( tapt, isom_trak_t );
517 isom_box_common_copy( tapt, box );
518 int ret = isom_add_print_func( file, tapt, level );
519 if( ret < 0 )
520 return ret;
521 return isom_read_children( file, box, tapt, level );
524 static int isom_read_clef( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
526 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->clef )
527 return isom_read_unknown_box( file, box, parent, level );
528 ADD_BOX( clef, isom_tapt_t );
529 lsmash_bs_t *bs = file->bs;
530 clef->width = lsmash_bs_get_be32( bs );
531 clef->height = lsmash_bs_get_be32( bs );
532 return isom_read_leaf_box_common_last_process( file, box, level, clef );
535 static int isom_read_prof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
537 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->prof )
538 return isom_read_unknown_box( file, box, parent, level );
539 ADD_BOX( prof, isom_tapt_t );
540 lsmash_bs_t *bs = file->bs;
541 prof->width = lsmash_bs_get_be32( bs );
542 prof->height = lsmash_bs_get_be32( bs );
543 return isom_read_leaf_box_common_last_process( file, box, level, prof );
546 static int isom_read_enof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
548 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->enof )
549 return isom_read_unknown_box( file, box, parent, level );
550 ADD_BOX( enof, isom_tapt_t );
551 lsmash_bs_t *bs = file->bs;
552 enof->width = lsmash_bs_get_be32( bs );
553 enof->height = lsmash_bs_get_be32( bs );
554 return isom_read_leaf_box_common_last_process( file, box, level, enof );
557 static int isom_read_edts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
559 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->edts )
560 return isom_read_unknown_box( file, box, parent, level );
561 ADD_BOX( edts, isom_trak_t );
562 isom_box_common_copy( edts, box );
563 if( isom_add_print_func( file, edts, level ) < 0 )
564 return -1;
565 return isom_read_children( file, box, edts, level );
568 static int isom_read_elst( 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_EDTS ) || ((isom_edts_t *)parent)->elst )
571 return isom_read_unknown_box( file, box, parent, level );
572 ADD_BOX( elst, isom_edts_t );
573 lsmash_bs_t *bs = file->bs;
574 uint32_t entry_count = lsmash_bs_get_be32( bs );
575 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && elst->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
577 isom_elst_entry_t *data = lsmash_malloc( sizeof(isom_elst_entry_t) );
578 if( !data )
579 return LSMASH_ERR_MEMORY_ALLOC;
580 if( lsmash_add_entry( elst->list, data ) < 0 )
582 lsmash_free( data );
583 return LSMASH_ERR_MEMORY_ALLOC;
585 if( box->version == 1 )
587 data->segment_duration = lsmash_bs_get_be64( bs );
588 data->media_time = (int64_t)lsmash_bs_get_be64( bs );
590 else
592 data->segment_duration = lsmash_bs_get_be32( bs );
593 data->media_time = (int32_t)lsmash_bs_get_be32( bs );
595 data->media_rate = lsmash_bs_get_be32( bs );
597 return isom_read_leaf_box_common_last_process( file, box, level, elst );
600 static int isom_read_tref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
602 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tref )
603 return isom_read_unknown_box( file, box, parent, level );
604 ADD_BOX( tref, isom_trak_t );
605 isom_box_common_copy( tref, box );
606 int ret = isom_add_print_func( file, tref, level );
607 if( ret < 0 )
608 return ret;
609 return isom_read_children( file, box, tref, level );
612 static int isom_read_track_reference_type( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
614 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
615 return isom_read_unknown_box( file, box, parent, level );
616 isom_tref_type_t *ref = isom_add_track_reference_type( (isom_tref_t *)parent, box->type.fourcc );
617 if( !ref )
618 return LSMASH_ERR_NAMELESS;
619 lsmash_bs_t *bs = file->bs;
620 ref->ref_count = (box->size - lsmash_bs_count( bs ) ) / sizeof(uint32_t);
621 if( ref->ref_count )
623 ref->track_ID = lsmash_malloc( ref->ref_count * sizeof(uint32_t) );
624 if( !ref->track_ID )
626 ref->ref_count = 0;
627 return LSMASH_ERR_MEMORY_ALLOC;
629 for( uint32_t i = 0; i < ref->ref_count; i++ )
630 ref->track_ID[i] = lsmash_bs_get_be32( bs );
632 return isom_read_leaf_box_common_last_process( file, box, level, ref );
635 static int isom_read_mdia( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
637 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->mdia )
638 return isom_read_unknown_box( file, box, parent, level );
639 ADD_BOX( mdia, isom_trak_t );
640 isom_box_common_copy( mdia, box );
641 int ret = isom_add_print_func( file, mdia, level );
642 if( ret < 0 )
643 return ret;
644 return isom_read_children( file, box, mdia, level );
647 static int isom_read_mdhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
649 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->mdhd )
650 return isom_read_unknown_box( file, box, parent, level );
651 ADD_BOX( mdhd, isom_mdia_t );
652 lsmash_bs_t *bs = file->bs;
653 if( box->version )
655 mdhd->creation_time = lsmash_bs_get_be64( bs );
656 mdhd->modification_time = lsmash_bs_get_be64( bs );
657 mdhd->timescale = lsmash_bs_get_be32( bs );
658 mdhd->duration = lsmash_bs_get_be64( bs );
660 else
662 mdhd->creation_time = lsmash_bs_get_be32( bs );
663 mdhd->modification_time = lsmash_bs_get_be32( bs );
664 mdhd->timescale = lsmash_bs_get_be32( bs );
665 mdhd->duration = lsmash_bs_get_be32( bs );
667 mdhd->language = lsmash_bs_get_be16( bs );
668 mdhd->quality = lsmash_bs_get_be16( bs );
669 return isom_read_leaf_box_common_last_process( file, box, level, mdhd );
672 static int isom_read_hdlr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
674 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
675 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
676 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META )
677 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ))
678 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) && ((isom_mdia_t *)parent)->hdlr)
679 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
680 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
681 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->hdlr) )
682 return isom_read_unknown_box( file, box, parent, level );
683 ADD_BOX( hdlr, void );
684 lsmash_bs_t *bs = file->bs;
685 hdlr->componentType = lsmash_bs_get_be32( bs );
686 hdlr->componentSubtype = lsmash_bs_get_be32( bs );
687 hdlr->componentManufacturer = lsmash_bs_get_be32( bs );
688 hdlr->componentFlags = lsmash_bs_get_be32( bs );
689 hdlr->componentFlagsMask = lsmash_bs_get_be32( bs );
690 uint64_t pos = lsmash_bs_count( bs );
691 hdlr->componentName_length = box->size - pos;
692 if( hdlr->componentName_length )
694 hdlr->componentName = lsmash_malloc( hdlr->componentName_length );
695 if( !hdlr->componentName )
696 return LSMASH_ERR_MEMORY_ALLOC;
697 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
698 hdlr->componentName[i++] = lsmash_bs_get_byte( bs );
700 return isom_read_leaf_box_common_last_process( file, box, level, hdlr );
703 static int isom_read_minf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
705 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->minf )
706 return isom_read_unknown_box( file, box, parent, level );
707 ADD_BOX( minf, isom_mdia_t );
708 isom_box_common_copy( minf, box );
709 int ret = isom_add_print_func( file, minf, level );
710 if( ret < 0 )
711 return ret;
712 return isom_read_children( file, box, minf, level );
715 static int isom_read_vmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
717 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->vmhd )
718 return isom_read_unknown_box( file, box, parent, level );
719 ADD_BOX( vmhd, isom_minf_t );
720 lsmash_bs_t *bs = file->bs;
721 vmhd->graphicsmode = lsmash_bs_get_be16( bs );
722 for( int i = 0; i < 3; i++ )
723 vmhd->opcolor[i] = lsmash_bs_get_be16( bs );
724 return isom_read_leaf_box_common_last_process( file, box, level, vmhd );
727 static int isom_read_smhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
729 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->smhd )
730 return isom_read_unknown_box( file, box, parent, level );
731 ADD_BOX( smhd, isom_minf_t );
732 lsmash_bs_t *bs = file->bs;
733 smhd->balance = lsmash_bs_get_be16( bs );
734 smhd->reserved = lsmash_bs_get_be16( bs );
735 return isom_read_leaf_box_common_last_process( file, box, level, smhd );
738 static int isom_read_hmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
740 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->hmhd )
741 return isom_read_unknown_box( file, box, parent, level );
742 ADD_BOX( hmhd, isom_minf_t );
743 lsmash_bs_t *bs = file->bs;
744 hmhd->maxPDUsize = lsmash_bs_get_be16( bs );
745 hmhd->avgPDUsize = lsmash_bs_get_be16( bs );
746 hmhd->maxbitrate = lsmash_bs_get_be32( bs );
747 hmhd->avgbitrate = lsmash_bs_get_be32( bs );
748 hmhd->reserved = lsmash_bs_get_be32( bs );
749 return isom_read_leaf_box_common_last_process( file, box, level, hmhd );
752 static int isom_read_nmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
754 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->nmhd )
755 return isom_read_unknown_box( file, box, parent, level );
756 ADD_BOX( nmhd, isom_minf_t );
757 return isom_read_leaf_box_common_last_process( file, box, level, nmhd );
760 static int isom_read_gmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
762 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->gmhd )
763 return isom_read_unknown_box( file, box, parent, level );
764 ADD_BOX( gmhd, isom_minf_t );
765 isom_box_common_copy( gmhd, box );
766 int ret = isom_add_print_func( file, gmhd, level );
767 if( ret < 0 )
768 return ret;
769 return isom_read_children( file, box, gmhd, level );
772 static int isom_read_gmin( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
774 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->gmin )
775 return isom_read_unknown_box( file, box, parent, level );
776 ADD_BOX( gmin, isom_gmhd_t );
777 lsmash_bs_t *bs = file->bs;
778 gmin->graphicsmode = lsmash_bs_get_be16( bs );
779 for( int i = 0; i < 3; i++ )
780 gmin->opcolor[i] = lsmash_bs_get_be16( bs );
781 gmin->balance = lsmash_bs_get_be16( bs );
782 gmin->reserved = lsmash_bs_get_be16( bs );
783 return isom_read_leaf_box_common_last_process( file, box, level, gmin );
786 static int isom_read_text( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
788 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->text )
789 return isom_read_unknown_box( file, box, parent, level );
790 ADD_BOX( text, isom_gmhd_t );
791 lsmash_bs_t *bs = file->bs;
792 for( int i = 0; i < 9; i++ )
793 text->matrix[i] = lsmash_bs_get_be32( bs );
794 return isom_read_leaf_box_common_last_process( file, box, level, text );
797 static int isom_read_dinf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
799 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
800 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
801 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
802 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->dinf)
803 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf)
804 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf) )
805 return isom_read_unknown_box( file, box, parent, level );
806 ADD_BOX( dinf, void );
807 isom_box_common_copy( dinf, box );
808 int ret = isom_add_print_func( file, dinf, level );
809 if( ret < 0 )
810 return ret;
811 return isom_read_children( file, box, dinf, level );
814 static int isom_read_dref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
816 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DINF ) || ((isom_dinf_t *)parent)->dref )
817 return isom_read_unknown_box( file, box, parent, level );
818 ADD_BOX( dref, isom_dinf_t );
819 lsmash_bs_t *bs = file->bs;
820 dref->list.entry_count = lsmash_bs_get_be32( bs );
821 isom_box_common_copy( dref, box );
822 int ret = isom_add_print_func( file, dref, level );
823 if( ret < 0 )
824 return ret;
825 return isom_read_children( file, box, dref, level );
828 static int isom_read_dref_entry( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
830 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
831 return isom_read_unknown_box( file, box, parent, level );
832 isom_dref_t *dref = (isom_dref_t *)parent;
833 if( !dref->list.head )
834 dref->list.entry_count = 0; /* discard entry_count gotten from the file */
835 isom_dref_entry_t *ref = isom_add_dref_entry( dref, box->type );
836 if( !ref )
837 return LSMASH_ERR_NAMELESS;
838 lsmash_bs_t *bs = file->bs;
839 if( lsmash_check_box_type_identical( ref->type, ISOM_BOX_TYPE_URL ) )
841 uint64_t pos = lsmash_bs_count( bs );
842 ref->location_length = box->size - pos;
843 if( ref->location_length )
845 ref->location = lsmash_malloc( ref->location_length );
846 if( !ref->location )
847 return LSMASH_ERR_MEMORY_ALLOC;
848 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
849 ref->location[i++] = lsmash_bs_get_byte( bs );
852 if( box->flags & 0x000001 )
853 ref->ref_file = ref->file;
854 box->parent = parent;
855 return isom_read_leaf_box_common_last_process( file, box, level, ref );
858 static int isom_read_stbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
860 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->stbl )
861 return isom_read_unknown_box( file, box, parent, level );
862 ADD_BOX( stbl, isom_minf_t );
863 isom_box_common_copy( stbl, box );
864 int ret = isom_add_print_func( file, stbl, level );
865 if( ret < 0 )
866 return ret;
867 return isom_read_children( file, box, stbl, level );
870 static int isom_read_stsd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
872 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsd )
873 return isom_read_unknown_box( file, box, parent, level );
874 ADD_BOX( stsd, isom_stbl_t );
875 lsmash_bs_t *bs = file->bs;
876 stsd->entry_count = lsmash_bs_get_be32( bs );
877 isom_box_common_copy( stsd, box );
878 int ret = isom_add_print_func( file, stsd, level );
879 if( ret < 0 )
880 return ret;
881 uint64_t stsd_pos = lsmash_bs_count( bs );
882 for( uint32_t i = 0; i < stsd->entry_count || (stsd_pos + ISOM_BASEBOX_COMMON_SIZE) <= stsd->size; i++ )
884 if( (ret = isom_read_box( file, box, (isom_box_t *)stsd, stsd_pos, level )) != 0 )
885 break;
886 stsd_pos += box->size;
887 if( stsd->size <= stsd_pos || bs->eob || bs->error )
888 break;
890 if( stsd->size < stsd_pos )
892 printf( "[stsd] box has extra bytes: %"PRId64"\n", stsd_pos - stsd->size );
893 stsd->size = stsd_pos;
895 box->size = stsd->size;
896 return ret;
899 static int isom_read_codec_specific( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
901 lsmash_bs_t *bs = file->bs;
902 uint64_t opaque_pos = lsmash_bs_count( bs );
903 uint64_t exdata_length = box->size - opaque_pos;
904 if( exdata_length > UINT32_MAX )
905 return LSMASH_ERR_MEMORY_ALLOC;
906 uint8_t *exdata = lsmash_malloc( box->size );
907 if( !exdata )
908 return LSMASH_ERR_MEMORY_ALLOC;
909 int ret = lsmash_bs_get_bytes_ex( bs, exdata_length, exdata + (uintptr_t)opaque_pos );
910 if( ret < 0 )
911 goto fail;
912 LSMASH_SET_BE32( &exdata[0], box->size );
913 LSMASH_SET_BE32( &exdata[4], box->type.fourcc );
914 uintptr_t i = 8;
915 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc )
917 LSMASH_SET_BE32( &exdata[8], box->type.user.fourcc );
918 memcpy( &exdata[12], box->type.user.id, 12 );
919 i += 16;
921 if( box->manager & LSMASH_FULLBOX )
923 LSMASH_SET_BYTE( &exdata[i], box->version );
924 i += 1;
925 LSMASH_SET_BE24( &exdata[i], box->flags );
926 i += 3;
928 if( i != opaque_pos )
930 ret = LSMASH_ERR_INVALID_DATA;
931 goto fail;
933 if( (ret = isom_add_extension_binary( parent, box->type, LSMASH_BOX_PRECEDENCE_N, exdata, box->size )) < 0 )
934 goto fail;
935 isom_box_t *ext = (isom_box_t *)parent->extensions.tail->data;
936 box->manager |= ext->manager;
937 isom_validate_box_size( file->bs, box );
938 isom_basebox_common_copy( ext, box );
939 return isom_add_print_func( file, ext, level );
940 fail:
941 lsmash_free( exdata );
942 return ret;
945 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
947 assert( isom_check_media_hdlr_from_stsd( stsd ) );
948 /* Determine suitable allocation size. */
949 size_t alloc_size = 0;
950 lsmash_media_type media_type = ((isom_mdia_t *)stsd->parent->parent->parent)->hdlr->componentSubtype;
951 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
952 alloc_size = sizeof(isom_visual_entry_t);
953 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
954 alloc_size = sizeof(isom_audio_entry_t);
955 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
957 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
958 alloc_size = sizeof(isom_tx3g_entry_t);
959 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TEXT_TEXT ) )
960 alloc_size = sizeof(isom_qt_text_entry_t);
962 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
963 alloc_size = sizeof(isom_mp4s_entry_t);
964 /* Return allocated memory block if the allocation size is non-zero. */
965 if( alloc_size == 0 )
966 return NULL;
967 return lsmash_malloc_zero( alloc_size );
970 static void *isom_add_description( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
972 void *sample = isom_sample_description_alloc( sample_type, stsd );
973 if( !sample )
974 return NULL;
975 if( lsmash_add_entry( &stsd->list, sample ) < 0 )
977 lsmash_free( sample );
978 return NULL;
980 if( lsmash_add_entry( &stsd->extensions, sample ) < 0 )
982 lsmash_remove_entry_tail( &stsd->list, lsmash_free );
983 return NULL;
985 ((isom_box_t *)sample)->destruct = (isom_extension_destructor_t)isom_remove_sample_description;
986 return sample;
989 static int isom_read_visual_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
991 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
992 return isom_read_unknown_box( file, box, parent, level );
993 isom_visual_entry_t *visual = (isom_visual_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
994 if( !visual )
995 return LSMASH_ERR_MEMORY_ALLOC;
996 lsmash_bs_t *bs = file->bs;
997 for( int i = 0; i < 6; i++ )
998 visual->reserved[i] = lsmash_bs_get_byte( bs );
999 visual->data_reference_index = lsmash_bs_get_be16( bs );
1000 visual->version = lsmash_bs_get_be16( bs );
1001 visual->revision_level = lsmash_bs_get_be16( bs );
1002 visual->vendor = lsmash_bs_get_be32( bs );
1003 visual->temporalQuality = lsmash_bs_get_be32( bs );
1004 visual->spatialQuality = lsmash_bs_get_be32( bs );
1005 visual->width = lsmash_bs_get_be16( bs );
1006 visual->height = lsmash_bs_get_be16( bs );
1007 visual->horizresolution = lsmash_bs_get_be32( bs );
1008 visual->vertresolution = lsmash_bs_get_be32( bs );
1009 visual->dataSize = lsmash_bs_get_be32( bs );
1010 visual->frame_count = lsmash_bs_get_be16( bs );
1011 for( int i = 0; i < 32; i++ )
1012 visual->compressorname[i] = lsmash_bs_get_byte( bs );
1013 visual->depth = lsmash_bs_get_be16( bs );
1014 visual->color_table_ID = lsmash_bs_get_be16( bs );
1015 int ret;
1016 if( visual->color_table_ID == 0
1017 && lsmash_bs_get_pos( bs ) < box->size
1018 && (ret = isom_read_qt_color_table( bs, &visual->color_table )) < 0 )
1019 return ret;
1020 box->parent = parent;
1021 box->manager |= LSMASH_VIDEO_DESCRIPTION;
1022 isom_box_common_copy( visual, box );
1023 if( (ret = isom_add_print_func( file, visual, level )) < 0 )
1024 return ret;
1025 return isom_read_children( file, box, visual, level );
1028 static int isom_read_esds( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1030 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4V_VIDEO )
1031 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO )
1032 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_ENCA_AUDIO )
1033 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_M4AE_AUDIO )
1034 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4S_SYSTEM )
1035 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1036 return isom_read_unknown_box( file, box, parent, level );
1037 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1039 box->type = QT_BOX_TYPE_ESDS;
1040 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO ) )
1041 parent->parent->type = QT_CODEC_TYPE_MP4A_AUDIO;
1043 else
1044 box->type = ISOM_BOX_TYPE_ESDS;
1045 ADD_BOX( esds, void );
1046 lsmash_bs_t *bs = file->bs;
1047 esds->ES = mp4sys_get_descriptor( bs, NULL );
1048 if( !esds->ES )
1049 return LSMASH_ERR_INVALID_DATA;
1050 return isom_read_leaf_box_common_last_process( file, box, level, esds );
1053 static int isom_read_btrt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1055 ADD_BOX( btrt, isom_visual_entry_t );
1056 lsmash_bs_t *bs = file->bs;
1057 btrt->bufferSizeDB = lsmash_bs_get_be32( bs );
1058 btrt->maxBitrate = lsmash_bs_get_be32( bs );
1059 btrt->avgBitrate = lsmash_bs_get_be32( bs );
1060 return isom_read_leaf_box_common_last_process( file, box, level, btrt );
1063 static int isom_read_glbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1065 ADD_BOX( glbl, isom_visual_entry_t );
1066 lsmash_bs_t *bs = file->bs;
1067 uint32_t header_size = box->size - ISOM_BASEBOX_COMMON_SIZE;
1068 if( header_size )
1070 glbl->header_data = lsmash_malloc( header_size );
1071 if( !glbl->header_data )
1072 return LSMASH_ERR_MEMORY_ALLOC;
1073 for( uint32_t i = 0; i < header_size; i++ )
1074 glbl->header_data[i] = lsmash_bs_get_byte( bs );
1076 glbl->header_size = header_size;
1077 return isom_read_leaf_box_common_last_process( file, box, level, glbl );
1080 static int isom_read_clap( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1082 ADD_BOX( clap, isom_visual_entry_t );
1083 lsmash_bs_t *bs = file->bs;
1084 clap->cleanApertureWidthN = lsmash_bs_get_be32( bs );
1085 clap->cleanApertureWidthD = lsmash_bs_get_be32( bs );
1086 clap->cleanApertureHeightN = lsmash_bs_get_be32( bs );
1087 clap->cleanApertureHeightD = lsmash_bs_get_be32( bs );
1088 clap->horizOffN = lsmash_bs_get_be32( bs );
1089 clap->horizOffD = lsmash_bs_get_be32( bs );
1090 clap->vertOffN = lsmash_bs_get_be32( bs );
1091 clap->vertOffD = lsmash_bs_get_be32( bs );
1092 return isom_read_leaf_box_common_last_process( file, box, level, clap );
1095 static int isom_read_pasp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1097 ADD_BOX( pasp, isom_visual_entry_t );
1098 lsmash_bs_t *bs = file->bs;
1099 pasp->hSpacing = lsmash_bs_get_be32( bs );
1100 pasp->vSpacing = lsmash_bs_get_be32( bs );
1101 return isom_read_leaf_box_common_last_process( file, box, level, pasp );
1104 static int isom_read_colr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1106 ADD_BOX( colr, isom_visual_entry_t );
1107 lsmash_bs_t *bs = file->bs;
1108 colr->color_parameter_type = lsmash_bs_get_be32( bs );
1109 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
1110 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1112 colr->primaries_index = lsmash_bs_get_be16( bs );
1113 colr->transfer_function_index = lsmash_bs_get_be16( bs );
1114 colr->matrix_index = lsmash_bs_get_be16( bs );
1115 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1117 if( lsmash_bs_count( bs ) < box->size )
1119 uint8_t temp8 = lsmash_bs_get_byte( bs );
1120 colr->full_range_flag = (temp8 >> 7) & 0x01;
1121 colr->reserved = temp8 & 0x7f;
1123 else
1125 /* It seems this box is broken or incomplete. */
1126 box->manager |= LSMASH_INCOMPLETE_BOX;
1127 colr->full_range_flag = 0;
1128 colr->reserved = 0;
1131 else
1132 box->manager |= LSMASH_QTFF_BASE;
1134 box->type = (box->manager & LSMASH_QTFF_BASE) ? QT_BOX_TYPE_COLR : ISOM_BOX_TYPE_COLR;
1135 return isom_read_leaf_box_common_last_process( file, box, level, colr );
1138 static int isom_read_gama( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1140 ADD_BOX( gama, isom_visual_entry_t );
1141 lsmash_bs_t *bs = file->bs;
1142 gama->level = lsmash_bs_get_be32( bs );
1143 return isom_read_leaf_box_common_last_process( file, box, level, gama );
1146 static int isom_read_fiel( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1148 ADD_BOX( fiel, isom_visual_entry_t );
1149 lsmash_bs_t *bs = file->bs;
1150 fiel->fields = lsmash_bs_get_byte( bs );
1151 fiel->detail = lsmash_bs_get_byte( bs );
1152 return isom_read_leaf_box_common_last_process( file, box, level, fiel );
1155 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1157 ADD_BOX( cspc, isom_visual_entry_t );
1158 lsmash_bs_t *bs = file->bs;
1159 cspc->pixel_format = lsmash_bs_get_be32( bs );
1160 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1163 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1165 ADD_BOX( sgbt, isom_visual_entry_t );
1166 lsmash_bs_t *bs = file->bs;
1167 sgbt->significantBits = lsmash_bs_get_byte( bs );
1168 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1171 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1173 ADD_BOX( stsl, isom_visual_entry_t );
1174 lsmash_bs_t *bs = file->bs;
1175 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1176 stsl->scale_method = lsmash_bs_get_byte( bs );
1177 stsl->display_center_x = lsmash_bs_get_be16( bs );
1178 stsl->display_center_y = lsmash_bs_get_be16( bs );
1179 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1182 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1184 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1185 return isom_read_unknown_box( file, box, parent, level );
1186 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1187 if( !audio )
1188 return LSMASH_ERR_MEMORY_ALLOC;
1189 lsmash_bs_t *bs = file->bs;
1190 for( int i = 0; i < 6; i++ )
1191 audio->reserved[i] = lsmash_bs_get_byte( bs );
1192 audio->data_reference_index = lsmash_bs_get_be16( bs );
1193 audio->version = lsmash_bs_get_be16( bs );
1194 audio->revision_level = lsmash_bs_get_be16( bs );
1195 audio->vendor = lsmash_bs_get_be32( bs );
1196 audio->channelcount = lsmash_bs_get_be16( bs );
1197 audio->samplesize = lsmash_bs_get_be16( bs );
1198 audio->compression_ID = lsmash_bs_get_be16( bs );
1199 audio->packet_size = lsmash_bs_get_be16( bs );
1200 audio->samplerate = lsmash_bs_get_be32( bs );
1201 if( audio->version == 0 && isom_is_qt_audio( box->type ) )
1203 /* Skip weird extra bytes.
1204 * About QTFF, extensions were first added with Sound Sample Description v1. */
1205 while( lsmash_bs_count( bs ) + ISOM_BASEBOX_COMMON_SIZE <= box->size )
1207 uint32_t size = lsmash_bs_show_be32( bs, 0 );
1208 if( size == 0 || lsmash_bs_count( bs ) + size > box->size )
1209 lsmash_bs_skip_bytes( bs, 1 );
1210 else
1211 break;
1214 else if( audio->version == 1 )
1216 if( ((isom_stsd_t *)parent)->version == 0 )
1218 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1219 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1220 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1221 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1222 box->manager |= LSMASH_QTFF_BASE;
1224 else
1225 /* AudioSampleEntryV1 has no additional fields. */
1226 box->manager &= ~LSMASH_QTFF_BASE;
1228 else if( audio->version == 2 )
1230 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1231 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1232 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1233 audio->always7F000000 = lsmash_bs_get_be32( bs );
1234 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1235 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1236 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1237 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1238 box->manager |= LSMASH_QTFF_BASE;
1240 box->parent = parent;
1241 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1242 isom_box_common_copy( audio, box );
1243 int ret = isom_add_print_func( file, audio, level );
1244 if( ret < 0 )
1245 return ret;
1246 return isom_read_children( file, box, audio, level );
1249 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1251 ADD_BOX( wave, isom_audio_entry_t );
1252 isom_box_common_copy( wave, box );
1253 int ret = isom_add_print_func( file, wave, level );
1254 if( ret < 0 )
1255 return ret;
1256 return isom_read_children( file, box, wave, level );
1259 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1261 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->frma )
1262 return isom_read_unknown_box( file, box, parent, level );
1263 ADD_BOX( frma, isom_wave_t );
1264 lsmash_bs_t *bs = file->bs;
1265 frma->data_format = lsmash_bs_get_be32( bs );
1266 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1269 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1271 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->enda )
1272 return isom_read_unknown_box( file, box, parent, level );
1273 ADD_BOX( enda, isom_wave_t );
1274 lsmash_bs_t *bs = file->bs;
1275 enda->littleEndian = lsmash_bs_get_be16( bs );
1276 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1279 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1281 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->terminator )
1282 return isom_read_unknown_box( file, box, parent, level );
1283 ADD_BOX( terminator, isom_wave_t );
1284 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1287 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1289 ADD_BOX( chan, isom_audio_entry_t );
1290 lsmash_bs_t *bs = file->bs;
1291 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1292 chan->channelBitmap = lsmash_bs_get_be32( bs );
1293 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1294 if( chan->numberChannelDescriptions )
1296 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1297 if( !desc )
1298 return LSMASH_ERR_MEMORY_ALLOC;
1299 chan->channelDescriptions = desc;
1300 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1302 desc->channelLabel = lsmash_bs_get_be32( bs );
1303 desc->channelFlags = lsmash_bs_get_be32( bs );
1304 for( int j = 0; j < 3; j++ )
1305 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1308 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1311 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1313 ADD_BOX( srat, isom_audio_entry_t );
1314 lsmash_bs_t *bs = file->bs;
1315 srat->sampling_rate = lsmash_bs_get_be32( bs );
1316 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1319 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1321 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1322 return isom_read_unknown_box( file, box, parent, level );
1323 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1324 if( !text )
1325 return LSMASH_ERR_MEMORY_ALLOC;
1326 lsmash_bs_t *bs = file->bs;
1327 for( int i = 0; i < 6; i++ )
1328 text->reserved[i] = lsmash_bs_get_byte( bs );
1329 text->data_reference_index = lsmash_bs_get_be16( bs );
1330 text->displayFlags = lsmash_bs_get_be32( bs );
1331 text->textJustification = lsmash_bs_get_be32( bs );
1332 for( int i = 0; i < 3; i++ )
1333 text->bgColor[i] = lsmash_bs_get_be16( bs );
1334 text->top = lsmash_bs_get_be16( bs );
1335 text->left = lsmash_bs_get_be16( bs );
1336 text->bottom = lsmash_bs_get_be16( bs );
1337 text->right = lsmash_bs_get_be16( bs );
1338 text->scrpStartChar = lsmash_bs_get_be32( bs );
1339 text->scrpHeight = lsmash_bs_get_be16( bs );
1340 text->scrpAscent = lsmash_bs_get_be16( bs );
1341 text->scrpFont = lsmash_bs_get_be16( bs );
1342 text->scrpFace = lsmash_bs_get_be16( bs );
1343 text->scrpSize = lsmash_bs_get_be16( bs );
1344 for( int i = 0; i < 3; i++ )
1345 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1346 text->font_name_length = lsmash_bs_get_byte( bs );
1347 if( text->font_name_length )
1349 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1350 if( !text->font_name )
1351 return LSMASH_ERR_MEMORY_ALLOC;
1352 for( uint8_t i = 0; i < text->font_name_length; i++ )
1353 text->font_name[i] = lsmash_bs_get_byte( bs );
1354 text->font_name[text->font_name_length] = '\0';
1356 box->parent = parent;
1357 isom_box_common_copy( text, box );
1358 int ret = isom_add_print_func( file, text, level );
1359 if( ret < 0 )
1360 return ret;
1361 return isom_read_children( file, box, text, level );
1364 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1366 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1367 return isom_read_unknown_box( file, box, parent, level );
1368 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1369 if( !tx3g )
1370 return LSMASH_ERR_MEMORY_ALLOC;
1371 lsmash_bs_t *bs = file->bs;
1372 for( int i = 0; i < 6; i++ )
1373 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1374 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1375 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1376 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1377 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1378 for( int i = 0; i < 4; i++ )
1379 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1380 tx3g->top = lsmash_bs_get_be16( bs );
1381 tx3g->left = lsmash_bs_get_be16( bs );
1382 tx3g->bottom = lsmash_bs_get_be16( bs );
1383 tx3g->right = lsmash_bs_get_be16( bs );
1384 tx3g->startChar = lsmash_bs_get_be16( bs );
1385 tx3g->endChar = lsmash_bs_get_be16( bs );
1386 tx3g->font_ID = lsmash_bs_get_be16( bs );
1387 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1388 tx3g->font_size = lsmash_bs_get_byte( bs );
1389 for( int i = 0; i < 4; i++ )
1390 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1391 box->parent = parent;
1392 isom_box_common_copy( tx3g, box );
1393 int ret = isom_add_print_func( file, tx3g, level );
1394 if( ret < 0 )
1395 return ret;
1396 return isom_read_children( file, box, tx3g, level );
1399 static int isom_read_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1401 if( lsmash_check_codec_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1402 return isom_read_qt_text_description( file, box, parent, level );
1403 else if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1404 return isom_read_tx3g_description( file, box, parent, level );
1405 assert( 0 );
1406 return isom_read_unknown_box( file, box, parent, level );
1409 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1411 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1412 || ((isom_tx3g_entry_t *)parent)->ftab )
1413 return isom_read_unknown_box( file, box, parent, level );
1414 ADD_BOX( ftab, isom_tx3g_entry_t );
1415 lsmash_bs_t *bs = file->bs;
1416 uint32_t entry_count = lsmash_bs_get_be16( bs );
1417 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1419 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1420 if( !data )
1421 return LSMASH_ERR_MEMORY_ALLOC;
1422 if( lsmash_add_entry( ftab->list, data ) < 0 )
1424 lsmash_free( data );
1425 return LSMASH_ERR_MEMORY_ALLOC;
1427 data->font_ID = lsmash_bs_get_be16( bs );
1428 data->font_name_length = lsmash_bs_get_byte( bs );
1429 if( data->font_name_length )
1431 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1432 if( !data->font_name )
1433 return LSMASH_ERR_MEMORY_ALLOC;
1434 for( uint8_t i = 0; i < data->font_name_length; i++ )
1435 data->font_name[i] = lsmash_bs_get_byte( bs );
1436 data->font_name[data->font_name_length] = '\0';
1439 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1442 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1444 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1445 return isom_read_unknown_box( file, box, parent, level );
1446 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1447 if( !mp4s )
1448 return LSMASH_ERR_MEMORY_ALLOC;
1449 lsmash_bs_t *bs = file->bs;
1450 for( int i = 0; i < 6; i++ )
1451 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1452 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1453 box->parent = parent;
1454 isom_box_common_copy( mp4s, box );
1455 int ret = isom_add_print_func( file, mp4s, level );
1456 if( ret < 0 )
1457 return ret;
1458 return isom_read_children( file, box, mp4s, level );
1461 static int isom_read_other_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1463 if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
1464 return isom_read_mp4s_description( file, box, parent, level );
1465 return isom_read_unknown_box( file, box, parent, level );
1468 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1470 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stts )
1471 return isom_read_unknown_box( file, box, parent, level );
1472 ADD_BOX( stts, isom_stbl_t );
1473 lsmash_bs_t *bs = file->bs;
1474 uint32_t entry_count = lsmash_bs_get_be32( bs );
1475 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1477 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1478 if( !data )
1479 return LSMASH_ERR_MEMORY_ALLOC;
1480 if( lsmash_add_entry( stts->list, data ) < 0 )
1482 lsmash_free( data );
1483 return LSMASH_ERR_MEMORY_ALLOC;
1485 data->sample_count = lsmash_bs_get_be32( bs );
1486 data->sample_delta = lsmash_bs_get_be32( bs );
1488 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1491 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1493 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->ctts )
1494 return isom_read_unknown_box( file, box, parent, level );
1495 ADD_BOX( ctts, isom_stbl_t );
1496 lsmash_bs_t *bs = file->bs;
1497 uint32_t entry_count = lsmash_bs_get_be32( bs );
1498 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1500 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1501 if( !data )
1502 return LSMASH_ERR_MEMORY_ALLOC;
1503 if( lsmash_add_entry( ctts->list, data ) < 0 )
1505 lsmash_free( data );
1506 return LSMASH_ERR_MEMORY_ALLOC;
1508 data->sample_count = lsmash_bs_get_be32( bs );
1509 data->sample_offset = lsmash_bs_get_be32( bs );
1511 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1514 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1516 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->cslg )
1517 return isom_read_unknown_box( file, box, parent, level );
1518 ADD_BOX( cslg, isom_stbl_t );
1519 lsmash_bs_t *bs = file->bs;
1520 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1521 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1522 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1523 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1524 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1525 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1528 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1530 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stss )
1531 return isom_read_unknown_box( file, box, parent, level );
1532 ADD_BOX( stss, isom_stbl_t );
1533 lsmash_bs_t *bs = file->bs;
1534 uint32_t entry_count = lsmash_bs_get_be32( bs );
1535 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1537 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1538 if( !data )
1539 return LSMASH_ERR_MEMORY_ALLOC;
1540 if( lsmash_add_entry( stss->list, data ) < 0 )
1542 lsmash_free( data );
1543 return LSMASH_ERR_MEMORY_ALLOC;
1545 data->sample_number = lsmash_bs_get_be32( bs );
1547 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1550 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1552 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stps )
1553 return isom_read_unknown_box( file, box, parent, level );
1554 ADD_BOX( stps, isom_stbl_t );
1555 lsmash_bs_t *bs = file->bs;
1556 uint32_t entry_count = lsmash_bs_get_be32( bs );
1557 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1559 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1560 if( !data )
1561 return LSMASH_ERR_MEMORY_ALLOC;
1562 if( lsmash_add_entry( stps->list, data ) < 0 )
1564 lsmash_free( data );
1565 return LSMASH_ERR_MEMORY_ALLOC;
1567 data->sample_number = lsmash_bs_get_be32( bs );
1569 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1572 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1574 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1575 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1576 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && ((isom_stbl_t *)parent)->sdtp)
1577 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && ((isom_traf_t *)parent)->sdtp))
1578 return isom_read_unknown_box( file, box, parent, level );
1579 ADD_BOX( sdtp, isom_box_t );
1580 lsmash_bs_t *bs = file->bs;
1581 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1583 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1584 if( !data )
1585 return LSMASH_ERR_MEMORY_ALLOC;
1586 if( lsmash_add_entry( sdtp->list, data ) < 0 )
1588 lsmash_free( data );
1589 return LSMASH_ERR_MEMORY_ALLOC;
1591 uint8_t temp = lsmash_bs_get_byte( bs );
1592 data->is_leading = (temp >> 6) & 0x3;
1593 data->sample_depends_on = (temp >> 4) & 0x3;
1594 data->sample_is_depended_on = (temp >> 2) & 0x3;
1595 data->sample_has_redundancy = temp & 0x3;
1597 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1600 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1602 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsc )
1603 return isom_read_unknown_box( file, box, parent, level );
1604 ADD_BOX( stsc, isom_stbl_t );
1605 lsmash_bs_t *bs = file->bs;
1606 uint32_t entry_count = lsmash_bs_get_be32( bs );
1607 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1609 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1610 if( !data )
1611 return LSMASH_ERR_MEMORY_ALLOC;
1612 if( lsmash_add_entry( stsc->list, data ) < 0 )
1614 lsmash_free( data );
1615 return LSMASH_ERR_MEMORY_ALLOC;
1617 data->first_chunk = lsmash_bs_get_be32( bs );
1618 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1619 data->sample_description_index = lsmash_bs_get_be32( bs );
1621 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1624 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1626 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsz )
1627 return isom_read_unknown_box( file, box, parent, level );
1628 ADD_BOX( stsz, isom_stbl_t );
1629 lsmash_bs_t *bs = file->bs;
1630 stsz->sample_size = lsmash_bs_get_be32( bs );
1631 stsz->sample_count = lsmash_bs_get_be32( bs );
1632 uint64_t pos = lsmash_bs_count( bs );
1633 if( pos < box->size )
1635 stsz->list = lsmash_create_entry_list();
1636 if( !stsz->list )
1637 return LSMASH_ERR_MEMORY_ALLOC;
1638 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1640 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1641 if( !data )
1642 return LSMASH_ERR_MEMORY_ALLOC;
1643 if( lsmash_add_entry( stsz->list, data ) < 0 )
1645 lsmash_free( data );
1646 return LSMASH_ERR_MEMORY_ALLOC;
1648 data->entry_size = lsmash_bs_get_be32( bs );
1651 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1654 static int isom_read_stz2( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1656 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stz2 )
1657 return isom_read_unknown_box( file, box, parent, level );
1658 ADD_BOX( stz2, isom_stbl_t );
1659 lsmash_bs_t *bs = file->bs;
1660 uint32_t temp32 = lsmash_bs_get_be32( bs );
1661 stz2->reserved = temp32 >> 24;
1662 stz2->field_size = temp32 & 0xff;
1663 stz2->sample_count = lsmash_bs_get_be32( bs );
1664 uint64_t pos = lsmash_bs_count( bs );
1665 if( pos < box->size )
1667 if( stz2->field_size == 16 || stz2->field_size == 8 )
1669 uint64_t (*bs_get_funcs[2])( lsmash_bs_t * ) =
1671 lsmash_bs_get_byte_to_64,
1672 lsmash_bs_get_be16_to_64
1674 uint64_t (*bs_get_entry_size)( lsmash_bs_t * ) = bs_get_funcs[ stz2->field_size == 16 ? 1 : 0 ];
1675 for( ; pos < box->size && stz2->list->entry_count < stz2->sample_count; pos = lsmash_bs_count( bs ) )
1677 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1678 if( !data )
1679 return LSMASH_ERR_MEMORY_ALLOC;
1680 if( lsmash_add_entry( stz2->list, data ) < 0 )
1682 lsmash_free( data );
1683 return LSMASH_ERR_MEMORY_ALLOC;
1685 data->entry_size = bs_get_entry_size( bs );
1688 else if( stz2->field_size == 4 )
1690 int parity = 1;
1691 uint8_t temp8;
1692 while( pos < box->size && stz2->list->entry_count < stz2->sample_count )
1694 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1695 if( !data )
1696 return LSMASH_ERR_MEMORY_ALLOC;
1697 if( lsmash_add_entry( stz2->list, data ) < 0 )
1699 lsmash_free( data );
1700 return LSMASH_ERR_MEMORY_ALLOC;
1702 /* Read a byte by two entries. */
1703 if( parity )
1705 temp8 = lsmash_bs_get_byte( bs );
1706 data->entry_size = (temp8 >> 4) & 0xf;
1708 else
1710 pos = lsmash_bs_count( bs );
1711 data->entry_size = temp8 & 0xf;
1713 parity ^= 1;
1716 else
1717 return LSMASH_ERR_INVALID_DATA;
1719 return isom_read_leaf_box_common_last_process( file, box, level, stz2 );
1722 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1724 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stco )
1725 return isom_read_unknown_box( file, box, parent, level );
1726 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1727 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1728 isom_stco_t *stco = is_stco
1729 ? isom_add_stco( (isom_stbl_t *)parent )
1730 : isom_add_co64( (isom_stbl_t *)parent );
1731 if( !stco )
1732 return LSMASH_ERR_NAMELESS;
1733 lsmash_bs_t *bs = file->bs;
1734 uint32_t entry_count = lsmash_bs_get_be32( bs );
1735 if( is_stco )
1736 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1738 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1739 if( !data )
1740 return LSMASH_ERR_MEMORY_ALLOC;
1741 if( lsmash_add_entry( stco->list, data ) < 0 )
1743 lsmash_free( data );
1744 return LSMASH_ERR_MEMORY_ALLOC;
1746 data->chunk_offset = lsmash_bs_get_be32( bs );
1748 else
1750 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1752 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1753 if( !data )
1754 return LSMASH_ERR_MEMORY_ALLOC;
1755 if( lsmash_add_entry( stco->list, data ) < 0 )
1757 lsmash_free( data );
1758 return LSMASH_ERR_MEMORY_ALLOC;
1760 data->chunk_offset = lsmash_bs_get_be64( bs );
1763 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1766 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1768 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1769 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1770 return isom_read_unknown_box( file, box, parent, level );
1771 ADD_BOX( sgpd, void );
1772 lsmash_bs_t *bs = file->bs;
1773 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1774 if( box->version == 1 )
1775 sgpd->default_length = lsmash_bs_get_be32( bs );
1776 uint32_t entry_count = lsmash_bs_get_be32( bs );
1777 switch( sgpd->grouping_type )
1779 case ISOM_GROUP_TYPE_RAP :
1781 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1783 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1784 if( !data )
1785 return LSMASH_ERR_MEMORY_ALLOC;
1786 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1788 lsmash_free( data );
1789 return LSMASH_ERR_MEMORY_ALLOC;
1791 memset( data, 0, sizeof(isom_rap_entry_t) );
1792 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1793 if( box->version == 1 && !sgpd->default_length )
1794 data->description_length = lsmash_bs_get_be32( bs );
1795 else
1797 uint8_t temp = lsmash_bs_get_byte( bs );
1798 data->num_leading_samples_known = (temp >> 7) & 0x01;
1799 data->num_leading_samples = temp & 0x7f;
1802 break;
1804 case ISOM_GROUP_TYPE_ROLL :
1805 case ISOM_GROUP_TYPE_PROL :
1807 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1809 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1810 if( !data )
1811 return LSMASH_ERR_MEMORY_ALLOC;
1812 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1814 lsmash_free( data );
1815 return LSMASH_ERR_MEMORY_ALLOC;
1817 memset( data, 0, sizeof(isom_roll_entry_t) );
1818 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1819 if( box->version == 1 && !sgpd->default_length )
1820 data->description_length = lsmash_bs_get_be32( bs );
1821 else
1822 data->roll_distance = lsmash_bs_get_be16( bs );
1824 break;
1826 default :
1827 break;
1829 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1832 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1834 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1835 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1836 return isom_read_unknown_box( file, box, parent, level );
1837 ADD_BOX( sbgp, void );
1838 lsmash_bs_t *bs = file->bs;
1839 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1840 if( box->version == 1 )
1841 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1842 uint32_t entry_count = lsmash_bs_get_be32( bs );
1843 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1845 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1846 if( !data )
1847 return LSMASH_ERR_MEMORY_ALLOC;
1848 if( lsmash_add_entry( sbgp->list, data ) < 0 )
1850 lsmash_free( data );
1851 return LSMASH_ERR_MEMORY_ALLOC;
1853 data->sample_count = lsmash_bs_get_be32( bs );
1854 data->group_description_index = lsmash_bs_get_be32( bs );
1856 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1859 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1861 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1862 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1863 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->udta)
1864 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->udta) )
1865 return isom_read_unknown_box( file, box, parent, level );
1866 ADD_BOX( udta, void );
1867 isom_box_common_copy( udta, box );
1868 int ret = isom_add_print_func( file, udta, level );
1869 if( ret < 0 )
1870 return ret;
1871 return isom_read_children( file, box, udta, level );
1874 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1876 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->chpl )
1877 return isom_read_unknown_box( file, box, parent, level );
1878 ADD_BOX( chpl, isom_udta_t );
1879 lsmash_bs_t *bs = file->bs;
1880 uint32_t entry_count;
1881 if( box->version == 1 )
1883 chpl->unknown = lsmash_bs_get_byte( bs );
1884 entry_count = lsmash_bs_get_be32( bs );
1886 else
1887 entry_count = lsmash_bs_get_byte( bs );
1888 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1890 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1891 if( !data )
1892 return LSMASH_ERR_MEMORY_ALLOC;
1893 if( lsmash_add_entry( chpl->list, data ) < 0 )
1895 lsmash_free( data );
1896 return LSMASH_ERR_MEMORY_ALLOC;
1898 data->start_time = lsmash_bs_get_be64( bs );
1899 data->chapter_name_length = lsmash_bs_get_byte( bs );
1900 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1901 if( !data->chapter_name )
1903 lsmash_free( data );
1904 return LSMASH_ERR_MEMORY_ALLOC;
1906 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1907 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1908 data->chapter_name[data->chapter_name_length] = '\0';
1910 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1913 static int isom_read_mvex( 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_MOOV ) || ((isom_moov_t *)parent)->mvex )
1916 return isom_read_unknown_box( file, box, parent, level );
1917 ADD_BOX( mvex, isom_moov_t );
1918 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1919 isom_box_common_copy( mvex, box );
1920 int ret = isom_add_print_func( file, mvex, level );
1921 if( ret < 0 )
1922 return ret;
1923 return isom_read_children( file, box, mvex, level );
1926 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1928 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) || ((isom_mvex_t *)parent)->mehd )
1929 return isom_read_unknown_box( file, box, parent, level );
1930 ADD_BOX( mehd, isom_mvex_t );
1931 lsmash_bs_t *bs = file->bs;
1932 if( box->version == 1 )
1933 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1934 else
1935 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1936 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1939 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1941 uint32_t temp = lsmash_bs_get_be32( bs );
1942 isom_sample_flags_t flags;
1943 flags.reserved = (temp >> 28) & 0xf;
1944 flags.is_leading = (temp >> 26) & 0x3;
1945 flags.sample_depends_on = (temp >> 24) & 0x3;
1946 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1947 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1948 flags.sample_padding_value = (temp >> 17) & 0x7;
1949 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1950 flags.sample_degradation_priority = temp & 0xffff;
1951 return flags;
1954 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1956 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
1957 return isom_read_unknown_box( file, box, parent, level );
1958 ADD_BOX( trex, isom_mvex_t );
1959 box->parent = parent;
1960 lsmash_bs_t *bs = file->bs;
1961 trex->track_ID = lsmash_bs_get_be32( bs );
1962 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
1963 trex->default_sample_duration = lsmash_bs_get_be32( bs );
1964 trex->default_sample_size = lsmash_bs_get_be32( bs );
1965 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
1966 return isom_read_leaf_box_common_last_process( file, box, level, trex );
1969 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1971 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
1972 return isom_read_unknown_box( file, box, parent, level );
1973 ADD_BOX( moof, lsmash_file_t );
1974 box->parent = parent;
1975 isom_box_common_copy( moof, box );
1976 int ret = isom_add_print_func( file, moof, level );
1977 if( ret < 0 )
1978 return ret;
1979 return isom_read_children( file, box, moof, level );
1982 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1984 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) || ((isom_moof_t *)parent)->mfhd )
1985 return isom_read_unknown_box( file, box, parent, level );
1986 ADD_BOX( mfhd, isom_moof_t );
1987 lsmash_bs_t *bs = file->bs;
1988 mfhd->sequence_number = lsmash_bs_get_be32( bs );
1989 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
1992 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1994 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
1995 return isom_read_unknown_box( file, box, parent, level );
1996 ADD_BOX( traf, isom_moof_t );
1997 box->parent = parent;
1998 isom_box_common_copy( traf, box );
1999 int ret = isom_add_print_func( file, traf, level );
2000 if( ret < 0 )
2001 return ret;
2002 return isom_read_children( file, box, traf, level );
2005 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2007 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfhd )
2008 return isom_read_unknown_box( file, box, parent, level );
2009 ADD_BOX( tfhd, isom_traf_t );
2010 lsmash_bs_t *bs = file->bs;
2011 tfhd->track_ID = lsmash_bs_get_be32( bs );
2012 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2013 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2014 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2015 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2016 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2017 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2020 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2022 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfdt )
2023 return isom_read_unknown_box( file, box, parent, level );
2024 ADD_BOX( tfdt, isom_traf_t );
2025 lsmash_bs_t *bs = file->bs;
2026 if( box->version == 1 )
2027 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2028 else
2029 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2030 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2033 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2035 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2036 return isom_read_unknown_box( file, box, parent, level );
2037 ADD_BOX( trun, isom_traf_t );
2038 box->parent = parent;
2039 lsmash_bs_t *bs = file->bs;
2040 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2041 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2042 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2043 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2044 has_optional_rows &= box->flags;
2045 trun->sample_count = lsmash_bs_get_be32( bs );
2046 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2047 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2048 if( trun->sample_count && has_optional_rows )
2050 trun->optional = lsmash_create_entry_list();
2051 if( !trun->optional )
2052 return LSMASH_ERR_MEMORY_ALLOC;
2053 for( uint32_t i = 0; i < trun->sample_count; i++ )
2055 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2056 if( !data )
2057 return LSMASH_ERR_MEMORY_ALLOC;
2058 if( lsmash_add_entry( trun->optional, data ) < 0 )
2060 lsmash_free( data );
2061 return LSMASH_ERR_MEMORY_ALLOC;
2063 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2064 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2065 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2066 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2069 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2072 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2074 if( file->fake_file_mode )
2075 return isom_read_unknown_box( file, box, parent, level );
2076 isom_box_t *skip = lsmash_malloc_zero( sizeof(isom_box_t) );
2077 if( !skip )
2078 return LSMASH_ERR_MEMORY_ALLOC;
2079 isom_skip_box_rest( file->bs, box );
2080 box->manager |= LSMASH_ABSENT_IN_FILE;
2081 isom_box_common_copy( skip, box );
2082 int ret = isom_add_print_func( file, skip, level );
2083 if( ret < 0 )
2085 lsmash_free( skip );
2086 return ret;
2088 return 0;
2091 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2093 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2094 return isom_read_unknown_box( file, box, parent, level );
2095 isom_box_t *mdat = lsmash_malloc_zero( sizeof(isom_box_t) );
2096 if( !mdat )
2097 return LSMASH_ERR_MEMORY_ALLOC;
2098 isom_skip_box_rest( file->bs, box );
2099 box->manager |= LSMASH_ABSENT_IN_FILE;
2100 file->flags |= LSMASH_FILE_MODE_MEDIA;
2101 isom_box_common_copy( mdat, box );
2102 int ret = isom_add_print_func( file, mdat, level );
2103 if( ret < 0 )
2105 lsmash_free( mdat );
2106 return ret;
2108 return 0;
2111 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2113 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2114 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2115 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2116 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2117 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && ((lsmash_file_t *)parent)->meta)
2118 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->meta)
2119 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->meta)
2120 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && ((isom_udta_t *)parent)->meta) )
2121 return isom_read_unknown_box( file, box, parent, level );
2122 ADD_BOX( meta, void );
2123 isom_box_common_copy( meta, box );
2124 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2125 if( is_qtff )
2127 box->manager |= LSMASH_QTFF_BASE;
2128 meta->manager |= LSMASH_QTFF_BASE;
2130 int ret = isom_add_print_func( file, meta, level );
2131 if( ret < 0 )
2132 return ret;
2133 return isom_read_children( file, box, meta, level );
2136 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2138 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2139 || ((isom_meta_t *)parent)->keys )
2140 return isom_read_unknown_box( file, box, parent, level );
2141 ADD_BOX( keys, isom_meta_t );
2142 lsmash_bs_t *bs = file->bs;
2143 uint32_t entry_count = lsmash_bs_get_be32( bs );
2144 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2146 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2147 if( !data )
2148 return LSMASH_ERR_MEMORY_ALLOC;
2149 if( lsmash_add_entry( keys->list, data ) < 0 )
2151 lsmash_free( data );
2152 return LSMASH_ERR_MEMORY_ALLOC;
2154 data->key_size = lsmash_bs_get_be32( bs );
2155 data->key_namespace = lsmash_bs_get_be32( bs );
2156 if( data->key_size > 8 )
2158 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2159 if( !data->key_value )
2160 return LSMASH_ERR_NAMELESS;
2162 else
2163 data->key_value = NULL;
2165 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2168 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2170 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2171 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2172 || ((isom_meta_t *)parent)->ilst )
2173 return isom_read_unknown_box( file, box, parent, level );
2174 ADD_BOX( ilst, isom_meta_t );
2175 isom_box_common_copy( ilst, box );
2176 int ret = isom_add_print_func( file, ilst, level );
2177 if( ret < 0 )
2178 return ret;
2179 return isom_read_children( file, box, ilst, level );
2182 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2184 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2185 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2186 return isom_read_unknown_box( file, box, parent, level );
2187 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2188 if( !metaitem )
2189 return -1;
2190 box->parent = parent;
2191 isom_box_common_copy( metaitem, box );
2192 int ret = isom_add_print_func( file, metaitem, level );
2193 if( ret < 0 )
2194 return ret;
2195 return isom_read_children( file, box, metaitem, level );
2198 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2200 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->mean )
2201 return isom_read_unknown_box( file, box, parent, level );
2202 ADD_BOX( mean, isom_metaitem_t );
2203 lsmash_bs_t *bs = file->bs;
2204 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2205 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2206 if( !mean->meaning_string )
2207 return LSMASH_ERR_NAMELESS;
2208 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2211 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2213 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->name )
2214 return isom_read_unknown_box( file, box, parent, level );
2215 ADD_BOX( name, isom_metaitem_t );
2216 lsmash_bs_t *bs = file->bs;
2217 name->name_length = box->size - lsmash_bs_count( bs );
2218 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2219 if( !name->name )
2220 return LSMASH_ERR_NAMELESS;
2221 return isom_read_leaf_box_common_last_process( file, box, level, name );
2224 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2226 if( ((isom_metaitem_t *)parent)->data )
2227 return isom_read_unknown_box( file, box, parent, level );
2228 ADD_BOX( data, isom_metaitem_t );
2229 lsmash_bs_t *bs = file->bs;
2230 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2231 data->reserved = lsmash_bs_get_be16( bs );
2232 data->type_set_identifier = lsmash_bs_get_byte( bs );
2233 data->type_code = lsmash_bs_get_byte( bs );
2234 data->the_locale = lsmash_bs_get_be32( bs );
2235 if( data->value_length )
2237 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2238 if( !data->value )
2239 return LSMASH_ERR_NAMELESS;
2241 return isom_read_leaf_box_common_last_process( file, box, level, data );
2244 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2246 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->WLOC )
2247 return isom_read_unknown_box( file, box, parent, level );
2248 ADD_BOX( WLOC, isom_udta_t );
2249 lsmash_bs_t *bs = file->bs;
2250 WLOC->x = lsmash_bs_get_be16( bs );
2251 WLOC->y = lsmash_bs_get_be16( bs );
2252 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2255 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2257 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->LOOP )
2258 return isom_read_unknown_box( file, box, parent, level );
2259 ADD_BOX( LOOP, isom_udta_t );
2260 lsmash_bs_t *bs = file->bs;
2261 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2262 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2265 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2267 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->SelO )
2268 return isom_read_unknown_box( file, box, parent, level );
2269 ADD_BOX( SelO, isom_udta_t );
2270 lsmash_bs_t *bs = file->bs;
2271 SelO->selection_only = lsmash_bs_get_byte( bs );
2272 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2275 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2277 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->AllF )
2278 return isom_read_unknown_box( file, box, parent, level );
2279 ADD_BOX( AllF, isom_udta_t );
2280 lsmash_bs_t *bs = file->bs;
2281 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2282 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2285 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2287 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2288 return isom_read_unknown_box( file, box, parent, level );
2289 ADD_BOX( cprt, isom_udta_t );
2290 box->parent = parent;
2291 lsmash_bs_t *bs = file->bs;
2292 cprt->language = lsmash_bs_get_be16( bs );
2293 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2294 if( cprt->notice_length )
2296 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2297 if( !cprt->notice )
2299 cprt->notice_length = 0;
2300 return LSMASH_ERR_NAMELESS;
2303 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2306 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2308 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->mfra )
2309 return isom_read_unknown_box( file, box, parent, level );
2310 ADD_BOX( mfra, lsmash_file_t );
2311 isom_box_common_copy( mfra, box );
2312 int ret = isom_add_print_func( file, mfra, level );
2313 if( ret < 0 )
2314 return ret;
2315 return isom_read_children( file, box, mfra, level );
2318 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2320 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2321 return isom_read_unknown_box( file, box, parent, level );
2322 ADD_BOX( tfra, isom_mfra_t );
2323 box->parent = parent;
2324 lsmash_bs_t *bs = file->bs;
2325 tfra->track_ID = lsmash_bs_get_be32( bs );
2326 uint32_t temp = lsmash_bs_get_be32( bs );
2327 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2328 tfra->reserved = (temp >> 6) & 0x3ffffff;
2329 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2330 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2331 tfra->length_size_of_sample_num = temp & 0x3;
2332 if( tfra->number_of_entry )
2334 tfra->list = lsmash_create_entry_list();
2335 if( !tfra->list )
2336 return LSMASH_ERR_MEMORY_ALLOC;
2337 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2339 lsmash_bs_get_byte_to_64,
2340 lsmash_bs_get_be16_to_64,
2341 lsmash_bs_get_be24_to_64,
2342 lsmash_bs_get_be32_to_64,
2343 lsmash_bs_get_be64
2345 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2346 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2347 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2348 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2349 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2350 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2352 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2353 if( !data )
2354 return LSMASH_ERR_MEMORY_ALLOC;
2355 if( lsmash_add_entry( tfra->list, data ) < 0 )
2357 lsmash_free( data );
2358 return LSMASH_ERR_MEMORY_ALLOC;
2360 data->time = bs_put_time ( bs );
2361 data->moof_offset = bs_put_moof_offset ( bs );
2362 data->traf_number = bs_put_traf_number ( bs );
2363 data->trun_number = bs_put_trun_number ( bs );
2364 data->sample_number = bs_put_sample_number( bs );
2367 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2370 static int isom_read_mfro( 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 ) || ((isom_mfra_t *)parent)->mfro )
2373 return isom_read_unknown_box( file, box, parent, level );
2374 ADD_BOX( mfro, isom_mfra_t );
2375 lsmash_bs_t *bs = file->bs;
2376 mfro->length = lsmash_bs_get_be32( bs );
2377 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2380 static void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2382 if( !bs->unseekable )
2384 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2385 while( size > (INT64_MAX >> 1) )
2387 lsmash_bs_read_seek( bs, INT64_MAX >> 1, SEEK_CUR );
2388 if( lsmash_bs_is_end( bs, 0 ) )
2389 return;
2390 size -= (INT64_MAX >> 1);
2392 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2394 else
2395 lsmash_bs_skip_bytes_64( bs, size );
2398 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2400 lsmash_bs_t *bs = file->bs;
2401 /* Skip extra bytes of the parent box if any. */
2402 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2404 uint64_t extra_bytes = parent->size - parent_pos;
2405 isom_read_skip_extra_bytes( bs, extra_bytes );
2406 /* This is not the size of a box but makes sense in isom_read_children(). */
2407 box->size = extra_bytes;
2408 return 1;
2410 /* Check if the size is valid or not. */
2411 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2413 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2414 if( size > 1
2415 && size < ISOM_BASEBOX_COMMON_SIZE )
2417 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2418 * Skip bytes up to the next box of the parent box. */
2419 uint64_t extra_bytes = parent->size - parent_pos;
2420 isom_read_skip_extra_bytes( bs, extra_bytes );
2421 box->size = extra_bytes;
2422 return 1;
2424 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2425 size = lsmash_bs_show_be64( bs, 8 ); /* large size */
2426 if( size == 0 && parent != (isom_box_t *)file )
2428 /* Check if this box is actually the last box or not. */
2429 uint64_t extra_bytes = parent->size - parent_pos;
2430 if( !bs->unseekable )
2431 size = bs->written - lsmash_bs_get_stream_pos( bs );
2432 else
2434 size = lsmash_bs_get_remaining_buffer_size( bs );
2435 while( size <= extra_bytes )
2437 int ret = lsmash_bs_read( bs, 1 );
2438 if( bs->eof || ret < 0 )
2439 break;
2440 size = lsmash_bs_get_remaining_buffer_size( bs );
2443 if( size != extra_bytes )
2445 /* This is not the size of the last box.
2446 * It seems we are still within the box considered as the previous or the parent box.
2447 * Skip bytes up to the next box. */
2448 if( box->size > lsmash_bs_count( bs ) )
2450 /* within the previous */
2451 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2452 box->size = 0; /* already added to the size of the parent box */
2454 else
2456 /* within the parent */
2457 isom_read_skip_extra_bytes( bs, extra_bytes );
2458 box->size = extra_bytes;
2460 return 1;
2464 return 0;
2467 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2469 assert( parent && parent->root && parent->file );
2470 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2471 return 0;
2472 memset( box, 0, sizeof(isom_box_t) );
2473 box->root = parent->root;
2474 box->file = parent->file;
2475 box->parent = parent;
2476 lsmash_bs_t *bs = file->bs;
2477 int ret = isom_bs_read_box_common( bs, box );
2478 if( !!ret )
2479 return ret; /* return if reached EOF */
2480 ++level;
2481 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2482 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2483 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2485 /* OK, this box is a sample entry.
2486 * Here, determine the suitable sample entry reader by media type if possible. */
2487 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
2488 goto read_box;
2489 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
2490 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2491 reader_func = isom_read_visual_description;
2492 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2493 reader_func = isom_read_audio_description;
2494 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2495 reader_func = isom_read_text_description;
2496 else
2497 reader_func = isom_read_other_description;
2498 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2499 static struct description_reader_table_tag
2501 lsmash_compact_box_type_t fourcc;
2502 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2503 } description_reader_table[160] = { { 0, NULL } };
2504 if( !description_reader_table[0].form_box_type_func )
2506 /* Initialize the table. */
2507 int i = 0;
2508 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2509 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2510 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type );
2511 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type );
2512 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type );
2513 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type );
2514 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type );
2515 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type );
2516 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type );
2517 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type );
2518 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type );
2519 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type );
2520 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type );
2521 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type );
2522 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type );
2523 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type );
2524 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type );
2525 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type );
2526 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type );
2527 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type );
2528 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type );
2529 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type );
2530 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type );
2531 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type );
2532 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type );
2533 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type );
2534 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type );
2535 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type );
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type );
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type );
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type );
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type );
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type );
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type );
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type );
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type );
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type );
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type );
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type );
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type );
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type );
2549 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO, lsmash_form_qtff_box_type );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type );
2551 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type );
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type );
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type );
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type );
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type );
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type );
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type );
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type );
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type );
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type );
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type );
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type );
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type );
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type );
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO, lsmash_form_qtff_box_type );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type );
2608 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type );
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type );
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type );
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW, lsmash_form_qtff_box_type );
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL );
2644 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2646 for( int i = 0; description_reader_table[i].form_box_type_func; i++ )
2647 if( box->type.fourcc == description_reader_table[i].fourcc )
2649 form_box_type_func = description_reader_table[i].form_box_type_func;
2650 goto read_box;
2652 goto read_box;
2654 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2656 form_box_type_func = lsmash_form_qtff_box_type;
2657 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2658 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2659 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2660 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2661 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2662 else reader_func = isom_read_codec_specific;
2663 goto read_box;
2665 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2667 form_box_type_func = lsmash_form_iso_box_type;
2668 reader_func = isom_read_track_reference_type;
2669 goto read_box;
2671 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2673 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2674 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2675 form_box_type_func = lsmash_form_iso_box_type;
2676 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2677 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2678 form_box_type_func = lsmash_form_qtff_box_type;
2679 reader_func = isom_read_dref_entry;
2680 goto read_box;
2682 static struct box_reader_table_tag
2684 lsmash_compact_box_type_t fourcc;
2685 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2686 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2687 } box_reader_table[128] = { { 0, NULL, NULL } };
2688 if( !box_reader_table[0].reader_func )
2690 /* Initialize the table. */
2691 int i = 0;
2692 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2693 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2694 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2695 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2696 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2697 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2698 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2699 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2700 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2701 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2702 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2703 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2704 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2705 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2706 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2707 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2708 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2709 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2710 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2711 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2712 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2713 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2714 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2715 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2716 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2717 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2718 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2719 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2720 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2721 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2722 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2724 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2726 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2727 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2728 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2729 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2730 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2731 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2732 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2733 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2734 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2735 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2736 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2737 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2738 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2739 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2740 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2741 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2742 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2743 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2744 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2745 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2746 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2747 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2748 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, lsmash_form_iso_box_type, isom_read_stz2 );
2749 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2750 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2753 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2754 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2755 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2756 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2757 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2758 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2760 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2761 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2762 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2763 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2769 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2771 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2773 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2774 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2775 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2776 #undef ADD_BOX_READER_TABLE_ELEMENT
2778 for( int i = 0; box_reader_table[i].reader_func; i++ )
2779 if( box->type.fourcc == box_reader_table[i].fourcc )
2781 form_box_type_func = box_reader_table[i].form_box_type_func;
2782 reader_func = box_reader_table[i].reader_func;
2783 goto read_box;
2785 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2787 if( lsmash_bs_is_end ( bs, 3 ) == 0
2788 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2789 form_box_type_func = lsmash_form_iso_box_type;
2790 else
2791 form_box_type_func = lsmash_form_qtff_box_type;
2792 reader_func = isom_read_meta;
2793 goto read_box;
2795 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2797 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2798 form_box_type_func = lsmash_form_iso_box_type;
2799 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2800 form_box_type_func = lsmash_form_qtff_box_type;
2801 if( form_box_type_func )
2803 reader_func = isom_read_ilst;
2804 goto read_box;
2807 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2808 form_box_type_func = lsmash_form_iso_box_type;
2809 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2810 form_box_type_func = lsmash_form_qtff_box_type;
2811 if( form_box_type_func )
2813 reader_func = isom_read_metaitem;
2814 goto read_box;
2816 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2818 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2819 reader_func = isom_read_mean;
2820 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2821 reader_func = isom_read_name;
2822 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2823 reader_func = isom_read_data;
2824 if( reader_func )
2826 form_box_type_func = lsmash_form_iso_box_type;
2827 goto read_box;
2830 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2832 /* Avoid confusing udta.cprt with ilst.cprt. */
2833 form_box_type_func = lsmash_form_iso_box_type;
2834 reader_func = isom_read_cprt;
2835 goto read_box;
2837 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2839 static struct codec_specific_marker_table_tag
2841 lsmash_compact_box_type_t fourcc;
2842 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2843 } codec_specific_marker_table[16] = { { 0, NULL } };
2844 if( !codec_specific_marker_table[0].form_box_type_func )
2846 /* Initialize the table. */
2847 int i = 0;
2848 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2849 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2850 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type );
2851 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type );
2852 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type );
2853 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type );
2854 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type );
2855 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type );
2856 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type );
2857 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type );
2858 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type );
2859 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type );
2860 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2861 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2863 for( int i = 0; codec_specific_marker_table[i].form_box_type_func; i++ )
2864 if( box->type.fourcc == codec_specific_marker_table[i].fourcc )
2866 form_box_type_func = codec_specific_marker_table[i].form_box_type_func;
2867 break;
2869 reader_func = isom_read_codec_specific;
2871 read_box:
2872 if( form_box_type_func )
2873 box->type = form_box_type_func( box->type.fourcc );
2874 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2875 return ret;
2876 return reader_func
2877 ? reader_func( file, box, parent, level )
2878 : isom_read_unknown_box( file, box, parent, level );
2881 int isom_read_file( lsmash_file_t *file )
2883 lsmash_bs_t *bs = file->bs;
2884 if( !bs )
2885 return LSMASH_ERR_NAMELESS;
2886 /* Reset the counter so that we can use it to get position within the box. */
2887 lsmash_bs_reset_counter( bs );
2888 if( file->flags & LSMASH_FILE_MODE_DUMP )
2890 file->print = lsmash_create_entry_list();
2891 if( !file->print )
2892 return LSMASH_ERR_MEMORY_ALLOC;
2894 file->size = UINT64_MAX;
2895 isom_box_t box;
2896 int ret = isom_read_children( file, &box, file, 0 );
2897 file->size = box.size;
2898 lsmash_bs_empty( bs );
2899 bs->error = 0; /* Clear error flag. */
2900 if( ret < 0 )
2901 return ret;
2902 return isom_check_compatibility( file );