list: Decide the entry eliminator of list at its initialization.
[L-SMASH.git] / core / read.c
blobfdbbf9f7d9d1ebb1c186fa136734e5e9a4dda301
1 /*****************************************************************************
2 * read.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "box.h"
30 #include "box_default.h"
31 #include "file.h"
32 #include "print.h"
33 #include "read.h"
34 #include "write.h"
36 #include "codecs/mp4a.h"
37 #include "codecs/mp4sys.h"
38 #include "codecs/description.h"
40 static int isom_bs_read_box_common( lsmash_bs_t *bs, isom_box_t *box )
42 assert( bs && box && box->file );
43 /* Reset the counter so that we can use it to get position within the box. */
44 lsmash_bs_reset_counter( bs );
45 /* Read the common fields of box. */
46 box->pos = lsmash_bs_get_stream_pos( bs );
47 if( bs->eob )
48 /* No more read. */
49 return 1;
50 /* Read size and type. */
51 box->size = lsmash_bs_get_be32( bs );
52 box->type.fourcc = lsmash_bs_get_be32( bs );
53 /* If size is set to 1, the actual size is repersented in the next 8 bytes.
54 * If size is set to 0, this box ends at the end of the stream. */
55 if( box->size == 1 )
56 box->size = lsmash_bs_get_be64( bs );
57 if( box->size == 0 )
59 /* This box is the last box in the stream. */
60 box->manager |= LSMASH_LAST_BOX;
61 if( !bs->unseekable )
62 box->size = bs->written - (lsmash_bs_get_stream_pos( bs ) - lsmash_bs_count( bs ));
63 else
64 /* We haven't known the box size yet.
65 * To get the box size, read the stream until the end of the stream. */
66 while( 1 )
68 int ret = lsmash_bs_read( bs, 1 );
69 if( bs->eof || ret < 0 )
71 /* OK, now we know the box size. */
72 box->size = lsmash_bs_count( bs ) + lsmash_bs_get_remaining_buffer_size( bs );
73 if( ret < 0 )
74 /* This box may end incompletely at the end of the stream. */
75 box->manager |= LSMASH_INCOMPLETE_BOX;
76 break;
80 /* Here, we don't set up extended box type fields if this box is not a UUID Box. */
81 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc
82 && box->size >= lsmash_bs_count( bs ) + 16 )
84 /* Get UUID. */
85 lsmash_box_type_t *type = &box->type;
86 uint64_t temp64 = lsmash_bs_get_be64( bs );
87 type->user.fourcc = (temp64 >> 32) & 0xffffffff;
88 LSMASH_SET_BE32( &type->user.id[0], temp64 );
89 temp64 = lsmash_bs_get_be64( bs );
90 LSMASH_SET_BE64( &type->user.id[4], temp64 );
92 return bs->eob;
95 static int isom_read_fullbox_common_extension( lsmash_bs_t *bs, isom_box_t *box )
97 if( !isom_is_fullbox( box ) )
98 return 0;
99 /* Get version and flags. */
100 box->version = lsmash_bs_get_byte( bs );
101 box->flags = lsmash_bs_get_be24( bs );
102 box->manager |= LSMASH_FULLBOX;
103 return 0;
106 /* Don't copy destructor since a destructor is defined as box specific. */
107 static void isom_basebox_common_copy( isom_box_t *dst, const isom_box_t *src )
109 dst->root = src->root;
110 dst->file = src->file;
111 dst->parent = src->parent;
112 dst->manager = src->manager;
113 dst->pos = src->pos;
114 dst->size = src->size;
115 dst->type = src->type;
118 static void isom_fullbox_common_copy( isom_box_t *dst, const isom_box_t *src )
120 dst->root = src->root;
121 dst->file = src->file;
122 dst->parent = src->parent;
123 dst->manager = src->manager;
124 dst->pos = src->pos;
125 dst->size = src->size;
126 dst->type = src->type;
127 dst->version = src->version;
128 dst->flags = src->flags;
131 static void isom_box_common_copy( void *dst, const void *src )
133 assert( LSMASH_IS_EXISTING_BOX( (isom_box_t *)dst )
134 && LSMASH_IS_EXISTING_BOX( (isom_box_t *)src ) );
135 if( lsmash_check_box_type_identical( ((isom_box_t *)src)->type, ISOM_BOX_TYPE_STSD ) )
137 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
138 return;
140 if( isom_is_fullbox( src ) )
141 isom_fullbox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
142 else
143 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
146 static void isom_skip_box_rest( lsmash_bs_t *bs, isom_box_t *box )
148 if( box->manager & LSMASH_LAST_BOX )
150 box->size = (box->manager & LSMASH_FULLBOX) ? ISOM_FULLBOX_COMMON_SIZE : ISOM_BASEBOX_COMMON_SIZE;
151 uint64_t start = lsmash_bs_get_stream_pos( bs );
152 if( !bs->unseekable )
153 lsmash_bs_read_seek( bs, 0, SEEK_END );
154 else
155 while( !bs->eob )
156 lsmash_bs_skip_bytes( bs, UINT32_MAX );
157 uint64_t end = lsmash_bs_get_stream_pos( bs );
158 box->size += end - start;
159 return;
161 uint64_t skip_bytes = box->size - lsmash_bs_count( bs );
162 if( !bs->unseekable )
164 /* The stream is seekable. So, skip by seeking the stream. */
165 uint64_t start = lsmash_bs_get_stream_pos( bs );
166 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
167 uint64_t end = lsmash_bs_get_stream_pos( bs );
168 if( end - start != skip_bytes )
169 /* not match size */
170 box->manager |= LSMASH_INCOMPLETE_BOX;
171 return;
173 /* The stream is unseekable. So, skip by reading the stream. */
174 lsmash_bs_skip_bytes_64( bs, skip_bytes );
175 if( box->size > lsmash_bs_count( bs ) )
176 box->manager |= LSMASH_INCOMPLETE_BOX;
179 static void isom_validate_box_size( lsmash_bs_t *bs, isom_box_t *box )
181 uint64_t pos = lsmash_bs_count( bs );
182 if( box->manager & LSMASH_LAST_BOX )
184 box->size = pos;
185 return;
187 if( box->size < pos )
189 fprintf( stderr, "[%s] box has less bytes than expected: %"PRId64"\n", isom_4cc2str( box->type.fourcc ), pos - box->size );
190 box->size = pos;
192 else if( box->size > pos )
194 /* The box probably has extra padding bytes at the end. */
195 fprintf( stderr, "[%s] box has more bytes than expected: %"PRId64"\n", isom_4cc2str( box->type.fourcc ), box->size - pos );
196 isom_skip_box_rest( bs, box );
200 static int isom_read_children( lsmash_file_t *file, isom_box_t *box, void *parent, int level )
202 int ret;
203 lsmash_bs_t *bs = file->bs;
204 isom_box_t *parent_box = (isom_box_t *)parent;
205 uint64_t parent_pos = lsmash_bs_count( bs );
206 while( !(ret = isom_read_box( file, box, parent_box, parent_pos, level )) )
208 parent_pos += box->size;
209 if( parent_box->size <= parent_pos || bs->eob || bs->error )
210 break;
212 box->size = parent_pos; /* for file size */
213 return ret;
216 static int isom_read_leaf_box_common_last_process( lsmash_file_t *file, isom_box_t *box, int level, void *instance )
218 isom_validate_box_size( file->bs, box );
219 isom_box_common_copy( instance, box );
220 return isom_add_print_func( file, instance, level );
223 static int isom_read_unknown_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
225 lsmash_bs_t *bs = file->bs;
226 uint64_t read_size = box->size - lsmash_bs_count( bs );
227 if( box->manager & LSMASH_INCOMPLETE_BOX )
228 return LSMASH_ERR_INVALID_DATA;
229 isom_unknown_box_t *unknown = ALLOCATE_BOX( unknown );
230 if( LSMASH_IS_NON_EXISTING_BOX( unknown ) )
231 return LSMASH_ERR_MEMORY_ALLOC;
232 if( lsmash_list_add_entry( &parent->extensions, unknown ) < 0 )
234 isom_remove_box_by_itself( unknown );
235 return LSMASH_ERR_MEMORY_ALLOC;
237 isom_box_common_copy( unknown, box );
238 unknown->manager |= LSMASH_UNKNOWN_BOX;
239 unknown->destruct = (isom_extension_destructor_t)isom_remove_unknown_box;
240 isom_set_box_writer( (isom_box_t *)unknown );
241 if( read_size )
243 unknown->unknown_field = lsmash_bs_get_bytes( bs, read_size );
244 if( unknown->unknown_field )
245 unknown->unknown_size = read_size;
246 else
247 unknown->manager |= LSMASH_INCOMPLETE_BOX;
249 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
250 return 0;
251 /* Create a dummy for dump. */
252 isom_dummy_t *dummy = ALLOCATE_BOX( dummy );
253 if( LSMASH_IS_NON_EXISTING_BOX( dummy ) )
254 return LSMASH_ERR_MEMORY_ALLOC;
255 box->manager |= LSMASH_ABSENT_IN_FILE | LSMASH_UNKNOWN_BOX;
256 isom_box_common_copy( dummy, box );
257 int ret = isom_add_print_func( file, dummy, level );
258 if( ret < 0 )
260 isom_remove_box_by_itself( dummy );
261 return ret;
263 return 0;
266 #define ADD_BOX( box_name, parent_type ) \
267 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
268 if( LSMASH_IS_NON_EXISTING_BOX( box_name ) ) \
269 return LSMASH_ERR_NAMELESS
271 static int isom_read_ftyp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
273 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
274 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->ftyp ) )
275 return isom_read_unknown_box( file, box, parent, level );
276 ADD_BOX( ftyp, lsmash_file_t );
277 lsmash_bs_t *bs = file->bs;
278 ftyp->major_brand = lsmash_bs_get_be32( bs );
279 ftyp->minor_version = lsmash_bs_get_be32( bs );
280 uint64_t pos = lsmash_bs_count( bs );
281 ftyp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
282 size_t alloc_size = ftyp->brand_count * sizeof(uint32_t);
283 ftyp->compatible_brands = ftyp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
284 if( ftyp->brand_count && !ftyp->compatible_brands )
285 return LSMASH_ERR_MEMORY_ALLOC;
286 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
287 ftyp->compatible_brands[i] = lsmash_bs_get_be32( bs );
288 if( !file->compatible_brands && ftyp->compatible_brands )
290 file->compatible_brands = lsmash_memdup( ftyp->compatible_brands, alloc_size );
291 if( !file->compatible_brands )
292 return LSMASH_ERR_MEMORY_ALLOC;
293 file->brand_count = ftyp->brand_count;
295 return isom_read_leaf_box_common_last_process( file, box, level, ftyp );
298 static int isom_read_styp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
300 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
301 return isom_read_unknown_box( file, box, parent, level );
302 ADD_BOX( styp, lsmash_file_t );
303 lsmash_bs_t *bs = file->bs;
304 styp->major_brand = lsmash_bs_get_be32( bs );
305 styp->minor_version = lsmash_bs_get_be32( bs );
306 uint64_t pos = lsmash_bs_count( bs );
307 styp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
308 size_t alloc_size = styp->brand_count * sizeof(uint32_t);
309 styp->compatible_brands = styp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
310 if( styp->brand_count && !styp->compatible_brands )
311 return LSMASH_ERR_MEMORY_ALLOC;
312 for( uint32_t i = 0; i < styp->brand_count; i++ )
313 styp->compatible_brands[i] = lsmash_bs_get_be32( bs );
314 if( !file->compatible_brands && styp->compatible_brands )
316 file->compatible_brands = lsmash_memdup( styp->compatible_brands, alloc_size );
317 if( !file->compatible_brands )
318 return LSMASH_ERR_MEMORY_ALLOC;
319 file->brand_count = styp->brand_count;
321 file->flags |= LSMASH_FILE_MODE_SEGMENT;
322 return isom_read_leaf_box_common_last_process( file, box, level, styp );
325 static int isom_read_sidx( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
327 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
328 return isom_read_unknown_box( file, box, parent, level );
329 ADD_BOX( sidx, lsmash_file_t );
330 lsmash_bs_t *bs = file->bs;
331 sidx->reference_ID = lsmash_bs_get_be32( bs );
332 sidx->timescale = lsmash_bs_get_be32( bs );
333 if( box->version == 0 )
335 sidx->earliest_presentation_time = lsmash_bs_get_be32( bs );
336 sidx->first_offset = lsmash_bs_get_be32( bs );
338 else
340 sidx->earliest_presentation_time = lsmash_bs_get_be64( bs );
341 sidx->first_offset = lsmash_bs_get_be64( bs );
343 sidx->reserved = lsmash_bs_get_be16( bs );
344 sidx->reference_count = lsmash_bs_get_be16( bs );
345 for( uint64_t pos = lsmash_bs_count( bs );
346 pos < box->size && sidx->list->entry_count < sidx->reference_count;
347 pos = lsmash_bs_count( bs ) )
349 isom_sidx_referenced_item_t *data = lsmash_malloc( sizeof(isom_sidx_referenced_item_t) );
350 if( !data )
351 return LSMASH_ERR_MEMORY_ALLOC;
352 if( lsmash_list_add_entry( sidx->list, data ) < 0 )
354 lsmash_free( data );
355 return LSMASH_ERR_MEMORY_ALLOC;
357 uint32_t temp32;
358 temp32 = lsmash_bs_get_be32( bs );
359 data->reference_type = (temp32 >> 31) & 0x00000001;
360 data->reference_size = temp32 & 0x7FFFFFFF;
361 data->subsegment_duration = lsmash_bs_get_be32( bs );
362 temp32 = lsmash_bs_get_be32( bs );
363 data->starts_with_SAP = (temp32 >> 31) & 0x00000001;
364 data->SAP_type = (temp32 >> 28) & 0x00000007;
365 data->SAP_delta_time = temp32 & 0x0FFFFFFF;
367 file->flags |= LSMASH_FILE_MODE_INDEX;
368 return isom_read_leaf_box_common_last_process( file, box, level, sidx );
371 static int isom_read_moov( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
373 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
374 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->moov ) )
375 return isom_read_unknown_box( file, box, parent, level );
376 ADD_BOX( moov, lsmash_file_t );
377 file->flags |= LSMASH_FILE_MODE_INITIALIZATION;
378 file->initializer = file;
379 isom_box_common_copy( moov, box );
380 int ret = isom_add_print_func( file, moov, level );
381 if( ret < 0 )
382 return ret;
383 return isom_read_children( file, box, moov, level );
386 static int isom_read_mvhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
388 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
389 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->mvhd ) )
390 return isom_read_unknown_box( file, box, parent, level );
391 ADD_BOX( mvhd, isom_moov_t );
392 lsmash_bs_t *bs = file->bs;
393 if( box->version )
395 mvhd->creation_time = lsmash_bs_get_be64( bs );
396 mvhd->modification_time = lsmash_bs_get_be64( bs );
397 mvhd->timescale = lsmash_bs_get_be32( bs );
398 mvhd->duration = lsmash_bs_get_be64( bs );
400 else
402 mvhd->creation_time = lsmash_bs_get_be32( bs );
403 mvhd->modification_time = lsmash_bs_get_be32( bs );
404 mvhd->timescale = lsmash_bs_get_be32( bs );
405 mvhd->duration = lsmash_bs_get_be32( bs );
407 mvhd->rate = lsmash_bs_get_be32( bs );
408 mvhd->volume = lsmash_bs_get_be16( bs );
409 mvhd->reserved = lsmash_bs_get_be16( bs );
410 mvhd->preferredLong[0] = lsmash_bs_get_be32( bs );
411 mvhd->preferredLong[1] = lsmash_bs_get_be32( bs );
412 for( int i = 0; i < 9; i++ )
413 mvhd->matrix[i] = lsmash_bs_get_be32( bs );
414 mvhd->previewTime = lsmash_bs_get_be32( bs );
415 mvhd->previewDuration = lsmash_bs_get_be32( bs );
416 mvhd->posterTime = lsmash_bs_get_be32( bs );
417 mvhd->selectionTime = lsmash_bs_get_be32( bs );
418 mvhd->selectionDuration = lsmash_bs_get_be32( bs );
419 mvhd->currentTime = lsmash_bs_get_be32( bs );
420 mvhd->next_track_ID = lsmash_bs_get_be32( bs );
421 return isom_read_leaf_box_common_last_process( file, box, level, mvhd );
424 static int isom_read_iods( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
426 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
427 return isom_read_unknown_box( file, box, parent, level );
428 ADD_BOX( iods, isom_moov_t );
429 lsmash_bs_t *bs = file->bs;
430 iods->OD = mp4sys_get_descriptor( bs, NULL );
431 if( !iods->OD )
432 return LSMASH_ERR_INVALID_DATA;
433 return isom_read_leaf_box_common_last_process( file, box, level, iods );
436 static int isom_read_qt_color_table( lsmash_bs_t *bs, isom_qt_color_table_t *color_table )
438 color_table->seed = lsmash_bs_get_be32( bs );
439 color_table->flags = lsmash_bs_get_be16( bs );
440 color_table->size = lsmash_bs_get_be16( bs );
441 if( bs->eob )
442 return LSMASH_ERR_INVALID_DATA;
443 isom_qt_color_array_t *array = lsmash_malloc_zero( (color_table->size + 1) * sizeof(isom_qt_color_array_t) );
444 if( !array )
445 return LSMASH_ERR_MEMORY_ALLOC;
446 color_table->array = array;
447 for( uint16_t i = 0; i <= color_table->size; i++ )
449 uint64_t color = lsmash_bs_get_be64( bs );
450 array[i].value = (color >> 48) & 0xffff;
451 array[i].r = (color >> 32) & 0xffff;
452 array[i].g = (color >> 16) & 0xffff;
453 array[i].b = color & 0xffff;
455 return 0;
458 static int isom_read_ctab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
460 ADD_BOX( ctab, isom_moov_t );
461 lsmash_bs_t *bs = file->bs;
462 int ret = isom_read_qt_color_table( bs, &ctab->color_table );
463 if( ret < 0 )
464 return ret;
465 return isom_read_leaf_box_common_last_process( file, box, level, ctab );
468 static int isom_read_trak( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
470 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
471 return isom_read_unknown_box( file, box, parent, level );
472 ADD_BOX( trak, isom_moov_t );
473 box->parent = parent;
474 box->root = file->root;
475 box->file = file;
476 isom_box_common_copy( trak, box );
477 int ret = isom_add_print_func( file, trak, level );
478 if( ret < 0 )
479 return ret;
480 return isom_read_children( file, box, trak, level );
483 static int isom_read_tkhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
485 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
486 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->tkhd ) )
487 return isom_read_unknown_box( file, box, parent, level );
488 ADD_BOX( tkhd, isom_trak_t );
489 lsmash_bs_t *bs = file->bs;
490 if( box->version )
492 tkhd->creation_time = lsmash_bs_get_be64( bs );
493 tkhd->modification_time = lsmash_bs_get_be64( bs );
494 tkhd->track_ID = lsmash_bs_get_be32( bs );
495 tkhd->reserved1 = lsmash_bs_get_be32( bs );
496 tkhd->duration = lsmash_bs_get_be64( bs );
498 else
500 tkhd->creation_time = lsmash_bs_get_be32( bs );
501 tkhd->modification_time = lsmash_bs_get_be32( bs );
502 tkhd->track_ID = lsmash_bs_get_be32( bs );
503 tkhd->reserved1 = lsmash_bs_get_be32( bs );
504 tkhd->duration = lsmash_bs_get_be32( bs );
506 tkhd->reserved2[0] = lsmash_bs_get_be32( bs );
507 tkhd->reserved2[1] = lsmash_bs_get_be32( bs );
508 tkhd->layer = lsmash_bs_get_be16( bs );
509 tkhd->alternate_group = lsmash_bs_get_be16( bs );
510 tkhd->volume = lsmash_bs_get_be16( bs );
511 tkhd->reserved3 = lsmash_bs_get_be16( bs );
512 for( int i = 0; i < 9; i++ )
513 tkhd->matrix[i] = lsmash_bs_get_be32( bs );
514 tkhd->width = lsmash_bs_get_be32( bs );
515 tkhd->height = lsmash_bs_get_be32( bs );
516 return isom_read_leaf_box_common_last_process( file, box, level, tkhd );
519 static int isom_read_tapt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
521 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
522 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->tapt ) )
523 return isom_read_unknown_box( file, box, parent, level );
524 ADD_BOX( tapt, isom_trak_t );
525 isom_box_common_copy( tapt, box );
526 int ret = isom_add_print_func( file, tapt, level );
527 if( ret < 0 )
528 return ret;
529 return isom_read_children( file, box, tapt, level );
532 static int isom_read_clef( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
534 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT )
535 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t *)parent)->clef ) )
536 return isom_read_unknown_box( file, box, parent, level );
537 ADD_BOX( clef, isom_tapt_t );
538 lsmash_bs_t *bs = file->bs;
539 clef->width = lsmash_bs_get_be32( bs );
540 clef->height = lsmash_bs_get_be32( bs );
541 return isom_read_leaf_box_common_last_process( file, box, level, clef );
544 static int isom_read_prof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
546 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT )
547 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t *)parent)->prof ) )
548 return isom_read_unknown_box( file, box, parent, level );
549 ADD_BOX( prof, isom_tapt_t );
550 lsmash_bs_t *bs = file->bs;
551 prof->width = lsmash_bs_get_be32( bs );
552 prof->height = lsmash_bs_get_be32( bs );
553 return isom_read_leaf_box_common_last_process( file, box, level, prof );
556 static int isom_read_enof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
558 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT )
559 || LSMASH_IS_EXISTING_BOX( ((isom_tapt_t *)parent)->enof ) )
560 return isom_read_unknown_box( file, box, parent, level );
561 ADD_BOX( enof, isom_tapt_t );
562 lsmash_bs_t *bs = file->bs;
563 enof->width = lsmash_bs_get_be32( bs );
564 enof->height = lsmash_bs_get_be32( bs );
565 return isom_read_leaf_box_common_last_process( file, box, level, enof );
568 static int isom_read_edts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
570 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
571 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->edts ) )
572 return isom_read_unknown_box( file, box, parent, level );
573 ADD_BOX( edts, isom_trak_t );
574 isom_box_common_copy( edts, box );
575 if( isom_add_print_func( file, edts, level ) < 0 )
576 return -1;
577 return isom_read_children( file, box, edts, level );
580 static int isom_read_elst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
582 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_EDTS )
583 || LSMASH_IS_EXISTING_BOX( ((isom_edts_t *)parent)->elst ) )
584 return isom_read_unknown_box( file, box, parent, level );
585 ADD_BOX( elst, isom_edts_t );
586 lsmash_bs_t *bs = file->bs;
587 uint32_t entry_count = lsmash_bs_get_be32( bs );
588 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && elst->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
590 isom_elst_entry_t *data = lsmash_malloc( sizeof(isom_elst_entry_t) );
591 if( !data )
592 return LSMASH_ERR_MEMORY_ALLOC;
593 if( lsmash_list_add_entry( elst->list, data ) < 0 )
595 lsmash_free( data );
596 return LSMASH_ERR_MEMORY_ALLOC;
598 if( box->version == 1 )
600 data->segment_duration = lsmash_bs_get_be64( bs );
601 data->media_time = (int64_t)lsmash_bs_get_be64( bs );
603 else
605 data->segment_duration = lsmash_bs_get_be32( bs );
606 data->media_time = (int32_t)lsmash_bs_get_be32( bs );
608 data->media_rate = lsmash_bs_get_be32( bs );
610 return isom_read_leaf_box_common_last_process( file, box, level, elst );
613 static int isom_read_tref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
615 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
616 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->tref ) )
617 return isom_read_unknown_box( file, box, parent, level );
618 ADD_BOX( tref, isom_trak_t );
619 isom_box_common_copy( tref, box );
620 int ret = isom_add_print_func( file, tref, level );
621 if( ret < 0 )
622 return ret;
623 return isom_read_children( file, box, tref, level );
626 static int isom_read_track_reference_type( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
628 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
629 return isom_read_unknown_box( file, box, parent, level );
630 isom_tref_type_t *ref = isom_add_track_reference_type( (isom_tref_t *)parent, box->type.fourcc );
631 if( !ref )
632 return LSMASH_ERR_NAMELESS;
633 lsmash_bs_t *bs = file->bs;
634 ref->ref_count = (box->size - lsmash_bs_count( bs ) ) / sizeof(uint32_t);
635 if( ref->ref_count )
637 ref->track_ID = lsmash_malloc( ref->ref_count * sizeof(uint32_t) );
638 if( !ref->track_ID )
640 ref->ref_count = 0;
641 return LSMASH_ERR_MEMORY_ALLOC;
643 for( uint32_t i = 0; i < ref->ref_count; i++ )
644 ref->track_ID[i] = lsmash_bs_get_be32( bs );
646 return isom_read_leaf_box_common_last_process( file, box, level, ref );
649 static int isom_read_mdia( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
651 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
652 || LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->mdia ) )
653 return isom_read_unknown_box( file, box, parent, level );
654 ADD_BOX( mdia, isom_trak_t );
655 isom_box_common_copy( mdia, box );
656 int ret = isom_add_print_func( file, mdia, level );
657 if( ret < 0 )
658 return ret;
659 return isom_read_children( file, box, mdia, level );
662 static int isom_read_mdhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
664 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
665 || LSMASH_IS_EXISTING_BOX( ((isom_mdia_t *)parent)->mdhd ) )
666 return isom_read_unknown_box( file, box, parent, level );
667 ADD_BOX( mdhd, isom_mdia_t );
668 lsmash_bs_t *bs = file->bs;
669 if( box->version )
671 mdhd->creation_time = lsmash_bs_get_be64( bs );
672 mdhd->modification_time = lsmash_bs_get_be64( bs );
673 mdhd->timescale = lsmash_bs_get_be32( bs );
674 mdhd->duration = lsmash_bs_get_be64( bs );
676 else
678 mdhd->creation_time = lsmash_bs_get_be32( bs );
679 mdhd->modification_time = lsmash_bs_get_be32( bs );
680 mdhd->timescale = lsmash_bs_get_be32( bs );
681 mdhd->duration = lsmash_bs_get_be32( bs );
683 mdhd->language = lsmash_bs_get_be16( bs );
684 mdhd->quality = lsmash_bs_get_be16( bs );
685 return isom_read_leaf_box_common_last_process( file, box, level, mdhd );
688 static int isom_read_hdlr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
690 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
691 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
692 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META )
693 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ))
694 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) && LSMASH_IS_EXISTING_BOX( ((isom_mdia_t *)parent)->hdlr ))
695 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->hdlr ))
696 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->hdlr ))
697 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->hdlr )) )
698 return isom_read_unknown_box( file, box, parent, level );
699 ADD_BOX( hdlr, void );
700 lsmash_bs_t *bs = file->bs;
701 hdlr->componentType = lsmash_bs_get_be32( bs );
702 hdlr->componentSubtype = lsmash_bs_get_be32( bs );
703 hdlr->componentManufacturer = lsmash_bs_get_be32( bs );
704 hdlr->componentFlags = lsmash_bs_get_be32( bs );
705 hdlr->componentFlagsMask = lsmash_bs_get_be32( bs );
706 uint64_t pos = lsmash_bs_count( bs );
707 hdlr->componentName_length = box->size - pos;
708 if( hdlr->componentName_length )
710 hdlr->componentName = lsmash_malloc( hdlr->componentName_length );
711 if( !hdlr->componentName )
712 return LSMASH_ERR_MEMORY_ALLOC;
713 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
714 hdlr->componentName[i++] = lsmash_bs_get_byte( bs );
716 return isom_read_leaf_box_common_last_process( file, box, level, hdlr );
719 static int isom_read_minf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
721 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
722 || LSMASH_IS_EXISTING_BOX( ((isom_mdia_t *)parent)->minf ) )
723 return isom_read_unknown_box( file, box, parent, level );
724 ADD_BOX( minf, isom_mdia_t );
725 isom_box_common_copy( minf, box );
726 int ret = isom_add_print_func( file, minf, level );
727 if( ret < 0 )
728 return ret;
729 return isom_read_children( file, box, minf, level );
732 static int isom_read_vmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
734 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
735 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->vmhd ) )
736 return isom_read_unknown_box( file, box, parent, level );
737 ADD_BOX( vmhd, isom_minf_t );
738 lsmash_bs_t *bs = file->bs;
739 vmhd->graphicsmode = lsmash_bs_get_be16( bs );
740 for( int i = 0; i < 3; i++ )
741 vmhd->opcolor[i] = lsmash_bs_get_be16( bs );
742 return isom_read_leaf_box_common_last_process( file, box, level, vmhd );
745 static int isom_read_smhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
747 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
748 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->smhd ) )
749 return isom_read_unknown_box( file, box, parent, level );
750 ADD_BOX( smhd, isom_minf_t );
751 lsmash_bs_t *bs = file->bs;
752 smhd->balance = lsmash_bs_get_be16( bs );
753 smhd->reserved = lsmash_bs_get_be16( bs );
754 return isom_read_leaf_box_common_last_process( file, box, level, smhd );
757 static int isom_read_hmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
759 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
760 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->hmhd ) )
761 return isom_read_unknown_box( file, box, parent, level );
762 ADD_BOX( hmhd, isom_minf_t );
763 lsmash_bs_t *bs = file->bs;
764 hmhd->maxPDUsize = lsmash_bs_get_be16( bs );
765 hmhd->avgPDUsize = lsmash_bs_get_be16( bs );
766 hmhd->maxbitrate = lsmash_bs_get_be32( bs );
767 hmhd->avgbitrate = lsmash_bs_get_be32( bs );
768 hmhd->reserved = lsmash_bs_get_be32( bs );
769 return isom_read_leaf_box_common_last_process( file, box, level, hmhd );
772 static int isom_read_nmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
774 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
775 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->nmhd ) )
776 return isom_read_unknown_box( file, box, parent, level );
777 ADD_BOX( nmhd, isom_minf_t );
778 return isom_read_leaf_box_common_last_process( file, box, level, nmhd );
781 static int isom_read_gmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
783 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
784 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->gmhd ) )
785 return isom_read_unknown_box( file, box, parent, level );
786 ADD_BOX( gmhd, isom_minf_t );
787 isom_box_common_copy( gmhd, box );
788 int ret = isom_add_print_func( file, gmhd, level );
789 if( ret < 0 )
790 return ret;
791 return isom_read_children( file, box, gmhd, level );
794 static int isom_read_gmin( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
796 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD )
797 || LSMASH_IS_EXISTING_BOX( ((isom_gmhd_t *)parent)->gmin ) )
798 return isom_read_unknown_box( file, box, parent, level );
799 ADD_BOX( gmin, isom_gmhd_t );
800 lsmash_bs_t *bs = file->bs;
801 gmin->graphicsmode = lsmash_bs_get_be16( bs );
802 for( int i = 0; i < 3; i++ )
803 gmin->opcolor[i] = lsmash_bs_get_be16( bs );
804 gmin->balance = lsmash_bs_get_be16( bs );
805 gmin->reserved = lsmash_bs_get_be16( bs );
806 return isom_read_leaf_box_common_last_process( file, box, level, gmin );
809 static int isom_read_text( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
811 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD )
812 || LSMASH_IS_EXISTING_BOX( ((isom_gmhd_t *)parent)->text ) )
813 return isom_read_unknown_box( file, box, parent, level );
814 ADD_BOX( text, isom_gmhd_t );
815 lsmash_bs_t *bs = file->bs;
816 for( int i = 0; i < 9; i++ )
817 text->matrix[i] = lsmash_bs_get_be32( bs );
818 return isom_read_leaf_box_common_last_process( file, box, level, text );
821 static int isom_read_dinf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
823 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
824 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
825 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
826 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->dinf ))
827 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->dinf ))
828 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->dinf )) )
829 return isom_read_unknown_box( file, box, parent, level );
830 ADD_BOX( dinf, void );
831 isom_box_common_copy( dinf, box );
832 int ret = isom_add_print_func( file, dinf, level );
833 if( ret < 0 )
834 return ret;
835 return isom_read_children( file, box, dinf, level );
838 static int isom_read_dref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
840 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DINF )
841 || LSMASH_IS_EXISTING_BOX( ((isom_dinf_t *)parent)->dref ) )
842 return isom_read_unknown_box( file, box, parent, level );
843 ADD_BOX( dref, isom_dinf_t );
844 lsmash_bs_t *bs = file->bs;
845 dref->list.entry_count = lsmash_bs_get_be32( bs );
846 isom_box_common_copy( dref, box );
847 int ret = isom_add_print_func( file, dref, level );
848 if( ret < 0 )
849 return ret;
850 return isom_read_children( file, box, dref, level );
853 static int isom_read_dref_entry( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
855 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
856 return isom_read_unknown_box( file, box, parent, level );
857 isom_dref_t *dref = (isom_dref_t *)parent;
858 if( !dref->list.head )
859 dref->list.entry_count = 0; /* discard entry_count gotten from the file */
860 isom_dref_entry_t *ref = isom_add_dref_entry( dref, box->type );
861 if( !ref )
862 return LSMASH_ERR_NAMELESS;
863 lsmash_bs_t *bs = file->bs;
864 if( lsmash_check_box_type_identical( ref->type, ISOM_BOX_TYPE_URL ) )
866 uint64_t pos = lsmash_bs_count( bs );
867 ref->location_length = box->size - pos;
868 if( ref->location_length )
870 ref->location = lsmash_malloc( ref->location_length );
871 if( !ref->location )
872 return LSMASH_ERR_MEMORY_ALLOC;
873 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
874 ref->location[i++] = lsmash_bs_get_byte( bs );
877 if( box->flags & 0x000001 )
878 ref->ref_file = ref->file;
879 box->parent = parent;
880 return isom_read_leaf_box_common_last_process( file, box, level, ref );
883 static int isom_read_stbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
885 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
886 || LSMASH_IS_EXISTING_BOX( ((isom_minf_t *)parent)->stbl ) )
887 return isom_read_unknown_box( file, box, parent, level );
888 ADD_BOX( stbl, isom_minf_t );
889 isom_box_common_copy( stbl, box );
890 int ret = isom_add_print_func( file, stbl, level );
891 if( ret < 0 )
892 return ret;
893 return isom_read_children( file, box, stbl, level );
896 static int isom_read_stsd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
898 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
899 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stsd ) )
900 return isom_read_unknown_box( file, box, parent, level );
901 ADD_BOX( stsd, isom_stbl_t );
902 lsmash_bs_t *bs = file->bs;
903 stsd->entry_count = lsmash_bs_get_be32( bs );
904 isom_box_common_copy( stsd, box );
905 int ret = isom_add_print_func( file, stsd, level );
906 if( ret < 0 )
907 return ret;
908 uint64_t stsd_pos = lsmash_bs_count( bs );
909 for( uint32_t i = 0; i < stsd->entry_count || (stsd_pos + ISOM_BASEBOX_COMMON_SIZE) <= stsd->size; i++ )
911 if( (ret = isom_read_box( file, box, (isom_box_t *)stsd, stsd_pos, level )) != 0 )
912 break;
913 stsd_pos += box->size;
914 if( stsd->size <= stsd_pos || bs->eob || bs->error )
915 break;
917 if( stsd->size < stsd_pos )
919 fprintf( stderr, "[stsd] box has extra bytes: %"PRId64"\n", stsd_pos - stsd->size );
920 stsd->size = stsd_pos;
922 box->size = stsd->size;
923 return ret;
926 static int isom_read_codec_specific( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
928 lsmash_bs_t *bs = file->bs;
929 uint64_t opaque_pos = lsmash_bs_count( bs );
930 uint64_t exdata_length = box->size - opaque_pos;
931 if( exdata_length > UINT32_MAX )
932 return LSMASH_ERR_MEMORY_ALLOC;
933 uint8_t *exdata = lsmash_malloc( box->size );
934 if( !exdata )
935 return LSMASH_ERR_MEMORY_ALLOC;
936 int ret = lsmash_bs_get_bytes_ex( bs, exdata_length, exdata + (uintptr_t)opaque_pos );
937 if( ret < 0 )
938 goto fail;
939 LSMASH_SET_BE32( &exdata[0], box->size );
940 LSMASH_SET_BE32( &exdata[4], box->type.fourcc );
941 uintptr_t i = 8;
942 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc )
944 LSMASH_SET_BE32( &exdata[8], box->type.user.fourcc );
945 memcpy( &exdata[12], box->type.user.id, 12 );
946 i += 16;
948 if( box->manager & LSMASH_FULLBOX )
950 LSMASH_SET_BYTE( &exdata[i], box->version );
951 i += 1;
952 LSMASH_SET_BE24( &exdata[i], box->flags );
953 i += 3;
955 if( i != opaque_pos )
957 ret = LSMASH_ERR_INVALID_DATA;
958 goto fail;
960 if( (ret = isom_add_extension_binary( parent, box->type, LSMASH_BOX_PRECEDENCE_N, exdata, box->size )) < 0 )
961 goto fail;
962 isom_box_t *ext = (isom_box_t *)parent->extensions.tail->data;
963 box->manager |= ext->manager;
964 isom_validate_box_size( file->bs, box );
965 isom_basebox_common_copy( ext, box );
966 return isom_add_print_func( file, ext, level );
967 fail:
968 lsmash_free( exdata );
969 return ret;
972 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
974 assert( isom_check_media_hdlr_from_stsd( stsd ) );
975 void *sample_desc = NULL;
976 lsmash_media_type media_type = ((isom_mdia_t *)stsd->parent->parent->parent)->hdlr->componentSubtype;
977 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
978 sample_desc = ALLOCATE_BOX( visual_entry );
979 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
980 sample_desc = ALLOCATE_BOX( audio_entry );
981 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
983 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
984 sample_desc = ALLOCATE_BOX( tx3g_entry );
985 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TEXT_TEXT ) )
986 sample_desc = ALLOCATE_BOX( qt_text_entry );
988 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
989 sample_desc = ALLOCATE_BOX( mp4s_entry );
990 if( !sample_desc )
991 return NULL;
992 ((isom_box_t *)sample_desc)->offset_in_parent = offsetof( isom_stsd_t, list );
993 ((isom_box_t *)sample_desc)->destruct = (isom_extension_destructor_t)isom_remove_sample_description;
994 return sample_desc;
997 static void *isom_add_description( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
999 void *sample_desc = isom_sample_description_alloc( sample_type, stsd );
1000 if( !sample_desc )
1001 return NULL;
1002 if( lsmash_list_add_entry( &stsd->list, sample_desc ) < 0 )
1004 lsmash_free( sample_desc );
1005 return NULL;
1007 if( lsmash_list_add_entry( &stsd->extensions, sample_desc ) < 0 )
1009 lsmash_list_remove_entry_tail( &stsd->list );
1010 return NULL;
1012 return sample_desc;
1015 static int isom_read_visual_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1017 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1018 return isom_read_unknown_box( file, box, parent, level );
1019 isom_visual_entry_t *visual = (isom_visual_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1020 if( LSMASH_IS_NON_EXISTING_BOX( visual ) )
1021 return LSMASH_ERR_MEMORY_ALLOC;
1022 lsmash_bs_t *bs = file->bs;
1023 for( int i = 0; i < 6; i++ )
1024 visual->reserved[i] = lsmash_bs_get_byte( bs );
1025 visual->data_reference_index = lsmash_bs_get_be16( bs );
1026 visual->version = lsmash_bs_get_be16( bs );
1027 visual->revision_level = lsmash_bs_get_be16( bs );
1028 visual->vendor = lsmash_bs_get_be32( bs );
1029 visual->temporalQuality = lsmash_bs_get_be32( bs );
1030 visual->spatialQuality = lsmash_bs_get_be32( bs );
1031 visual->width = lsmash_bs_get_be16( bs );
1032 visual->height = lsmash_bs_get_be16( bs );
1033 visual->horizresolution = lsmash_bs_get_be32( bs );
1034 visual->vertresolution = lsmash_bs_get_be32( bs );
1035 visual->dataSize = lsmash_bs_get_be32( bs );
1036 visual->frame_count = lsmash_bs_get_be16( bs );
1037 for( int i = 0; i < 32; i++ )
1038 visual->compressorname[i] = lsmash_bs_get_byte( bs );
1039 visual->depth = lsmash_bs_get_be16( bs );
1040 visual->color_table_ID = lsmash_bs_get_be16( bs );
1041 int ret;
1042 if( visual->color_table_ID == 0
1043 && lsmash_bs_get_pos( bs ) < box->size
1044 && (ret = isom_read_qt_color_table( bs, &visual->color_table )) < 0 )
1045 return ret;
1046 box->parent = parent;
1047 box->manager |= LSMASH_VIDEO_DESCRIPTION;
1048 isom_box_common_copy( visual, box );
1049 if( (ret = isom_add_print_func( file, visual, level )) < 0 )
1050 return ret;
1051 return isom_read_children( file, box, visual, level );
1054 static int isom_read_esds( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1056 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4V_VIDEO )
1057 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO )
1058 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_ENCA_AUDIO )
1059 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_M4AE_AUDIO )
1060 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4S_SYSTEM )
1061 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1062 return isom_read_codec_specific( file, box, parent, level );
1063 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1065 box->type = QT_BOX_TYPE_ESDS;
1066 assert( LSMASH_IS_EXISTING_BOX( parent->parent ) );
1067 if( lsmash_check_box_type_identical( parent->parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO ) )
1068 parent->parent->type = QT_CODEC_TYPE_MP4A_AUDIO;
1070 else
1071 box->type = ISOM_BOX_TYPE_ESDS;
1072 ADD_BOX( esds, void );
1073 lsmash_bs_t *bs = file->bs;
1074 esds->ES = mp4sys_get_descriptor( bs, NULL );
1075 if( !esds->ES )
1076 return LSMASH_ERR_INVALID_DATA;
1077 return isom_read_leaf_box_common_last_process( file, box, level, esds );
1080 static int isom_read_btrt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1082 ADD_BOX( btrt, isom_visual_entry_t );
1083 lsmash_bs_t *bs = file->bs;
1084 btrt->bufferSizeDB = lsmash_bs_get_be32( bs );
1085 btrt->maxBitrate = lsmash_bs_get_be32( bs );
1086 btrt->avgBitrate = lsmash_bs_get_be32( bs );
1087 return isom_read_leaf_box_common_last_process( file, box, level, btrt );
1090 static int isom_read_glbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1092 ADD_BOX( glbl, isom_visual_entry_t );
1093 lsmash_bs_t *bs = file->bs;
1094 uint32_t header_size = box->size - ISOM_BASEBOX_COMMON_SIZE;
1095 if( header_size )
1097 glbl->header_data = lsmash_malloc( header_size );
1098 if( !glbl->header_data )
1099 return LSMASH_ERR_MEMORY_ALLOC;
1100 for( uint32_t i = 0; i < header_size; i++ )
1101 glbl->header_data[i] = lsmash_bs_get_byte( bs );
1103 glbl->header_size = header_size;
1104 return isom_read_leaf_box_common_last_process( file, box, level, glbl );
1107 static int isom_read_clap( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1109 ADD_BOX( clap, isom_visual_entry_t );
1110 lsmash_bs_t *bs = file->bs;
1111 clap->cleanApertureWidthN = lsmash_bs_get_be32( bs );
1112 clap->cleanApertureWidthD = lsmash_bs_get_be32( bs );
1113 clap->cleanApertureHeightN = lsmash_bs_get_be32( bs );
1114 clap->cleanApertureHeightD = lsmash_bs_get_be32( bs );
1115 clap->horizOffN = lsmash_bs_get_be32( bs );
1116 clap->horizOffD = lsmash_bs_get_be32( bs );
1117 clap->vertOffN = lsmash_bs_get_be32( bs );
1118 clap->vertOffD = lsmash_bs_get_be32( bs );
1119 return isom_read_leaf_box_common_last_process( file, box, level, clap );
1122 static int isom_read_pasp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1124 ADD_BOX( pasp, isom_visual_entry_t );
1125 lsmash_bs_t *bs = file->bs;
1126 pasp->hSpacing = lsmash_bs_get_be32( bs );
1127 pasp->vSpacing = lsmash_bs_get_be32( bs );
1128 return isom_read_leaf_box_common_last_process( file, box, level, pasp );
1131 static int isom_read_colr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1133 ADD_BOX( colr, isom_visual_entry_t );
1134 lsmash_bs_t *bs = file->bs;
1135 colr->color_parameter_type = lsmash_bs_get_be32( bs );
1136 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
1137 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1139 colr->primaries_index = lsmash_bs_get_be16( bs );
1140 colr->transfer_function_index = lsmash_bs_get_be16( bs );
1141 colr->matrix_index = lsmash_bs_get_be16( bs );
1142 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1144 if( lsmash_bs_count( bs ) < box->size )
1146 uint8_t temp8 = lsmash_bs_get_byte( bs );
1147 colr->full_range_flag = (temp8 >> 7) & 0x01;
1148 colr->reserved = temp8 & 0x7f;
1150 else
1152 /* It seems this box is broken or incomplete. */
1153 box->manager |= LSMASH_INCOMPLETE_BOX;
1154 colr->full_range_flag = 0;
1155 colr->reserved = 0;
1158 else
1159 box->manager |= LSMASH_QTFF_BASE;
1161 box->type = (box->manager & LSMASH_QTFF_BASE) ? QT_BOX_TYPE_COLR : ISOM_BOX_TYPE_COLR;
1162 return isom_read_leaf_box_common_last_process( file, box, level, colr );
1165 static int isom_read_gama( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1167 ADD_BOX( gama, isom_visual_entry_t );
1168 lsmash_bs_t *bs = file->bs;
1169 gama->level = lsmash_bs_get_be32( bs );
1170 return isom_read_leaf_box_common_last_process( file, box, level, gama );
1173 static int isom_read_fiel( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1175 ADD_BOX( fiel, isom_visual_entry_t );
1176 lsmash_bs_t *bs = file->bs;
1177 fiel->fields = lsmash_bs_get_byte( bs );
1178 fiel->detail = lsmash_bs_get_byte( bs );
1179 return isom_read_leaf_box_common_last_process( file, box, level, fiel );
1182 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1184 ADD_BOX( cspc, isom_visual_entry_t );
1185 lsmash_bs_t *bs = file->bs;
1186 cspc->pixel_format = lsmash_bs_get_be32( bs );
1187 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1190 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1192 ADD_BOX( sgbt, isom_visual_entry_t );
1193 lsmash_bs_t *bs = file->bs;
1194 sgbt->significantBits = lsmash_bs_get_byte( bs );
1195 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1198 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1200 ADD_BOX( stsl, isom_visual_entry_t );
1201 lsmash_bs_t *bs = file->bs;
1202 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1203 stsl->scale_method = lsmash_bs_get_byte( bs );
1204 stsl->display_center_x = lsmash_bs_get_be16( bs );
1205 stsl->display_center_y = lsmash_bs_get_be16( bs );
1206 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1209 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1211 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1212 return isom_read_unknown_box( file, box, parent, level );
1213 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1214 if( LSMASH_IS_NON_EXISTING_BOX( audio ) )
1215 return LSMASH_ERR_MEMORY_ALLOC;
1216 lsmash_bs_t *bs = file->bs;
1217 for( int i = 0; i < 6; i++ )
1218 audio->reserved[i] = lsmash_bs_get_byte( bs );
1219 audio->data_reference_index = lsmash_bs_get_be16( bs );
1220 audio->version = lsmash_bs_get_be16( bs );
1221 audio->revision_level = lsmash_bs_get_be16( bs );
1222 audio->vendor = lsmash_bs_get_be32( bs );
1223 audio->channelcount = lsmash_bs_get_be16( bs );
1224 audio->samplesize = lsmash_bs_get_be16( bs );
1225 audio->compression_ID = lsmash_bs_get_be16( bs );
1226 audio->packet_size = lsmash_bs_get_be16( bs );
1227 audio->samplerate = lsmash_bs_get_be32( bs );
1228 if( audio->version == 0 && isom_is_qt_audio( box->type ) )
1230 /* Skip weird extra bytes.
1231 * About QTFF, extensions were first added with Sound Sample Description v1. */
1232 while( lsmash_bs_count( bs ) + ISOM_BASEBOX_COMMON_SIZE <= box->size )
1234 uint32_t size = lsmash_bs_show_be32( bs, 0 );
1235 if( size == 0 || lsmash_bs_count( bs ) + size > box->size )
1236 lsmash_bs_skip_bytes( bs, 1 );
1237 else
1238 break;
1241 else if( audio->version == 1 )
1243 if( ((isom_stsd_t *)parent)->version == 0 )
1245 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1246 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1247 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1248 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1249 box->manager |= LSMASH_QTFF_BASE;
1251 else
1252 /* AudioSampleEntryV1 has no additional fields. */
1253 box->manager &= ~LSMASH_QTFF_BASE;
1255 else if( audio->version == 2 )
1257 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1258 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1259 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1260 audio->always7F000000 = lsmash_bs_get_be32( bs );
1261 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1262 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1263 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1264 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1265 box->manager |= LSMASH_QTFF_BASE;
1267 box->parent = parent;
1268 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1269 isom_box_common_copy( audio, box );
1270 int ret = isom_add_print_func( file, audio, level );
1271 if( ret < 0 )
1272 return ret;
1273 return isom_read_children( file, box, audio, level );
1276 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1278 ADD_BOX( wave, isom_audio_entry_t );
1279 isom_box_common_copy( wave, box );
1280 int ret = isom_add_print_func( file, wave, level );
1281 if( ret < 0 )
1282 return ret;
1283 return isom_read_children( file, box, wave, level );
1286 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1288 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1289 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->frma ) )
1290 return isom_read_unknown_box( file, box, parent, level );
1291 ADD_BOX( frma, isom_wave_t );
1292 lsmash_bs_t *bs = file->bs;
1293 frma->data_format = lsmash_bs_get_be32( bs );
1294 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1297 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1299 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1300 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->enda ) )
1301 return isom_read_unknown_box( file, box, parent, level );
1302 ADD_BOX( enda, isom_wave_t );
1303 lsmash_bs_t *bs = file->bs;
1304 enda->littleEndian = lsmash_bs_get_be16( bs );
1305 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1308 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1310 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1311 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->terminator ) )
1312 return isom_read_unknown_box( file, box, parent, level );
1313 ADD_BOX( terminator, isom_wave_t );
1314 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1317 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1319 ADD_BOX( chan, isom_audio_entry_t );
1320 lsmash_bs_t *bs = file->bs;
1321 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1322 chan->channelBitmap = lsmash_bs_get_be32( bs );
1323 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1324 if( chan->numberChannelDescriptions )
1326 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1327 if( !desc )
1328 return LSMASH_ERR_MEMORY_ALLOC;
1329 chan->channelDescriptions = desc;
1330 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1332 desc->channelLabel = lsmash_bs_get_be32( bs );
1333 desc->channelFlags = lsmash_bs_get_be32( bs );
1334 for( int j = 0; j < 3; j++ )
1335 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1338 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1341 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1343 ADD_BOX( srat, isom_audio_entry_t );
1344 lsmash_bs_t *bs = file->bs;
1345 srat->sampling_rate = lsmash_bs_get_be32( bs );
1346 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1349 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1351 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1352 return isom_read_unknown_box( file, box, parent, level );
1353 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1354 if( LSMASH_IS_NON_EXISTING_BOX( text ) )
1355 return LSMASH_ERR_MEMORY_ALLOC;
1356 lsmash_bs_t *bs = file->bs;
1357 for( int i = 0; i < 6; i++ )
1358 text->reserved[i] = lsmash_bs_get_byte( bs );
1359 text->data_reference_index = lsmash_bs_get_be16( bs );
1360 text->displayFlags = lsmash_bs_get_be32( bs );
1361 text->textJustification = lsmash_bs_get_be32( bs );
1362 for( int i = 0; i < 3; i++ )
1363 text->bgColor[i] = lsmash_bs_get_be16( bs );
1364 text->top = lsmash_bs_get_be16( bs );
1365 text->left = lsmash_bs_get_be16( bs );
1366 text->bottom = lsmash_bs_get_be16( bs );
1367 text->right = lsmash_bs_get_be16( bs );
1368 text->scrpStartChar = lsmash_bs_get_be32( bs );
1369 text->scrpHeight = lsmash_bs_get_be16( bs );
1370 text->scrpAscent = lsmash_bs_get_be16( bs );
1371 text->scrpFont = lsmash_bs_get_be16( bs );
1372 text->scrpFace = lsmash_bs_get_be16( bs );
1373 text->scrpSize = lsmash_bs_get_be16( bs );
1374 for( int i = 0; i < 3; i++ )
1375 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1376 text->font_name_length = lsmash_bs_get_byte( bs );
1377 if( text->font_name_length )
1379 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1380 if( !text->font_name )
1381 return LSMASH_ERR_MEMORY_ALLOC;
1382 for( uint8_t i = 0; i < text->font_name_length; i++ )
1383 text->font_name[i] = lsmash_bs_get_byte( bs );
1384 text->font_name[text->font_name_length] = '\0';
1386 box->parent = parent;
1387 isom_box_common_copy( text, box );
1388 int ret = isom_add_print_func( file, text, level );
1389 if( ret < 0 )
1390 return ret;
1391 return isom_read_children( file, box, text, level );
1394 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1396 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1397 return isom_read_unknown_box( file, box, parent, level );
1398 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1399 if( LSMASH_IS_NON_EXISTING_BOX( tx3g ) )
1400 return LSMASH_ERR_MEMORY_ALLOC;
1401 lsmash_bs_t *bs = file->bs;
1402 for( int i = 0; i < 6; i++ )
1403 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1404 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1405 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1406 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1407 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1408 for( int i = 0; i < 4; i++ )
1409 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1410 tx3g->top = lsmash_bs_get_be16( bs );
1411 tx3g->left = lsmash_bs_get_be16( bs );
1412 tx3g->bottom = lsmash_bs_get_be16( bs );
1413 tx3g->right = lsmash_bs_get_be16( bs );
1414 tx3g->startChar = lsmash_bs_get_be16( bs );
1415 tx3g->endChar = lsmash_bs_get_be16( bs );
1416 tx3g->font_ID = lsmash_bs_get_be16( bs );
1417 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1418 tx3g->font_size = lsmash_bs_get_byte( bs );
1419 for( int i = 0; i < 4; i++ )
1420 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1421 box->parent = parent;
1422 isom_box_common_copy( tx3g, box );
1423 int ret = isom_add_print_func( file, tx3g, level );
1424 if( ret < 0 )
1425 return ret;
1426 return isom_read_children( file, box, tx3g, level );
1429 static int isom_read_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1431 if( lsmash_check_codec_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1432 return isom_read_qt_text_description( file, box, parent, level );
1433 else if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1434 return isom_read_tx3g_description( file, box, parent, level );
1435 assert( 0 );
1436 return isom_read_unknown_box( file, box, parent, level );
1439 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1441 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1442 || LSMASH_IS_EXISTING_BOX( ((isom_tx3g_entry_t *)parent)->ftab ) )
1443 return isom_read_codec_specific( file, box, parent, level );
1444 ADD_BOX( ftab, isom_tx3g_entry_t );
1445 lsmash_bs_t *bs = file->bs;
1446 uint32_t entry_count = lsmash_bs_get_be16( bs );
1447 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1449 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1450 if( !data )
1451 return LSMASH_ERR_MEMORY_ALLOC;
1452 if( lsmash_list_add_entry( ftab->list, data ) < 0 )
1454 lsmash_free( data );
1455 return LSMASH_ERR_MEMORY_ALLOC;
1457 data->font_ID = lsmash_bs_get_be16( bs );
1458 data->font_name_length = lsmash_bs_get_byte( bs );
1459 if( data->font_name_length )
1461 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1462 if( !data->font_name )
1463 return LSMASH_ERR_MEMORY_ALLOC;
1464 for( uint8_t i = 0; i < data->font_name_length; i++ )
1465 data->font_name[i] = lsmash_bs_get_byte( bs );
1466 data->font_name[data->font_name_length] = '\0';
1469 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1472 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1474 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1475 return isom_read_unknown_box( file, box, parent, level );
1476 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1477 if( LSMASH_IS_NON_EXISTING_BOX( mp4s ) )
1478 return LSMASH_ERR_MEMORY_ALLOC;
1479 lsmash_bs_t *bs = file->bs;
1480 for( int i = 0; i < 6; i++ )
1481 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1482 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1483 box->parent = parent;
1484 isom_box_common_copy( mp4s, box );
1485 int ret = isom_add_print_func( file, mp4s, level );
1486 if( ret < 0 )
1487 return ret;
1488 return isom_read_children( file, box, mp4s, level );
1491 static int isom_read_other_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1493 if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
1494 return isom_read_mp4s_description( file, box, parent, level );
1495 return isom_read_unknown_box( file, box, parent, level );
1498 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1500 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1501 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stts ) )
1502 return isom_read_unknown_box( file, box, parent, level );
1503 ADD_BOX( stts, isom_stbl_t );
1504 lsmash_bs_t *bs = file->bs;
1505 uint32_t entry_count = lsmash_bs_get_be32( bs );
1506 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1508 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1509 if( !data )
1510 return LSMASH_ERR_MEMORY_ALLOC;
1511 if( lsmash_list_add_entry( stts->list, data ) < 0 )
1513 lsmash_free( data );
1514 return LSMASH_ERR_MEMORY_ALLOC;
1516 data->sample_count = lsmash_bs_get_be32( bs );
1517 data->sample_delta = lsmash_bs_get_be32( bs );
1519 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1522 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1524 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1525 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->ctts ) )
1526 return isom_read_unknown_box( file, box, parent, level );
1527 ADD_BOX( ctts, isom_stbl_t );
1528 lsmash_bs_t *bs = file->bs;
1529 uint32_t entry_count = lsmash_bs_get_be32( bs );
1530 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1532 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1533 if( !data )
1534 return LSMASH_ERR_MEMORY_ALLOC;
1535 if( lsmash_list_add_entry( ctts->list, data ) < 0 )
1537 lsmash_free( data );
1538 return LSMASH_ERR_MEMORY_ALLOC;
1540 data->sample_count = lsmash_bs_get_be32( bs );
1541 data->sample_offset = lsmash_bs_get_be32( bs );
1543 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1546 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1548 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1549 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->cslg ) )
1550 return isom_read_unknown_box( file, box, parent, level );
1551 ADD_BOX( cslg, isom_stbl_t );
1552 lsmash_bs_t *bs = file->bs;
1553 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1554 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1555 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1556 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1557 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1558 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1561 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1563 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1564 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stss ) )
1565 return isom_read_unknown_box( file, box, parent, level );
1566 ADD_BOX( stss, isom_stbl_t );
1567 lsmash_bs_t *bs = file->bs;
1568 uint32_t entry_count = lsmash_bs_get_be32( bs );
1569 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1571 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1572 if( !data )
1573 return LSMASH_ERR_MEMORY_ALLOC;
1574 if( lsmash_list_add_entry( stss->list, data ) < 0 )
1576 lsmash_free( data );
1577 return LSMASH_ERR_MEMORY_ALLOC;
1579 data->sample_number = lsmash_bs_get_be32( bs );
1581 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1584 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1586 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1587 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stps ) )
1588 return isom_read_unknown_box( file, box, parent, level );
1589 ADD_BOX( stps, isom_stbl_t );
1590 lsmash_bs_t *bs = file->bs;
1591 uint32_t entry_count = lsmash_bs_get_be32( bs );
1592 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1594 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1595 if( !data )
1596 return LSMASH_ERR_MEMORY_ALLOC;
1597 if( lsmash_list_add_entry( stps->list, data ) < 0 )
1599 lsmash_free( data );
1600 return LSMASH_ERR_MEMORY_ALLOC;
1602 data->sample_number = lsmash_bs_get_be32( bs );
1604 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1607 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1609 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1610 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1611 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->sdtp ))
1612 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->sdtp )) )
1613 return isom_read_unknown_box( file, box, parent, level );
1614 ADD_BOX( sdtp, isom_box_t );
1615 lsmash_bs_t *bs = file->bs;
1616 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1618 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1619 if( !data )
1620 return LSMASH_ERR_MEMORY_ALLOC;
1621 if( lsmash_list_add_entry( sdtp->list, data ) < 0 )
1623 lsmash_free( data );
1624 return LSMASH_ERR_MEMORY_ALLOC;
1626 uint8_t temp = lsmash_bs_get_byte( bs );
1627 data->is_leading = (temp >> 6) & 0x3;
1628 data->sample_depends_on = (temp >> 4) & 0x3;
1629 data->sample_is_depended_on = (temp >> 2) & 0x3;
1630 data->sample_has_redundancy = temp & 0x3;
1632 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1635 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1637 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1638 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stsc ) )
1639 return isom_read_unknown_box( file, box, parent, level );
1640 ADD_BOX( stsc, isom_stbl_t );
1641 lsmash_bs_t *bs = file->bs;
1642 uint32_t entry_count = lsmash_bs_get_be32( bs );
1643 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1645 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1646 if( !data )
1647 return LSMASH_ERR_MEMORY_ALLOC;
1648 if( lsmash_list_add_entry( stsc->list, data ) < 0 )
1650 lsmash_free( data );
1651 return LSMASH_ERR_MEMORY_ALLOC;
1653 data->first_chunk = lsmash_bs_get_be32( bs );
1654 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1655 data->sample_description_index = lsmash_bs_get_be32( bs );
1657 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1660 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1662 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1663 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stsz ) )
1664 return isom_read_unknown_box( file, box, parent, level );
1665 ADD_BOX( stsz, isom_stbl_t );
1666 lsmash_bs_t *bs = file->bs;
1667 stsz->sample_size = lsmash_bs_get_be32( bs );
1668 stsz->sample_count = lsmash_bs_get_be32( bs );
1669 uint64_t pos = lsmash_bs_count( bs );
1670 if( pos < box->size )
1672 stsz->list = lsmash_list_create_simple();
1673 if( !stsz->list )
1674 return LSMASH_ERR_MEMORY_ALLOC;
1675 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1677 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1678 if( !data )
1679 return LSMASH_ERR_MEMORY_ALLOC;
1680 if( lsmash_list_add_entry( stsz->list, data ) < 0 )
1682 lsmash_free( data );
1683 return LSMASH_ERR_MEMORY_ALLOC;
1685 data->entry_size = lsmash_bs_get_be32( bs );
1688 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1691 static int isom_read_stz2( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1693 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1694 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stz2 ) )
1695 return isom_read_unknown_box( file, box, parent, level );
1696 ADD_BOX( stz2, isom_stbl_t );
1697 lsmash_bs_t *bs = file->bs;
1698 uint32_t temp32 = lsmash_bs_get_be32( bs );
1699 stz2->reserved = temp32 >> 24;
1700 stz2->field_size = temp32 & 0xff;
1701 stz2->sample_count = lsmash_bs_get_be32( bs );
1702 uint64_t pos = lsmash_bs_count( bs );
1703 if( pos < box->size )
1705 if( stz2->field_size == 16 || stz2->field_size == 8 )
1707 uint64_t (*bs_get_funcs[2])( lsmash_bs_t * ) =
1709 lsmash_bs_get_byte_to_64,
1710 lsmash_bs_get_be16_to_64
1712 uint64_t (*bs_get_entry_size)( lsmash_bs_t * ) = bs_get_funcs[ stz2->field_size == 16 ? 1 : 0 ];
1713 for( ; pos < box->size && stz2->list->entry_count < stz2->sample_count; pos = lsmash_bs_count( bs ) )
1715 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1716 if( !data )
1717 return LSMASH_ERR_MEMORY_ALLOC;
1718 if( lsmash_list_add_entry( stz2->list, data ) < 0 )
1720 lsmash_free( data );
1721 return LSMASH_ERR_MEMORY_ALLOC;
1723 data->entry_size = bs_get_entry_size( bs );
1726 else if( stz2->field_size == 4 )
1728 int parity = 1;
1729 uint8_t temp8;
1730 while( pos < box->size && stz2->list->entry_count < stz2->sample_count )
1732 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1733 if( !data )
1734 return LSMASH_ERR_MEMORY_ALLOC;
1735 if( lsmash_list_add_entry( stz2->list, data ) < 0 )
1737 lsmash_free( data );
1738 return LSMASH_ERR_MEMORY_ALLOC;
1740 /* Read a byte by two entries. */
1741 if( parity )
1743 temp8 = lsmash_bs_get_byte( bs );
1744 data->entry_size = (temp8 >> 4) & 0xf;
1746 else
1748 pos = lsmash_bs_count( bs );
1749 data->entry_size = temp8 & 0xf;
1751 parity ^= 1;
1754 else
1755 return LSMASH_ERR_INVALID_DATA;
1757 return isom_read_leaf_box_common_last_process( file, box, level, stz2 );
1760 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1762 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1763 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stco ) )
1764 return isom_read_unknown_box( file, box, parent, level );
1765 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1766 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1767 isom_stco_t *stco = is_stco
1768 ? isom_add_stco( (isom_stbl_t *)parent )
1769 : isom_add_co64( (isom_stbl_t *)parent );
1770 if( !stco )
1771 return LSMASH_ERR_NAMELESS;
1772 lsmash_bs_t *bs = file->bs;
1773 uint32_t entry_count = lsmash_bs_get_be32( bs );
1774 if( is_stco )
1775 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1777 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1778 if( !data )
1779 return LSMASH_ERR_MEMORY_ALLOC;
1780 if( lsmash_list_add_entry( stco->list, data ) < 0 )
1782 lsmash_free( data );
1783 return LSMASH_ERR_MEMORY_ALLOC;
1785 data->chunk_offset = lsmash_bs_get_be32( bs );
1787 else
1789 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1791 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1792 if( !data )
1793 return LSMASH_ERR_MEMORY_ALLOC;
1794 if( lsmash_list_add_entry( stco->list, data ) < 0 )
1796 lsmash_free( data );
1797 return LSMASH_ERR_MEMORY_ALLOC;
1799 data->chunk_offset = lsmash_bs_get_be64( bs );
1802 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1805 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1807 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1808 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1809 return isom_read_unknown_box( file, box, parent, level );
1810 ADD_BOX( sgpd, void );
1811 lsmash_bs_t *bs = file->bs;
1812 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1813 if( box->version == 1 )
1814 sgpd->default_length = lsmash_bs_get_be32( bs );
1815 uint32_t entry_count = lsmash_bs_get_be32( bs );
1816 switch( sgpd->grouping_type )
1818 case ISOM_GROUP_TYPE_RAP :
1820 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1822 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1823 if( !data )
1824 return LSMASH_ERR_MEMORY_ALLOC;
1825 if( lsmash_list_add_entry( sgpd->list, data ) < 0 )
1827 lsmash_free( data );
1828 return LSMASH_ERR_MEMORY_ALLOC;
1830 memset( data, 0, sizeof(isom_rap_entry_t) );
1831 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1832 if( box->version == 1 && !sgpd->default_length )
1833 data->description_length = lsmash_bs_get_be32( bs );
1834 else
1836 uint8_t temp = lsmash_bs_get_byte( bs );
1837 data->num_leading_samples_known = (temp >> 7) & 0x01;
1838 data->num_leading_samples = temp & 0x7f;
1841 break;
1843 case ISOM_GROUP_TYPE_ROLL :
1844 case ISOM_GROUP_TYPE_PROL :
1846 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1848 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1849 if( !data )
1850 return LSMASH_ERR_MEMORY_ALLOC;
1851 if( lsmash_list_add_entry( sgpd->list, data ) < 0 )
1853 lsmash_free( data );
1854 return LSMASH_ERR_MEMORY_ALLOC;
1856 memset( data, 0, sizeof(isom_roll_entry_t) );
1857 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1858 if( box->version == 1 && !sgpd->default_length )
1859 data->description_length = lsmash_bs_get_be32( bs );
1860 else
1861 data->roll_distance = lsmash_bs_get_be16( bs );
1863 break;
1865 default :
1866 break;
1868 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1871 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1873 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1874 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1875 return isom_read_unknown_box( file, box, parent, level );
1876 ADD_BOX( sbgp, void );
1877 lsmash_bs_t *bs = file->bs;
1878 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1879 if( box->version == 1 )
1880 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1881 uint32_t entry_count = lsmash_bs_get_be32( bs );
1882 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1884 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1885 if( !data )
1886 return LSMASH_ERR_MEMORY_ALLOC;
1887 if( lsmash_list_add_entry( sbgp->list, data ) < 0 )
1889 lsmash_free( data );
1890 return LSMASH_ERR_MEMORY_ALLOC;
1892 data->sample_count = lsmash_bs_get_be32( bs );
1893 data->group_description_index = lsmash_bs_get_be32( bs );
1895 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1898 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1900 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1901 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1902 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->udta ))
1903 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->udta )) )
1904 return isom_read_unknown_box( file, box, parent, level );
1905 ADD_BOX( udta, void );
1906 isom_box_common_copy( udta, box );
1907 int ret = isom_add_print_func( file, udta, level );
1908 if( ret < 0 )
1909 return ret;
1910 return isom_read_children( file, box, udta, level );
1913 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1915 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
1916 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->chpl ) )
1917 return isom_read_unknown_box( file, box, parent, level );
1918 ADD_BOX( chpl, isom_udta_t );
1919 lsmash_bs_t *bs = file->bs;
1920 uint32_t entry_count;
1921 if( box->version == 1 )
1923 chpl->unknown = lsmash_bs_get_byte( bs );
1924 entry_count = lsmash_bs_get_be32( bs );
1926 else
1927 entry_count = lsmash_bs_get_byte( bs );
1928 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1930 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1931 if( !data )
1932 return LSMASH_ERR_MEMORY_ALLOC;
1933 if( lsmash_list_add_entry( chpl->list, data ) < 0 )
1935 lsmash_free( data );
1936 return LSMASH_ERR_MEMORY_ALLOC;
1938 data->start_time = lsmash_bs_get_be64( bs );
1939 data->chapter_name_length = lsmash_bs_get_byte( bs );
1940 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1941 if( !data->chapter_name )
1943 lsmash_free( data );
1944 return LSMASH_ERR_MEMORY_ALLOC;
1946 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1947 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1948 data->chapter_name[data->chapter_name_length] = '\0';
1950 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1953 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1955 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1956 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->mvex ) )
1957 return isom_read_unknown_box( file, box, parent, level );
1958 ADD_BOX( mvex, isom_moov_t );
1959 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1960 isom_box_common_copy( mvex, box );
1961 int ret = isom_add_print_func( file, mvex, level );
1962 if( ret < 0 )
1963 return ret;
1964 return isom_read_children( file, box, mvex, level );
1967 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1969 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX )
1970 || LSMASH_IS_EXISTING_BOX( ((isom_mvex_t *)parent)->mehd ) )
1971 return isom_read_unknown_box( file, box, parent, level );
1972 ADD_BOX( mehd, isom_mvex_t );
1973 lsmash_bs_t *bs = file->bs;
1974 if( box->version == 1 )
1975 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1976 else
1977 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1978 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1981 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1983 uint32_t temp = lsmash_bs_get_be32( bs );
1984 isom_sample_flags_t flags;
1985 flags.reserved = (temp >> 28) & 0xf;
1986 flags.is_leading = (temp >> 26) & 0x3;
1987 flags.sample_depends_on = (temp >> 24) & 0x3;
1988 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1989 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1990 flags.sample_padding_value = (temp >> 17) & 0x7;
1991 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1992 flags.sample_degradation_priority = temp & 0xffff;
1993 return flags;
1996 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1998 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
1999 return isom_read_unknown_box( file, box, parent, level );
2000 ADD_BOX( trex, isom_mvex_t );
2001 box->parent = parent;
2002 lsmash_bs_t *bs = file->bs;
2003 trex->track_ID = lsmash_bs_get_be32( bs );
2004 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
2005 trex->default_sample_duration = lsmash_bs_get_be32( bs );
2006 trex->default_sample_size = lsmash_bs_get_be32( bs );
2007 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
2008 return isom_read_leaf_box_common_last_process( file, box, level, trex );
2011 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2013 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2014 return isom_read_unknown_box( file, box, parent, level );
2015 ADD_BOX( moof, lsmash_file_t );
2016 box->parent = parent;
2017 isom_box_common_copy( moof, box );
2018 int ret = isom_add_print_func( file, moof, level );
2019 if( ret < 0 )
2020 return ret;
2021 return isom_read_children( file, box, moof, level );
2024 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2026 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF )
2027 || LSMASH_IS_EXISTING_BOX( ((isom_moof_t *)parent)->mfhd ) )
2028 return isom_read_unknown_box( file, box, parent, level );
2029 ADD_BOX( mfhd, isom_moof_t );
2030 lsmash_bs_t *bs = file->bs;
2031 mfhd->sequence_number = lsmash_bs_get_be32( bs );
2032 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
2035 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2037 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
2038 return isom_read_unknown_box( file, box, parent, level );
2039 ADD_BOX( traf, isom_moof_t );
2040 box->parent = parent;
2041 isom_box_common_copy( traf, box );
2042 int ret = isom_add_print_func( file, traf, level );
2043 if( ret < 0 )
2044 return ret;
2045 return isom_read_children( file, box, traf, level );
2048 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2050 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF )
2051 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->tfhd ) )
2052 return isom_read_unknown_box( file, box, parent, level );
2053 ADD_BOX( tfhd, isom_traf_t );
2054 lsmash_bs_t *bs = file->bs;
2055 tfhd->track_ID = lsmash_bs_get_be32( bs );
2056 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2057 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2058 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2059 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2060 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2061 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2064 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2066 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF )
2067 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->tfdt ) )
2068 return isom_read_unknown_box( file, box, parent, level );
2069 ADD_BOX( tfdt, isom_traf_t );
2070 lsmash_bs_t *bs = file->bs;
2071 if( box->version == 1 )
2072 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2073 else
2074 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2075 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2078 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2080 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2081 return isom_read_unknown_box( file, box, parent, level );
2082 ADD_BOX( trun, isom_traf_t );
2083 box->parent = parent;
2084 lsmash_bs_t *bs = file->bs;
2085 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2086 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2087 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2088 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2089 has_optional_rows &= box->flags;
2090 trun->sample_count = lsmash_bs_get_be32( bs );
2091 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2092 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2093 if( trun->sample_count && has_optional_rows )
2095 trun->optional = lsmash_list_create_simple();
2096 if( !trun->optional )
2097 return LSMASH_ERR_MEMORY_ALLOC;
2098 for( uint32_t i = 0; i < trun->sample_count; i++ )
2100 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2101 if( !data )
2102 return LSMASH_ERR_MEMORY_ALLOC;
2103 if( lsmash_list_add_entry( trun->optional, data ) < 0 )
2105 lsmash_free( data );
2106 return LSMASH_ERR_MEMORY_ALLOC;
2108 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2109 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2110 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2111 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2114 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2117 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2119 if( file->fake_file_mode )
2120 return isom_read_unknown_box( file, box, parent, level );
2121 isom_skip_t *skip = ALLOCATE_BOX( skip );
2122 if( LSMASH_IS_NON_EXISTING_BOX( skip ) )
2123 return LSMASH_ERR_MEMORY_ALLOC;
2124 isom_skip_box_rest( file->bs, box );
2125 box->manager |= LSMASH_ABSENT_IN_FILE;
2126 isom_box_common_copy( skip, box );
2127 int ret = isom_add_print_func( file, skip, level );
2128 if( ret < 0 )
2130 isom_remove_box_by_itself( skip );
2131 return ret;
2133 return 0;
2136 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2138 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2139 return isom_read_unknown_box( file, box, parent, level );
2140 isom_mdat_t *mdat = ALLOCATE_BOX( mdat );
2141 if( LSMASH_IS_NON_EXISTING_BOX( mdat ) )
2142 return LSMASH_ERR_MEMORY_ALLOC;
2143 isom_skip_box_rest( file->bs, box );
2144 box->manager |= LSMASH_ABSENT_IN_FILE;
2145 file->flags |= LSMASH_FILE_MODE_MEDIA;
2146 isom_box_common_copy( mdat, box );
2147 int ret = isom_add_print_func( file, mdat, level );
2148 if( ret < 0 )
2150 isom_remove_box_by_itself( mdat );
2151 return ret;
2153 return 0;
2156 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2158 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2159 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2160 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2161 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2162 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->meta ))
2163 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->meta ))
2164 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->meta ))
2165 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->meta )) )
2166 return isom_read_unknown_box( file, box, parent, level );
2167 ADD_BOX( meta, void );
2168 isom_box_common_copy( meta, box );
2169 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2170 if( is_qtff )
2172 box->manager |= LSMASH_QTFF_BASE;
2173 meta->manager |= LSMASH_QTFF_BASE;
2175 int ret = isom_add_print_func( file, meta, level );
2176 if( ret < 0 )
2177 return ret;
2178 return isom_read_children( file, box, meta, level );
2181 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2183 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2184 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->keys ) )
2185 return isom_read_unknown_box( file, box, parent, level );
2186 ADD_BOX( keys, isom_meta_t );
2187 lsmash_bs_t *bs = file->bs;
2188 uint32_t entry_count = lsmash_bs_get_be32( bs );
2189 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2191 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2192 if( !data )
2193 return LSMASH_ERR_MEMORY_ALLOC;
2194 if( lsmash_list_add_entry( keys->list, data ) < 0 )
2196 lsmash_free( data );
2197 return LSMASH_ERR_MEMORY_ALLOC;
2199 data->key_size = lsmash_bs_get_be32( bs );
2200 data->key_namespace = lsmash_bs_get_be32( bs );
2201 if( data->key_size > 8 )
2203 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2204 if( !data->key_value )
2205 return LSMASH_ERR_NAMELESS;
2207 else
2208 data->key_value = NULL;
2210 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2213 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2215 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2216 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2217 || ((isom_meta_t *)parent)->ilst )
2218 return isom_read_unknown_box( file, box, parent, level );
2219 ADD_BOX( ilst, isom_meta_t );
2220 isom_box_common_copy( ilst, box );
2221 int ret = isom_add_print_func( file, ilst, level );
2222 if( ret < 0 )
2223 return ret;
2224 return isom_read_children( file, box, ilst, level );
2227 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2229 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2230 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2231 return isom_read_unknown_box( file, box, parent, level );
2232 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2233 if( !metaitem )
2234 return -1;
2235 box->parent = parent;
2236 isom_box_common_copy( metaitem, box );
2237 int ret = isom_add_print_func( file, metaitem, level );
2238 if( ret < 0 )
2239 return ret;
2240 return isom_read_children( file, box, metaitem, level );
2243 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2245 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM
2246 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->mean ) )
2247 return isom_read_unknown_box( file, box, parent, level );
2248 ADD_BOX( mean, isom_metaitem_t );
2249 lsmash_bs_t *bs = file->bs;
2250 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2251 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2252 if( !mean->meaning_string )
2253 return LSMASH_ERR_NAMELESS;
2254 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2257 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2259 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM
2260 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->name ) )
2261 return isom_read_unknown_box( file, box, parent, level );
2262 ADD_BOX( name, isom_metaitem_t );
2263 lsmash_bs_t *bs = file->bs;
2264 name->name_length = box->size - lsmash_bs_count( bs );
2265 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2266 if( !name->name )
2267 return LSMASH_ERR_NAMELESS;
2268 return isom_read_leaf_box_common_last_process( file, box, level, name );
2271 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2273 if( LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->data ) )
2274 return isom_read_unknown_box( file, box, parent, level );
2275 ADD_BOX( data, isom_metaitem_t );
2276 lsmash_bs_t *bs = file->bs;
2277 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2278 data->reserved = lsmash_bs_get_be16( bs );
2279 data->type_set_identifier = lsmash_bs_get_byte( bs );
2280 data->type_code = lsmash_bs_get_byte( bs );
2281 data->the_locale = lsmash_bs_get_be32( bs );
2282 if( data->value_length )
2284 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2285 if( !data->value )
2286 return LSMASH_ERR_NAMELESS;
2288 return isom_read_leaf_box_common_last_process( file, box, level, data );
2291 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2293 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2294 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->WLOC ) )
2295 return isom_read_unknown_box( file, box, parent, level );
2296 ADD_BOX( WLOC, isom_udta_t );
2297 lsmash_bs_t *bs = file->bs;
2298 WLOC->x = lsmash_bs_get_be16( bs );
2299 WLOC->y = lsmash_bs_get_be16( bs );
2300 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2303 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2305 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2306 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->LOOP ) )
2307 return isom_read_unknown_box( file, box, parent, level );
2308 ADD_BOX( LOOP, isom_udta_t );
2309 lsmash_bs_t *bs = file->bs;
2310 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2311 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2314 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2316 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2317 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->SelO ) )
2318 return isom_read_unknown_box( file, box, parent, level );
2319 ADD_BOX( SelO, isom_udta_t );
2320 lsmash_bs_t *bs = file->bs;
2321 SelO->selection_only = lsmash_bs_get_byte( bs );
2322 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2325 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2327 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2328 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->AllF ) )
2329 return isom_read_unknown_box( file, box, parent, level );
2330 ADD_BOX( AllF, isom_udta_t );
2331 lsmash_bs_t *bs = file->bs;
2332 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2333 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2336 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2338 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2339 return isom_read_unknown_box( file, box, parent, level );
2340 ADD_BOX( cprt, isom_udta_t );
2341 box->parent = parent;
2342 lsmash_bs_t *bs = file->bs;
2343 cprt->language = lsmash_bs_get_be16( bs );
2344 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2345 if( cprt->notice_length )
2347 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2348 if( !cprt->notice )
2350 cprt->notice_length = 0;
2351 return LSMASH_ERR_NAMELESS;
2354 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2357 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2359 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2360 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->mfra ) )
2361 return isom_read_unknown_box( file, box, parent, level );
2362 ADD_BOX( mfra, lsmash_file_t );
2363 isom_box_common_copy( mfra, box );
2364 int ret = isom_add_print_func( file, mfra, level );
2365 if( ret < 0 )
2366 return ret;
2367 return isom_read_children( file, box, mfra, level );
2370 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2372 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2373 return isom_read_unknown_box( file, box, parent, level );
2374 ADD_BOX( tfra, isom_mfra_t );
2375 box->parent = parent;
2376 lsmash_bs_t *bs = file->bs;
2377 tfra->track_ID = lsmash_bs_get_be32( bs );
2378 uint32_t temp = lsmash_bs_get_be32( bs );
2379 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2380 tfra->reserved = (temp >> 6) & 0x3ffffff;
2381 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2382 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2383 tfra->length_size_of_sample_num = temp & 0x3;
2384 if( tfra->number_of_entry )
2386 tfra->list = lsmash_list_create_simple();
2387 if( !tfra->list )
2388 return LSMASH_ERR_MEMORY_ALLOC;
2389 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2391 lsmash_bs_get_byte_to_64,
2392 lsmash_bs_get_be16_to_64,
2393 lsmash_bs_get_be24_to_64,
2394 lsmash_bs_get_be32_to_64,
2395 lsmash_bs_get_be64
2397 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2398 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2399 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2400 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2401 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2402 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2404 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2405 if( !data )
2406 return LSMASH_ERR_MEMORY_ALLOC;
2407 if( lsmash_list_add_entry( tfra->list, data ) < 0 )
2409 lsmash_free( data );
2410 return LSMASH_ERR_MEMORY_ALLOC;
2412 data->time = bs_put_time ( bs );
2413 data->moof_offset = bs_put_moof_offset ( bs );
2414 data->traf_number = bs_put_traf_number ( bs );
2415 data->trun_number = bs_put_trun_number ( bs );
2416 data->sample_number = bs_put_sample_number( bs );
2419 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2422 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2424 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA )
2425 || LSMASH_IS_EXISTING_BOX( ((isom_mfra_t *)parent)->mfro ) )
2426 return isom_read_unknown_box( file, box, parent, level );
2427 ADD_BOX( mfro, isom_mfra_t );
2428 lsmash_bs_t *bs = file->bs;
2429 mfro->length = lsmash_bs_get_be32( bs );
2430 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2433 static void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2435 if( !bs->unseekable )
2437 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2438 while( size > (INT64_MAX >> 1) )
2440 lsmash_bs_read_seek( bs, INT64_MAX >> 1, SEEK_CUR );
2441 if( lsmash_bs_is_end( bs, 0 ) )
2442 return;
2443 size -= (INT64_MAX >> 1);
2445 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2447 else
2448 lsmash_bs_skip_bytes_64( bs, size );
2451 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2453 lsmash_bs_t *bs = file->bs;
2454 /* Skip extra bytes of the parent box if any. */
2455 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2457 uint64_t extra_bytes = parent->size - parent_pos;
2458 isom_read_skip_extra_bytes( bs, extra_bytes );
2459 /* This is not the size of a box but makes sense in isom_read_children(). */
2460 box->size = extra_bytes;
2461 return 1;
2463 /* Check if the size is valid or not. */
2464 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2466 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2467 if( size > 1
2468 && size < ISOM_BASEBOX_COMMON_SIZE )
2470 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2471 * Skip bytes up to the next box of the parent box. */
2472 uint64_t extra_bytes = parent->size - parent_pos;
2473 isom_read_skip_extra_bytes( bs, extra_bytes );
2474 box->size = extra_bytes;
2475 return 1;
2477 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2478 size = lsmash_bs_show_be64( bs, 8 ); /* large size */
2479 if( size == 0 && parent != (isom_box_t *)file )
2481 /* Check if this box is actually the last box or not. */
2482 uint64_t extra_bytes = parent->size - parent_pos;
2483 if( !bs->unseekable )
2484 size = bs->written - lsmash_bs_get_stream_pos( bs );
2485 else
2487 size = lsmash_bs_get_remaining_buffer_size( bs );
2488 while( size <= extra_bytes )
2490 int ret = lsmash_bs_read( bs, 1 );
2491 if( bs->eof || ret < 0 )
2492 break;
2493 size = lsmash_bs_get_remaining_buffer_size( bs );
2496 if( size != extra_bytes )
2498 /* This is not the size of the last box.
2499 * It seems we are still within the box considered as the previous or the parent box.
2500 * Skip bytes up to the next box. */
2501 if( box->size > lsmash_bs_count( bs ) )
2503 /* within the previous */
2504 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2505 box->size = 0; /* already added to the size of the parent box */
2507 else
2509 /* within the parent */
2510 isom_read_skip_extra_bytes( bs, extra_bytes );
2511 box->size = extra_bytes;
2513 return 1;
2517 return 0;
2520 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2522 assert( parent && parent->root && parent->file );
2523 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2524 return 0;
2525 memset( box, 0, sizeof(isom_box_t) );
2526 box->root = parent->root;
2527 box->file = parent->file;
2528 box->parent = parent;
2529 lsmash_bs_t *bs = file->bs;
2530 int ret = isom_bs_read_box_common( bs, box );
2531 if( !!ret )
2532 return ret; /* return if reached EOF */
2533 ++level;
2534 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2535 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2536 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2538 /* OK, this box is a sample entry.
2539 * Here, determine the suitable sample entry reader by media type if possible. */
2540 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
2541 goto read_box;
2542 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
2543 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2544 reader_func = isom_read_visual_description;
2545 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2546 reader_func = isom_read_audio_description;
2547 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2548 reader_func = isom_read_text_description;
2549 else
2550 reader_func = isom_read_other_description;
2551 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2552 static struct description_reader_table_tag
2554 lsmash_compact_box_type_t fourcc;
2555 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2556 } description_reader_table[160] = { { 0, NULL } };
2557 if( !description_reader_table[0].form_box_type_func )
2559 /* Initialize the table. */
2560 int i = 0;
2561 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2562 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type );
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type );
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type );
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO, lsmash_form_qtff_box_type );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type );
2604 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type );
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type );
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO, lsmash_form_qtff_box_type );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type );
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type );
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type );
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSEL_AUDIO, lsmash_form_iso_box_type );
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSDL_AUDIO, lsmash_form_iso_box_type );
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type );
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type );
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type );
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type );
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSX_AUDIO, lsmash_form_iso_box_type );
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type );
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type );
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type );
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type );
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type );
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type );
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type );
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type );
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type );
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type );
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type );
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type );
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type );
2664 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2665 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type );
2666 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type );
2667 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type );
2668 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type );
2669 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type );
2670 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type );
2671 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type );
2672 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type );
2673 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type );
2674 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type );
2675 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type );
2676 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type );
2677 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type );
2678 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type );
2679 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type );
2680 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type );
2681 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type );
2682 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type );
2683 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type );
2684 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type );
2685 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type );
2686 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type );
2687 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type );
2688 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type );
2689 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type );
2690 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type );
2691 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type );
2692 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type );
2693 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type );
2694 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type );
2695 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type );
2696 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type );
2697 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type );
2698 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW, lsmash_form_qtff_box_type );
2699 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL );
2700 assert( sizeof(description_reader_table) >= (size_t)i * sizeof(description_reader_table[0]) );
2701 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2703 for( int i = 0; description_reader_table[i].form_box_type_func; i++ )
2704 if( box->type.fourcc == description_reader_table[i].fourcc )
2706 form_box_type_func = description_reader_table[i].form_box_type_func;
2707 goto read_box;
2709 goto read_box;
2711 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2713 form_box_type_func = lsmash_form_qtff_box_type;
2714 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2715 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2716 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2717 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2718 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2719 else reader_func = isom_read_codec_specific;
2720 goto read_box;
2722 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2724 form_box_type_func = lsmash_form_iso_box_type;
2725 reader_func = isom_read_track_reference_type;
2726 goto read_box;
2728 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2730 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2731 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2732 form_box_type_func = lsmash_form_iso_box_type;
2733 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2734 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2735 form_box_type_func = lsmash_form_qtff_box_type;
2736 reader_func = isom_read_dref_entry;
2737 goto read_box;
2739 static struct box_reader_table_tag
2741 lsmash_compact_box_type_t fourcc;
2742 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2743 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2744 } box_reader_table[128] = { { 0, NULL, NULL } };
2745 if( !box_reader_table[0].reader_func )
2747 /* Initialize the table. */
2748 int i = 0;
2749 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2750 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2753 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2754 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2755 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2756 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2757 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2758 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2760 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2761 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2762 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2763 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2769 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2773 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2774 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2775 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2776 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2777 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2778 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2779 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2780 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2781 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2783 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2786 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2787 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2788 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2789 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, lsmash_form_iso_box_type, isom_read_stz2 );
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2792 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2794 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2796 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2797 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2798 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2799 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2800 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2801 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2802 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2803 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2804 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2805 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2806 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2807 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2808 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2809 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2810 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2811 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2812 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2813 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2814 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2815 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2816 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2817 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2818 assert( sizeof(box_reader_table) >= (size_t)i * sizeof(box_reader_table[0]) );
2819 #undef ADD_BOX_READER_TABLE_ELEMENT
2821 for( int i = 0; box_reader_table[i].reader_func; i++ )
2822 if( box->type.fourcc == box_reader_table[i].fourcc )
2824 form_box_type_func = box_reader_table[i].form_box_type_func;
2825 reader_func = box_reader_table[i].reader_func;
2826 goto read_box;
2828 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2830 if( lsmash_bs_is_end ( bs, 3 ) == 0
2831 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2832 form_box_type_func = lsmash_form_iso_box_type;
2833 else
2834 form_box_type_func = lsmash_form_qtff_box_type;
2835 reader_func = isom_read_meta;
2836 goto read_box;
2838 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2840 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2841 form_box_type_func = lsmash_form_iso_box_type;
2842 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2843 form_box_type_func = lsmash_form_qtff_box_type;
2844 if( form_box_type_func )
2846 reader_func = isom_read_ilst;
2847 goto read_box;
2850 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2851 form_box_type_func = lsmash_form_iso_box_type;
2852 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2853 form_box_type_func = lsmash_form_qtff_box_type;
2854 if( form_box_type_func )
2856 reader_func = isom_read_metaitem;
2857 goto read_box;
2859 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2861 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2862 reader_func = isom_read_mean;
2863 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2864 reader_func = isom_read_name;
2865 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2866 reader_func = isom_read_data;
2867 if( reader_func )
2869 form_box_type_func = lsmash_form_iso_box_type;
2870 goto read_box;
2873 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2875 /* Avoid confusing udta.cprt with ilst.cprt. */
2876 form_box_type_func = lsmash_form_iso_box_type;
2877 reader_func = isom_read_cprt;
2878 goto read_box;
2880 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2882 static struct sample_description_extension_reader_table_tag
2884 lsmash_compact_box_type_t fourcc;
2885 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2886 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2887 } extension_reader_table[32] = { { 0, NULL, NULL } };
2888 if( !extension_reader_table[0].reader_func )
2890 /* Initialize the table. */
2891 int i = 0;
2892 #define ADD_EXTENSION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2893 extension_reader_table[i++] = (struct sample_description_extension_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2894 /* Audio */
2895 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type, isom_read_codec_specific );
2896 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type, isom_read_codec_specific );
2897 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type, isom_read_codec_specific );
2898 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type, isom_read_codec_specific );
2899 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type, isom_read_codec_specific );
2900 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2901 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type, isom_read_codec_specific );
2902 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2903 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2904 /* Video */
2905 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type, isom_read_codec_specific );
2906 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2907 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2908 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2909 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type, isom_read_codec_specific );
2910 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type, isom_read_codec_specific );
2911 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2912 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2913 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2914 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2915 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2916 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2917 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2918 /* Others */
2919 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2920 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2921 ADD_EXTENSION_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2922 assert( sizeof(extension_reader_table) >= (size_t)i * sizeof(extension_reader_table[0]) );
2923 #undef ADD_EXTENSION_READER_TABLE_ELEMENT
2925 for( int i = 0; extension_reader_table[i].reader_func; i++ )
2926 if( box->type.fourcc == extension_reader_table[i].fourcc )
2928 form_box_type_func = extension_reader_table[i].form_box_type_func;
2929 reader_func = extension_reader_table[i].reader_func;
2930 goto read_box;
2932 reader_func = isom_read_codec_specific;
2934 read_box:
2935 if( form_box_type_func )
2936 box->type = form_box_type_func( box->type.fourcc );
2937 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2938 return ret;
2939 return reader_func
2940 ? reader_func( file, box, parent, level )
2941 : isom_read_unknown_box( file, box, parent, level );
2944 int isom_read_file( lsmash_file_t *file )
2946 lsmash_bs_t *bs = file->bs;
2947 if( !bs )
2948 return LSMASH_ERR_NAMELESS;
2949 /* Reset the counter so that we can use it to get position within the box. */
2950 lsmash_bs_reset_counter( bs );
2951 if( file->flags & LSMASH_FILE_MODE_DUMP )
2953 file->print = isom_printer_create_list();
2954 if( !file->print )
2955 return LSMASH_ERR_MEMORY_ALLOC;
2957 file->size = UINT64_MAX;
2958 isom_box_t box;
2959 int ret = isom_read_children( file, &box, file, 0 );
2960 file->size = box.size;
2961 lsmash_bs_empty( bs );
2962 bs->error = 0; /* Clear error flag. */
2963 if( ret < 0 )
2964 return ret;
2965 return isom_check_compatibility( file );