write: Fix type size for mdcv luminance
[L-SMASH.git] / core / read.c
blobbdcd6623bb2594f3bfcb0fd7b72bb7b299ff847a
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_clli( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1184 ADD_BOX( clli, isom_visual_entry_t );
1185 lsmash_bs_t *bs = file->bs;
1186 clli->max_content_light_level = lsmash_bs_get_be16( bs );
1187 clli->max_pic_average_light_level = lsmash_bs_get_be16( bs );
1188 return isom_read_leaf_box_common_last_process( file, box, level, clli );
1191 static int isom_read_mdcv( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1193 ADD_BOX( mdcv, isom_visual_entry_t );
1194 lsmash_bs_t *bs = file->bs;
1195 mdcv->display_primaries_g_x = lsmash_bs_get_be16( bs );
1196 mdcv->display_primaries_g_y = lsmash_bs_get_be16( bs );
1197 mdcv->display_primaries_b_x = lsmash_bs_get_be16( bs );
1198 mdcv->display_primaries_b_y = lsmash_bs_get_be16( bs );
1199 mdcv->display_primaries_r_x = lsmash_bs_get_be16( bs );
1200 mdcv->display_primaries_r_y = lsmash_bs_get_be16( bs );
1201 mdcv->white_point_x = lsmash_bs_get_be16( bs );
1202 mdcv->white_point_y = lsmash_bs_get_be16( bs );
1203 mdcv->max_display_mastering_luminance = lsmash_bs_get_be32( bs );
1204 mdcv->min_display_mastering_luminance = lsmash_bs_get_be32( bs );
1205 return isom_read_leaf_box_common_last_process( file, box, level, mdcv );
1208 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1210 ADD_BOX( cspc, isom_visual_entry_t );
1211 lsmash_bs_t *bs = file->bs;
1212 cspc->pixel_format = lsmash_bs_get_be32( bs );
1213 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1216 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1218 ADD_BOX( sgbt, isom_visual_entry_t );
1219 lsmash_bs_t *bs = file->bs;
1220 sgbt->significantBits = lsmash_bs_get_byte( bs );
1221 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1224 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1226 ADD_BOX( stsl, isom_visual_entry_t );
1227 lsmash_bs_t *bs = file->bs;
1228 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1229 stsl->scale_method = lsmash_bs_get_byte( bs );
1230 stsl->display_center_x = lsmash_bs_get_be16( bs );
1231 stsl->display_center_y = lsmash_bs_get_be16( bs );
1232 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1235 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1237 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1238 return isom_read_unknown_box( file, box, parent, level );
1239 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1240 if( LSMASH_IS_NON_EXISTING_BOX( audio ) )
1241 return LSMASH_ERR_MEMORY_ALLOC;
1242 lsmash_bs_t *bs = file->bs;
1243 for( int i = 0; i < 6; i++ )
1244 audio->reserved[i] = lsmash_bs_get_byte( bs );
1245 audio->data_reference_index = lsmash_bs_get_be16( bs );
1246 audio->version = lsmash_bs_get_be16( bs );
1247 audio->revision_level = lsmash_bs_get_be16( bs );
1248 audio->vendor = lsmash_bs_get_be32( bs );
1249 audio->channelcount = lsmash_bs_get_be16( bs );
1250 audio->samplesize = lsmash_bs_get_be16( bs );
1251 audio->compression_ID = lsmash_bs_get_be16( bs );
1252 audio->packet_size = lsmash_bs_get_be16( bs );
1253 audio->samplerate = lsmash_bs_get_be32( bs );
1254 if( audio->version == 0 && isom_is_qt_audio( box->type ) )
1256 /* Skip weird extra bytes.
1257 * About QTFF, extensions were first added with Sound Sample Description v1. */
1258 while( lsmash_bs_count( bs ) + ISOM_BASEBOX_COMMON_SIZE <= box->size )
1260 uint32_t size = lsmash_bs_show_be32( bs, 0 );
1261 if( size == 0 || lsmash_bs_count( bs ) + size > box->size )
1262 lsmash_bs_skip_bytes( bs, 1 );
1263 else
1264 break;
1267 else if( audio->version == 1 )
1269 if( ((isom_stsd_t *)parent)->version == 0 )
1271 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1272 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1273 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1274 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1275 box->manager |= LSMASH_QTFF_BASE;
1277 else
1278 /* AudioSampleEntryV1 has no additional fields. */
1279 box->manager &= ~LSMASH_QTFF_BASE;
1281 else if( audio->version == 2 )
1283 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1284 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1285 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1286 audio->always7F000000 = lsmash_bs_get_be32( bs );
1287 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1288 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1289 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1290 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1291 box->manager |= LSMASH_QTFF_BASE;
1293 box->parent = parent;
1294 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1295 isom_box_common_copy( audio, box );
1296 int ret = isom_add_print_func( file, audio, level );
1297 if( ret < 0 )
1298 return ret;
1299 return isom_read_children( file, box, audio, level );
1302 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1304 ADD_BOX( wave, isom_audio_entry_t );
1305 isom_box_common_copy( wave, box );
1306 int ret = isom_add_print_func( file, wave, level );
1307 if( ret < 0 )
1308 return ret;
1309 return isom_read_children( file, box, wave, level );
1312 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1314 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1315 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->frma ) )
1316 return isom_read_unknown_box( file, box, parent, level );
1317 ADD_BOX( frma, isom_wave_t );
1318 lsmash_bs_t *bs = file->bs;
1319 frma->data_format = lsmash_bs_get_be32( bs );
1320 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1323 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1325 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1326 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->enda ) )
1327 return isom_read_unknown_box( file, box, parent, level );
1328 ADD_BOX( enda, isom_wave_t );
1329 lsmash_bs_t *bs = file->bs;
1330 enda->littleEndian = lsmash_bs_get_be16( bs );
1331 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1334 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1336 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE )
1337 || LSMASH_IS_EXISTING_BOX( ((isom_wave_t *)parent)->terminator ) )
1338 return isom_read_unknown_box( file, box, parent, level );
1339 ADD_BOX( terminator, isom_wave_t );
1340 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1343 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1345 ADD_BOX( chan, isom_audio_entry_t );
1346 lsmash_bs_t *bs = file->bs;
1347 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1348 chan->channelBitmap = lsmash_bs_get_be32( bs );
1349 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1350 if( chan->numberChannelDescriptions )
1352 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1353 if( !desc )
1354 return LSMASH_ERR_MEMORY_ALLOC;
1355 chan->channelDescriptions = desc;
1356 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1358 desc->channelLabel = lsmash_bs_get_be32( bs );
1359 desc->channelFlags = lsmash_bs_get_be32( bs );
1360 for( int j = 0; j < 3; j++ )
1361 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1364 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1367 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1369 ADD_BOX( srat, isom_audio_entry_t );
1370 lsmash_bs_t *bs = file->bs;
1371 srat->sampling_rate = lsmash_bs_get_be32( bs );
1372 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1375 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1377 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1378 return isom_read_unknown_box( file, box, parent, level );
1379 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1380 if( LSMASH_IS_NON_EXISTING_BOX( text ) )
1381 return LSMASH_ERR_MEMORY_ALLOC;
1382 lsmash_bs_t *bs = file->bs;
1383 for( int i = 0; i < 6; i++ )
1384 text->reserved[i] = lsmash_bs_get_byte( bs );
1385 text->data_reference_index = lsmash_bs_get_be16( bs );
1386 text->displayFlags = lsmash_bs_get_be32( bs );
1387 text->textJustification = lsmash_bs_get_be32( bs );
1388 for( int i = 0; i < 3; i++ )
1389 text->bgColor[i] = lsmash_bs_get_be16( bs );
1390 text->top = lsmash_bs_get_be16( bs );
1391 text->left = lsmash_bs_get_be16( bs );
1392 text->bottom = lsmash_bs_get_be16( bs );
1393 text->right = lsmash_bs_get_be16( bs );
1394 text->scrpStartChar = lsmash_bs_get_be32( bs );
1395 text->scrpHeight = lsmash_bs_get_be16( bs );
1396 text->scrpAscent = lsmash_bs_get_be16( bs );
1397 text->scrpFont = lsmash_bs_get_be16( bs );
1398 text->scrpFace = lsmash_bs_get_be16( bs );
1399 text->scrpSize = lsmash_bs_get_be16( bs );
1400 for( int i = 0; i < 3; i++ )
1401 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1402 text->font_name_length = lsmash_bs_get_byte( bs );
1403 if( text->font_name_length )
1405 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1406 if( !text->font_name )
1407 return LSMASH_ERR_MEMORY_ALLOC;
1408 for( uint8_t i = 0; i < text->font_name_length; i++ )
1409 text->font_name[i] = lsmash_bs_get_byte( bs );
1410 text->font_name[text->font_name_length] = '\0';
1412 box->parent = parent;
1413 isom_box_common_copy( text, box );
1414 int ret = isom_add_print_func( file, text, level );
1415 if( ret < 0 )
1416 return ret;
1417 return isom_read_children( file, box, text, level );
1420 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1422 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1423 return isom_read_unknown_box( file, box, parent, level );
1424 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1425 if( LSMASH_IS_NON_EXISTING_BOX( tx3g ) )
1426 return LSMASH_ERR_MEMORY_ALLOC;
1427 lsmash_bs_t *bs = file->bs;
1428 for( int i = 0; i < 6; i++ )
1429 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1430 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1431 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1432 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1433 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1434 for( int i = 0; i < 4; i++ )
1435 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1436 tx3g->top = lsmash_bs_get_be16( bs );
1437 tx3g->left = lsmash_bs_get_be16( bs );
1438 tx3g->bottom = lsmash_bs_get_be16( bs );
1439 tx3g->right = lsmash_bs_get_be16( bs );
1440 tx3g->startChar = lsmash_bs_get_be16( bs );
1441 tx3g->endChar = lsmash_bs_get_be16( bs );
1442 tx3g->font_ID = lsmash_bs_get_be16( bs );
1443 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1444 tx3g->font_size = lsmash_bs_get_byte( bs );
1445 for( int i = 0; i < 4; i++ )
1446 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1447 box->parent = parent;
1448 isom_box_common_copy( tx3g, box );
1449 int ret = isom_add_print_func( file, tx3g, level );
1450 if( ret < 0 )
1451 return ret;
1452 return isom_read_children( file, box, tx3g, level );
1455 static int isom_read_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1457 if( lsmash_check_codec_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1458 return isom_read_qt_text_description( file, box, parent, level );
1459 else if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1460 return isom_read_tx3g_description( file, box, parent, level );
1461 assert( 0 );
1462 return isom_read_unknown_box( file, box, parent, level );
1465 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1467 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1468 || LSMASH_IS_EXISTING_BOX( ((isom_tx3g_entry_t *)parent)->ftab ) )
1469 return isom_read_codec_specific( file, box, parent, level );
1470 ADD_BOX( ftab, isom_tx3g_entry_t );
1471 lsmash_bs_t *bs = file->bs;
1472 uint32_t entry_count = lsmash_bs_get_be16( bs );
1473 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1475 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1476 if( !data )
1477 return LSMASH_ERR_MEMORY_ALLOC;
1478 if( lsmash_list_add_entry( ftab->list, data ) < 0 )
1480 lsmash_free( data );
1481 return LSMASH_ERR_MEMORY_ALLOC;
1483 data->font_ID = lsmash_bs_get_be16( bs );
1484 data->font_name_length = lsmash_bs_get_byte( bs );
1485 if( data->font_name_length )
1487 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1488 if( !data->font_name )
1489 return LSMASH_ERR_MEMORY_ALLOC;
1490 for( uint8_t i = 0; i < data->font_name_length; i++ )
1491 data->font_name[i] = lsmash_bs_get_byte( bs );
1492 data->font_name[data->font_name_length] = '\0';
1495 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1498 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1500 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1501 return isom_read_unknown_box( file, box, parent, level );
1502 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1503 if( LSMASH_IS_NON_EXISTING_BOX( mp4s ) )
1504 return LSMASH_ERR_MEMORY_ALLOC;
1505 lsmash_bs_t *bs = file->bs;
1506 for( int i = 0; i < 6; i++ )
1507 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1508 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1509 box->parent = parent;
1510 isom_box_common_copy( mp4s, box );
1511 int ret = isom_add_print_func( file, mp4s, level );
1512 if( ret < 0 )
1513 return ret;
1514 return isom_read_children( file, box, mp4s, level );
1517 static int isom_read_other_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1519 if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
1520 return isom_read_mp4s_description( file, box, parent, level );
1521 return isom_read_unknown_box( file, box, parent, level );
1524 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1526 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1527 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stts ) )
1528 return isom_read_unknown_box( file, box, parent, level );
1529 ADD_BOX( stts, isom_stbl_t );
1530 lsmash_bs_t *bs = file->bs;
1531 uint32_t entry_count = lsmash_bs_get_be32( bs );
1532 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1534 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1535 if( !data )
1536 return LSMASH_ERR_MEMORY_ALLOC;
1537 if( lsmash_list_add_entry( stts->list, data ) < 0 )
1539 lsmash_free( data );
1540 return LSMASH_ERR_MEMORY_ALLOC;
1542 data->sample_count = lsmash_bs_get_be32( bs );
1543 data->sample_delta = lsmash_bs_get_be32( bs );
1545 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1548 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1550 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1551 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->ctts ) )
1552 return isom_read_unknown_box( file, box, parent, level );
1553 ADD_BOX( ctts, isom_stbl_t );
1554 lsmash_bs_t *bs = file->bs;
1555 uint32_t entry_count = lsmash_bs_get_be32( bs );
1556 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1558 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1559 if( !data )
1560 return LSMASH_ERR_MEMORY_ALLOC;
1561 if( lsmash_list_add_entry( ctts->list, data ) < 0 )
1563 lsmash_free( data );
1564 return LSMASH_ERR_MEMORY_ALLOC;
1566 data->sample_count = lsmash_bs_get_be32( bs );
1567 data->sample_offset = lsmash_bs_get_be32( bs );
1569 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1572 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1574 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1575 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->cslg ) )
1576 return isom_read_unknown_box( file, box, parent, level );
1577 ADD_BOX( cslg, isom_stbl_t );
1578 lsmash_bs_t *bs = file->bs;
1579 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1580 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1581 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1582 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1583 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1584 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1587 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1589 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1590 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stss ) )
1591 return isom_read_unknown_box( file, box, parent, level );
1592 ADD_BOX( stss, isom_stbl_t );
1593 lsmash_bs_t *bs = file->bs;
1594 uint32_t entry_count = lsmash_bs_get_be32( bs );
1595 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1597 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1598 if( !data )
1599 return LSMASH_ERR_MEMORY_ALLOC;
1600 if( lsmash_list_add_entry( stss->list, data ) < 0 )
1602 lsmash_free( data );
1603 return LSMASH_ERR_MEMORY_ALLOC;
1605 data->sample_number = lsmash_bs_get_be32( bs );
1607 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1610 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1612 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1613 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stps ) )
1614 return isom_read_unknown_box( file, box, parent, level );
1615 ADD_BOX( stps, isom_stbl_t );
1616 lsmash_bs_t *bs = file->bs;
1617 uint32_t entry_count = lsmash_bs_get_be32( bs );
1618 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1620 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1621 if( !data )
1622 return LSMASH_ERR_MEMORY_ALLOC;
1623 if( lsmash_list_add_entry( stps->list, data ) < 0 )
1625 lsmash_free( data );
1626 return LSMASH_ERR_MEMORY_ALLOC;
1628 data->sample_number = lsmash_bs_get_be32( bs );
1630 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1633 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1635 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1636 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1637 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->sdtp ))
1638 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->sdtp )) )
1639 return isom_read_unknown_box( file, box, parent, level );
1640 ADD_BOX( sdtp, isom_box_t );
1641 lsmash_bs_t *bs = file->bs;
1642 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1644 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1645 if( !data )
1646 return LSMASH_ERR_MEMORY_ALLOC;
1647 if( lsmash_list_add_entry( sdtp->list, data ) < 0 )
1649 lsmash_free( data );
1650 return LSMASH_ERR_MEMORY_ALLOC;
1652 uint8_t temp = lsmash_bs_get_byte( bs );
1653 data->is_leading = (temp >> 6) & 0x3;
1654 data->sample_depends_on = (temp >> 4) & 0x3;
1655 data->sample_is_depended_on = (temp >> 2) & 0x3;
1656 data->sample_has_redundancy = temp & 0x3;
1658 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1661 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1663 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1664 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stsc ) )
1665 return isom_read_unknown_box( file, box, parent, level );
1666 ADD_BOX( stsc, isom_stbl_t );
1667 lsmash_bs_t *bs = file->bs;
1668 uint32_t entry_count = lsmash_bs_get_be32( bs );
1669 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1671 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1672 if( !data )
1673 return LSMASH_ERR_MEMORY_ALLOC;
1674 if( lsmash_list_add_entry( stsc->list, data ) < 0 )
1676 lsmash_free( data );
1677 return LSMASH_ERR_MEMORY_ALLOC;
1679 data->first_chunk = lsmash_bs_get_be32( bs );
1680 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1681 data->sample_description_index = lsmash_bs_get_be32( bs );
1683 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1686 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1688 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1689 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stsz ) )
1690 return isom_read_unknown_box( file, box, parent, level );
1691 ADD_BOX( stsz, isom_stbl_t );
1692 lsmash_bs_t *bs = file->bs;
1693 stsz->sample_size = lsmash_bs_get_be32( bs );
1694 stsz->sample_count = lsmash_bs_get_be32( bs );
1695 uint64_t pos = lsmash_bs_count( bs );
1696 if( pos < box->size )
1698 stsz->list = lsmash_list_create_simple();
1699 if( !stsz->list )
1700 return LSMASH_ERR_MEMORY_ALLOC;
1701 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1703 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1704 if( !data )
1705 return LSMASH_ERR_MEMORY_ALLOC;
1706 if( lsmash_list_add_entry( stsz->list, data ) < 0 )
1708 lsmash_free( data );
1709 return LSMASH_ERR_MEMORY_ALLOC;
1711 data->entry_size = lsmash_bs_get_be32( bs );
1714 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1717 static int isom_read_stz2( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1719 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1720 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stz2 ) )
1721 return isom_read_unknown_box( file, box, parent, level );
1722 ADD_BOX( stz2, isom_stbl_t );
1723 lsmash_bs_t *bs = file->bs;
1724 uint32_t temp32 = lsmash_bs_get_be32( bs );
1725 stz2->reserved = temp32 >> 24;
1726 stz2->field_size = temp32 & 0xff;
1727 stz2->sample_count = lsmash_bs_get_be32( bs );
1728 uint64_t pos = lsmash_bs_count( bs );
1729 if( pos < box->size )
1731 if( stz2->field_size == 16 || stz2->field_size == 8 )
1733 uint64_t (*bs_get_funcs[2])( lsmash_bs_t * ) =
1735 lsmash_bs_get_byte_to_64,
1736 lsmash_bs_get_be16_to_64
1738 uint64_t (*bs_get_entry_size)( lsmash_bs_t * ) = bs_get_funcs[ stz2->field_size == 16 ? 1 : 0 ];
1739 for( ; pos < box->size && stz2->list->entry_count < stz2->sample_count; pos = lsmash_bs_count( bs ) )
1741 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1742 if( !data )
1743 return LSMASH_ERR_MEMORY_ALLOC;
1744 if( lsmash_list_add_entry( stz2->list, data ) < 0 )
1746 lsmash_free( data );
1747 return LSMASH_ERR_MEMORY_ALLOC;
1749 data->entry_size = bs_get_entry_size( bs );
1752 else if( stz2->field_size == 4 )
1754 int parity = 1;
1755 uint8_t temp8;
1756 while( pos < box->size && stz2->list->entry_count < stz2->sample_count )
1758 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1759 if( !data )
1760 return LSMASH_ERR_MEMORY_ALLOC;
1761 if( lsmash_list_add_entry( stz2->list, data ) < 0 )
1763 lsmash_free( data );
1764 return LSMASH_ERR_MEMORY_ALLOC;
1766 /* Read a byte by two entries. */
1767 if( parity )
1769 temp8 = lsmash_bs_get_byte( bs );
1770 data->entry_size = (temp8 >> 4) & 0xf;
1772 else
1774 pos = lsmash_bs_count( bs );
1775 data->entry_size = temp8 & 0xf;
1777 parity ^= 1;
1780 else
1781 return LSMASH_ERR_INVALID_DATA;
1783 return isom_read_leaf_box_common_last_process( file, box, level, stz2 );
1786 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1788 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1789 || LSMASH_IS_EXISTING_BOX( ((isom_stbl_t *)parent)->stco ) )
1790 return isom_read_unknown_box( file, box, parent, level );
1791 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1792 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1793 isom_stco_t *stco = is_stco
1794 ? isom_add_stco( (isom_stbl_t *)parent )
1795 : isom_add_co64( (isom_stbl_t *)parent );
1796 if( !stco )
1797 return LSMASH_ERR_NAMELESS;
1798 lsmash_bs_t *bs = file->bs;
1799 uint32_t entry_count = lsmash_bs_get_be32( bs );
1800 if( is_stco )
1801 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1803 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1804 if( !data )
1805 return LSMASH_ERR_MEMORY_ALLOC;
1806 if( lsmash_list_add_entry( stco->list, data ) < 0 )
1808 lsmash_free( data );
1809 return LSMASH_ERR_MEMORY_ALLOC;
1811 data->chunk_offset = lsmash_bs_get_be32( bs );
1813 else
1815 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1817 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1818 if( !data )
1819 return LSMASH_ERR_MEMORY_ALLOC;
1820 if( lsmash_list_add_entry( stco->list, data ) < 0 )
1822 lsmash_free( data );
1823 return LSMASH_ERR_MEMORY_ALLOC;
1825 data->chunk_offset = lsmash_bs_get_be64( bs );
1828 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1831 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1833 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1834 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1835 return isom_read_unknown_box( file, box, parent, level );
1836 ADD_BOX( sgpd, void );
1837 lsmash_bs_t *bs = file->bs;
1838 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1839 if( box->version == 1 )
1840 sgpd->default_length = lsmash_bs_get_be32( bs );
1841 uint32_t entry_count = lsmash_bs_get_be32( bs );
1842 switch( sgpd->grouping_type )
1844 case ISOM_GROUP_TYPE_RAP :
1846 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1848 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
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_rap_entry_t) );
1857 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1858 if( box->version == 1 && !sgpd->default_length )
1859 data->description_length = lsmash_bs_get_be32( bs );
1860 else
1862 uint8_t temp = lsmash_bs_get_byte( bs );
1863 data->num_leading_samples_known = (temp >> 7) & 0x01;
1864 data->num_leading_samples = temp & 0x7f;
1867 break;
1869 case ISOM_GROUP_TYPE_ROLL :
1870 case ISOM_GROUP_TYPE_PROL :
1872 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1874 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1875 if( !data )
1876 return LSMASH_ERR_MEMORY_ALLOC;
1877 if( lsmash_list_add_entry( sgpd->list, data ) < 0 )
1879 lsmash_free( data );
1880 return LSMASH_ERR_MEMORY_ALLOC;
1882 memset( data, 0, sizeof(isom_roll_entry_t) );
1883 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1884 if( box->version == 1 && !sgpd->default_length )
1885 data->description_length = lsmash_bs_get_be32( bs );
1886 else
1887 data->roll_distance = lsmash_bs_get_be16( bs );
1889 break;
1891 default :
1892 break;
1894 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1897 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1899 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1900 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1901 return isom_read_unknown_box( file, box, parent, level );
1902 ADD_BOX( sbgp, void );
1903 lsmash_bs_t *bs = file->bs;
1904 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1905 if( box->version == 1 )
1906 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1907 uint32_t entry_count = lsmash_bs_get_be32( bs );
1908 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1910 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1911 if( !data )
1912 return LSMASH_ERR_MEMORY_ALLOC;
1913 if( lsmash_list_add_entry( sbgp->list, data ) < 0 )
1915 lsmash_free( data );
1916 return LSMASH_ERR_MEMORY_ALLOC;
1918 data->sample_count = lsmash_bs_get_be32( bs );
1919 data->group_description_index = lsmash_bs_get_be32( bs );
1921 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1924 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1926 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1927 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1928 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->udta ))
1929 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->udta )) )
1930 return isom_read_unknown_box( file, box, parent, level );
1931 ADD_BOX( udta, void );
1932 isom_box_common_copy( udta, box );
1933 int ret = isom_add_print_func( file, udta, level );
1934 if( ret < 0 )
1935 return ret;
1936 return isom_read_children( file, box, udta, level );
1939 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1941 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
1942 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->chpl ) )
1943 return isom_read_unknown_box( file, box, parent, level );
1944 ADD_BOX( chpl, isom_udta_t );
1945 lsmash_bs_t *bs = file->bs;
1946 uint32_t entry_count;
1947 if( box->version == 1 )
1949 chpl->unknown = lsmash_bs_get_byte( bs );
1950 entry_count = lsmash_bs_get_be32( bs );
1952 else
1953 entry_count = lsmash_bs_get_byte( bs );
1954 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1956 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1957 if( !data )
1958 return LSMASH_ERR_MEMORY_ALLOC;
1959 if( lsmash_list_add_entry( chpl->list, data ) < 0 )
1961 lsmash_free( data );
1962 return LSMASH_ERR_MEMORY_ALLOC;
1964 data->start_time = lsmash_bs_get_be64( bs );
1965 data->chapter_name_length = lsmash_bs_get_byte( bs );
1966 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1967 if( !data->chapter_name )
1969 lsmash_free( data );
1970 return LSMASH_ERR_MEMORY_ALLOC;
1972 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1973 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1974 data->chapter_name[data->chapter_name_length] = '\0';
1976 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1979 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1981 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1982 || LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->mvex ) )
1983 return isom_read_unknown_box( file, box, parent, level );
1984 ADD_BOX( mvex, isom_moov_t );
1985 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1986 isom_box_common_copy( mvex, box );
1987 int ret = isom_add_print_func( file, mvex, level );
1988 if( ret < 0 )
1989 return ret;
1990 return isom_read_children( file, box, mvex, level );
1993 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1995 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX )
1996 || LSMASH_IS_EXISTING_BOX( ((isom_mvex_t *)parent)->mehd ) )
1997 return isom_read_unknown_box( file, box, parent, level );
1998 ADD_BOX( mehd, isom_mvex_t );
1999 lsmash_bs_t *bs = file->bs;
2000 if( box->version == 1 )
2001 mehd->fragment_duration = lsmash_bs_get_be64( bs );
2002 else
2003 mehd->fragment_duration = lsmash_bs_get_be32( bs );
2004 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
2007 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
2009 uint32_t temp = lsmash_bs_get_be32( bs );
2010 isom_sample_flags_t flags;
2011 flags.reserved = (temp >> 28) & 0xf;
2012 flags.is_leading = (temp >> 26) & 0x3;
2013 flags.sample_depends_on = (temp >> 24) & 0x3;
2014 flags.sample_is_depended_on = (temp >> 22) & 0x3;
2015 flags.sample_has_redundancy = (temp >> 20) & 0x3;
2016 flags.sample_padding_value = (temp >> 17) & 0x7;
2017 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
2018 flags.sample_degradation_priority = temp & 0xffff;
2019 return flags;
2022 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2024 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
2025 return isom_read_unknown_box( file, box, parent, level );
2026 ADD_BOX( trex, isom_mvex_t );
2027 box->parent = parent;
2028 lsmash_bs_t *bs = file->bs;
2029 trex->track_ID = lsmash_bs_get_be32( bs );
2030 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
2031 trex->default_sample_duration = lsmash_bs_get_be32( bs );
2032 trex->default_sample_size = lsmash_bs_get_be32( bs );
2033 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
2034 return isom_read_leaf_box_common_last_process( file, box, level, trex );
2037 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2039 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2040 return isom_read_unknown_box( file, box, parent, level );
2041 ADD_BOX( moof, lsmash_file_t );
2042 box->parent = parent;
2043 isom_box_common_copy( moof, box );
2044 int ret = isom_add_print_func( file, moof, level );
2045 if( ret < 0 )
2046 return ret;
2047 return isom_read_children( file, box, moof, level );
2050 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2052 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF )
2053 || LSMASH_IS_EXISTING_BOX( ((isom_moof_t *)parent)->mfhd ) )
2054 return isom_read_unknown_box( file, box, parent, level );
2055 ADD_BOX( mfhd, isom_moof_t );
2056 lsmash_bs_t *bs = file->bs;
2057 mfhd->sequence_number = lsmash_bs_get_be32( bs );
2058 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
2061 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2063 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
2064 return isom_read_unknown_box( file, box, parent, level );
2065 ADD_BOX( traf, isom_moof_t );
2066 box->parent = parent;
2067 isom_box_common_copy( traf, box );
2068 int ret = isom_add_print_func( file, traf, level );
2069 if( ret < 0 )
2070 return ret;
2071 return isom_read_children( file, box, traf, level );
2074 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2076 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF )
2077 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->tfhd ) )
2078 return isom_read_unknown_box( file, box, parent, level );
2079 ADD_BOX( tfhd, isom_traf_t );
2080 lsmash_bs_t *bs = file->bs;
2081 tfhd->track_ID = lsmash_bs_get_be32( bs );
2082 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2083 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2084 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2085 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2086 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2087 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2090 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2092 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF )
2093 || LSMASH_IS_EXISTING_BOX( ((isom_traf_t *)parent)->tfdt ) )
2094 return isom_read_unknown_box( file, box, parent, level );
2095 ADD_BOX( tfdt, isom_traf_t );
2096 lsmash_bs_t *bs = file->bs;
2097 if( box->version == 1 )
2098 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2099 else
2100 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2101 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2104 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2106 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2107 return isom_read_unknown_box( file, box, parent, level );
2108 ADD_BOX( trun, isom_traf_t );
2109 box->parent = parent;
2110 lsmash_bs_t *bs = file->bs;
2111 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2112 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2113 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2114 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2115 has_optional_rows &= box->flags;
2116 trun->sample_count = lsmash_bs_get_be32( bs );
2117 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2118 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2119 if( trun->sample_count && has_optional_rows )
2121 trun->optional = lsmash_list_create_simple();
2122 if( !trun->optional )
2123 return LSMASH_ERR_MEMORY_ALLOC;
2124 for( uint32_t i = 0; i < trun->sample_count; i++ )
2126 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2127 if( !data )
2128 return LSMASH_ERR_MEMORY_ALLOC;
2129 if( lsmash_list_add_entry( trun->optional, data ) < 0 )
2131 lsmash_free( data );
2132 return LSMASH_ERR_MEMORY_ALLOC;
2134 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2135 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2136 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2137 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2140 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2143 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2145 if( file->fake_file_mode )
2146 return isom_read_unknown_box( file, box, parent, level );
2147 isom_skip_t *skip = ALLOCATE_BOX( skip );
2148 if( LSMASH_IS_NON_EXISTING_BOX( skip ) )
2149 return LSMASH_ERR_MEMORY_ALLOC;
2150 isom_skip_box_rest( file->bs, box );
2151 box->manager |= LSMASH_ABSENT_IN_FILE;
2152 isom_box_common_copy( skip, box );
2153 int ret = isom_add_print_func( file, skip, level );
2154 if( ret < 0 )
2156 isom_remove_box_by_itself( skip );
2157 return ret;
2159 return 0;
2162 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2164 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2165 return isom_read_unknown_box( file, box, parent, level );
2166 isom_mdat_t *mdat = ALLOCATE_BOX( mdat );
2167 if( LSMASH_IS_NON_EXISTING_BOX( mdat ) )
2168 return LSMASH_ERR_MEMORY_ALLOC;
2169 isom_skip_box_rest( file->bs, box );
2170 box->manager |= LSMASH_ABSENT_IN_FILE;
2171 file->flags |= LSMASH_FILE_MODE_MEDIA;
2172 isom_box_common_copy( mdat, box );
2173 int ret = isom_add_print_func( file, mdat, level );
2174 if( ret < 0 )
2176 isom_remove_box_by_itself( mdat );
2177 return ret;
2179 return 0;
2182 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2184 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2185 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2186 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2187 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2188 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->meta ))
2189 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && LSMASH_IS_EXISTING_BOX( ((isom_moov_t *)parent)->meta ))
2190 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && LSMASH_IS_EXISTING_BOX( ((isom_trak_t *)parent)->meta ))
2191 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->meta )) )
2192 return isom_read_unknown_box( file, box, parent, level );
2193 ADD_BOX( meta, void );
2194 isom_box_common_copy( meta, box );
2195 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2196 if( is_qtff )
2198 box->manager |= LSMASH_QTFF_BASE;
2199 meta->manager |= LSMASH_QTFF_BASE;
2201 int ret = isom_add_print_func( file, meta, level );
2202 if( ret < 0 )
2203 return ret;
2204 return isom_read_children( file, box, meta, level );
2207 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2209 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2210 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->keys ) )
2211 return isom_read_unknown_box( file, box, parent, level );
2212 ADD_BOX( keys, isom_meta_t );
2213 lsmash_bs_t *bs = file->bs;
2214 uint32_t entry_count = lsmash_bs_get_be32( bs );
2215 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2217 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2218 if( !data )
2219 return LSMASH_ERR_MEMORY_ALLOC;
2220 if( lsmash_list_add_entry( keys->list, data ) < 0 )
2222 lsmash_free( data );
2223 return LSMASH_ERR_MEMORY_ALLOC;
2225 data->key_size = lsmash_bs_get_be32( bs );
2226 data->key_namespace = lsmash_bs_get_be32( bs );
2227 if( data->key_size > 8 )
2229 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2230 if( !data->key_value )
2231 return LSMASH_ERR_NAMELESS;
2233 else
2234 data->key_value = NULL;
2236 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2239 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2241 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2242 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2243 || LSMASH_IS_EXISTING_BOX( ((isom_meta_t *)parent)->ilst ) )
2244 return isom_read_unknown_box( file, box, parent, level );
2245 ADD_BOX( ilst, isom_meta_t );
2246 isom_box_common_copy( ilst, box );
2247 int ret = isom_add_print_func( file, ilst, level );
2248 if( ret < 0 )
2249 return ret;
2250 return isom_read_children( file, box, ilst, level );
2253 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2255 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2256 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2257 return isom_read_unknown_box( file, box, parent, level );
2258 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2259 if( !metaitem )
2260 return -1;
2261 box->parent = parent;
2262 isom_box_common_copy( metaitem, box );
2263 int ret = isom_add_print_func( file, metaitem, level );
2264 if( ret < 0 )
2265 return ret;
2266 return isom_read_children( file, box, metaitem, level );
2269 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2271 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM
2272 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->mean ) )
2273 return isom_read_unknown_box( file, box, parent, level );
2274 ADD_BOX( mean, isom_metaitem_t );
2275 lsmash_bs_t *bs = file->bs;
2276 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2277 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2278 if( !mean->meaning_string )
2279 return LSMASH_ERR_NAMELESS;
2280 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2283 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2285 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM
2286 || LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->name ) )
2287 return isom_read_unknown_box( file, box, parent, level );
2288 ADD_BOX( name, isom_metaitem_t );
2289 lsmash_bs_t *bs = file->bs;
2290 name->name_length = box->size - lsmash_bs_count( bs );
2291 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2292 if( !name->name )
2293 return LSMASH_ERR_NAMELESS;
2294 return isom_read_leaf_box_common_last_process( file, box, level, name );
2297 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2299 if( LSMASH_IS_EXISTING_BOX( ((isom_metaitem_t *)parent)->data ) )
2300 return isom_read_unknown_box( file, box, parent, level );
2301 ADD_BOX( data, isom_metaitem_t );
2302 lsmash_bs_t *bs = file->bs;
2303 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2304 data->reserved = lsmash_bs_get_be16( bs );
2305 data->type_set_identifier = lsmash_bs_get_byte( bs );
2306 data->type_code = lsmash_bs_get_byte( bs );
2307 data->the_locale = lsmash_bs_get_be32( bs );
2308 if( data->value_length )
2310 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2311 if( !data->value )
2312 return LSMASH_ERR_NAMELESS;
2314 return isom_read_leaf_box_common_last_process( file, box, level, data );
2317 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2319 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2320 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->WLOC ) )
2321 return isom_read_unknown_box( file, box, parent, level );
2322 ADD_BOX( WLOC, isom_udta_t );
2323 lsmash_bs_t *bs = file->bs;
2324 WLOC->x = lsmash_bs_get_be16( bs );
2325 WLOC->y = lsmash_bs_get_be16( bs );
2326 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2329 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2331 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2332 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->LOOP ) )
2333 return isom_read_unknown_box( file, box, parent, level );
2334 ADD_BOX( LOOP, isom_udta_t );
2335 lsmash_bs_t *bs = file->bs;
2336 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2337 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2340 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2342 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2343 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->SelO ) )
2344 return isom_read_unknown_box( file, box, parent, level );
2345 ADD_BOX( SelO, isom_udta_t );
2346 lsmash_bs_t *bs = file->bs;
2347 SelO->selection_only = lsmash_bs_get_byte( bs );
2348 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2351 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2353 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA )
2354 || LSMASH_IS_EXISTING_BOX( ((isom_udta_t *)parent)->AllF ) )
2355 return isom_read_unknown_box( file, box, parent, level );
2356 ADD_BOX( AllF, isom_udta_t );
2357 lsmash_bs_t *bs = file->bs;
2358 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2359 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2362 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2364 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2365 return isom_read_unknown_box( file, box, parent, level );
2366 ADD_BOX( cprt, isom_udta_t );
2367 box->parent = parent;
2368 lsmash_bs_t *bs = file->bs;
2369 cprt->language = lsmash_bs_get_be16( bs );
2370 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2371 if( cprt->notice_length )
2373 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2374 if( !cprt->notice )
2376 cprt->notice_length = 0;
2377 return LSMASH_ERR_NAMELESS;
2380 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2383 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2385 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2386 || LSMASH_IS_EXISTING_BOX( ((lsmash_file_t *)parent)->mfra ) )
2387 return isom_read_unknown_box( file, box, parent, level );
2388 ADD_BOX( mfra, lsmash_file_t );
2389 isom_box_common_copy( mfra, box );
2390 int ret = isom_add_print_func( file, mfra, level );
2391 if( ret < 0 )
2392 return ret;
2393 return isom_read_children( file, box, mfra, level );
2396 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2398 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2399 return isom_read_unknown_box( file, box, parent, level );
2400 ADD_BOX( tfra, isom_mfra_t );
2401 box->parent = parent;
2402 lsmash_bs_t *bs = file->bs;
2403 tfra->track_ID = lsmash_bs_get_be32( bs );
2404 uint32_t temp = lsmash_bs_get_be32( bs );
2405 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2406 tfra->reserved = (temp >> 6) & 0x3ffffff;
2407 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2408 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2409 tfra->length_size_of_sample_num = temp & 0x3;
2410 if( tfra->number_of_entry )
2412 tfra->list = lsmash_list_create_simple();
2413 if( !tfra->list )
2414 return LSMASH_ERR_MEMORY_ALLOC;
2415 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2417 lsmash_bs_get_byte_to_64,
2418 lsmash_bs_get_be16_to_64,
2419 lsmash_bs_get_be24_to_64,
2420 lsmash_bs_get_be32_to_64,
2421 lsmash_bs_get_be64
2423 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2424 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2425 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2426 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2427 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2428 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2430 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2431 if( !data )
2432 return LSMASH_ERR_MEMORY_ALLOC;
2433 if( lsmash_list_add_entry( tfra->list, data ) < 0 )
2435 lsmash_free( data );
2436 return LSMASH_ERR_MEMORY_ALLOC;
2438 data->time = bs_put_time ( bs );
2439 data->moof_offset = bs_put_moof_offset ( bs );
2440 data->traf_number = bs_put_traf_number ( bs );
2441 data->trun_number = bs_put_trun_number ( bs );
2442 data->sample_number = bs_put_sample_number( bs );
2445 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2448 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2450 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA )
2451 || LSMASH_IS_EXISTING_BOX( ((isom_mfra_t *)parent)->mfro ) )
2452 return isom_read_unknown_box( file, box, parent, level );
2453 ADD_BOX( mfro, isom_mfra_t );
2454 lsmash_bs_t *bs = file->bs;
2455 mfro->length = lsmash_bs_get_be32( bs );
2456 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2459 static void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2461 if( !bs->unseekable )
2463 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2464 while( size > (INT64_MAX >> 1) )
2466 lsmash_bs_read_seek( bs, INT64_MAX >> 1, SEEK_CUR );
2467 if( lsmash_bs_is_end( bs, 0 ) )
2468 return;
2469 size -= (INT64_MAX >> 1);
2471 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2473 else
2474 lsmash_bs_skip_bytes_64( bs, size );
2477 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2479 lsmash_bs_t *bs = file->bs;
2480 /* Skip extra bytes of the parent box if any. */
2481 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2483 uint64_t extra_bytes = parent->size - parent_pos;
2484 isom_read_skip_extra_bytes( bs, extra_bytes );
2485 /* This is not the size of a box but makes sense in isom_read_children(). */
2486 box->size = extra_bytes;
2487 return 1;
2489 /* Check if the size is valid or not. */
2490 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2492 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2493 if( size > 1
2494 && size < ISOM_BASEBOX_COMMON_SIZE )
2496 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2497 * Skip bytes up to the next box of the parent box. */
2498 uint64_t extra_bytes = parent->size - parent_pos;
2499 isom_read_skip_extra_bytes( bs, extra_bytes );
2500 box->size = extra_bytes;
2501 return 1;
2503 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2504 size = lsmash_bs_show_be64( bs, 8 ); /* large size */
2505 if( size == 0 && parent != (isom_box_t *)file )
2507 /* Check if this box is actually the last box or not. */
2508 uint64_t extra_bytes = parent->size - parent_pos;
2509 if( !bs->unseekable )
2510 size = bs->written - lsmash_bs_get_stream_pos( bs );
2511 else
2513 size = lsmash_bs_get_remaining_buffer_size( bs );
2514 while( size <= extra_bytes )
2516 int ret = lsmash_bs_read( bs, 1 );
2517 if( bs->eof || ret < 0 )
2518 break;
2519 size = lsmash_bs_get_remaining_buffer_size( bs );
2522 if( size != extra_bytes )
2524 /* This is not the size of the last box.
2525 * It seems we are still within the box considered as the previous or the parent box.
2526 * Skip bytes up to the next box. */
2527 if( box->size > lsmash_bs_count( bs ) )
2529 /* within the previous */
2530 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2531 box->size = 0; /* already added to the size of the parent box */
2533 else
2535 /* within the parent */
2536 isom_read_skip_extra_bytes( bs, extra_bytes );
2537 box->size = extra_bytes;
2539 return 1;
2543 return 0;
2546 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2548 assert( parent && parent->root && parent->file );
2549 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2550 return 0;
2551 memset( box, 0, sizeof(isom_box_t) );
2552 box->root = parent->root;
2553 box->file = parent->file;
2554 box->parent = parent;
2555 lsmash_bs_t *bs = file->bs;
2556 int ret = isom_bs_read_box_common( bs, box );
2557 if( !!ret )
2558 return ret; /* return if reached EOF */
2559 ++level;
2560 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2561 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2562 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2564 /* OK, this box is a sample entry.
2565 * Here, determine the suitable sample entry reader by media type if possible. */
2566 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
2567 goto read_box;
2568 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
2569 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2570 reader_func = isom_read_visual_description;
2571 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2572 reader_func = isom_read_audio_description;
2573 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2574 reader_func = isom_read_text_description;
2575 else
2576 reader_func = isom_read_other_description;
2577 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2578 static struct description_reader_table_tag
2580 lsmash_compact_box_type_t fourcc;
2581 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2582 } description_reader_table[160] = { { 0, NULL } };
2583 if( !description_reader_table[0].form_box_type_func )
2585 /* Initialize the table. */
2586 int i = 0;
2587 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2588 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO, lsmash_form_qtff_box_type );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type );
2630 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type );
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type );
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type );
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type );
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type );
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type );
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type );
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type );
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type );
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type );
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type );
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type );
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type );
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type );
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type );
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type );
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type );
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type );
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type );
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type );
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO, lsmash_form_qtff_box_type );
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type );
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type );
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type );
2664 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type );
2665 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type );
2666 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type );
2667 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type );
2668 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type );
2669 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type );
2670 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSEL_AUDIO, lsmash_form_iso_box_type );
2671 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSDL_AUDIO, lsmash_form_iso_box_type );
2672 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type );
2673 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type );
2674 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type );
2675 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type );
2676 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSX_AUDIO, lsmash_form_iso_box_type );
2677 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type );
2678 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type );
2679 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type );
2680 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type );
2681 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type );
2682 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type );
2683 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type );
2684 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type );
2685 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type );
2686 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type );
2687 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type );
2688 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type );
2689 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type );
2690 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2691 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type );
2692 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type );
2693 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type );
2694 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type );
2695 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type );
2696 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type );
2697 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type );
2698 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type );
2699 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type );
2700 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type );
2701 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type );
2702 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type );
2703 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type );
2704 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type );
2705 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type );
2706 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type );
2707 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type );
2708 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type );
2709 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type );
2710 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type );
2711 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type );
2712 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type );
2713 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type );
2714 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type );
2715 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type );
2716 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type );
2717 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type );
2718 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type );
2719 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type );
2720 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type );
2721 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type );
2722 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type );
2723 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type );
2724 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW, lsmash_form_qtff_box_type );
2725 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL );
2726 assert( sizeof(description_reader_table) >= (size_t)i * sizeof(description_reader_table[0]) );
2727 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2729 for( int i = 0; description_reader_table[i].form_box_type_func; i++ )
2730 if( box->type.fourcc == description_reader_table[i].fourcc )
2732 form_box_type_func = description_reader_table[i].form_box_type_func;
2733 goto read_box;
2735 goto read_box;
2737 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2739 form_box_type_func = lsmash_form_qtff_box_type;
2740 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2741 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2742 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2743 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2744 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2745 else reader_func = isom_read_codec_specific;
2746 goto read_box;
2748 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2750 form_box_type_func = lsmash_form_iso_box_type;
2751 reader_func = isom_read_track_reference_type;
2752 goto read_box;
2754 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2756 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2757 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2758 form_box_type_func = lsmash_form_iso_box_type;
2759 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2760 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2761 form_box_type_func = lsmash_form_qtff_box_type;
2762 reader_func = isom_read_dref_entry;
2763 goto read_box;
2765 static struct box_reader_table_tag
2767 lsmash_compact_box_type_t fourcc;
2768 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2769 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2770 } box_reader_table[128] = { { 0, NULL, NULL } };
2771 if( !box_reader_table[0].reader_func )
2773 /* Initialize the table. */
2774 int i = 0;
2775 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2776 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2777 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2778 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2779 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2780 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2781 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2783 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2786 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2787 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2788 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2789 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2792 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2794 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2796 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2797 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2798 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2799 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2800 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2801 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2802 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2803 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2804 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2805 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2806 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2807 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2808 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2809 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2810 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2811 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2812 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2813 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2814 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2815 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2816 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, lsmash_form_iso_box_type, isom_read_stz2 );
2817 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2818 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2819 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2820 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2821 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2822 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2823 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2824 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2825 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2826 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2827 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2828 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2829 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2830 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2831 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2832 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2833 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2834 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2835 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2836 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2837 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2838 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2839 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2840 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2841 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2842 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2843 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2844 assert( sizeof(box_reader_table) >= (size_t)i * sizeof(box_reader_table[0]) );
2845 #undef ADD_BOX_READER_TABLE_ELEMENT
2847 for( int i = 0; box_reader_table[i].reader_func; i++ )
2848 if( box->type.fourcc == box_reader_table[i].fourcc )
2850 form_box_type_func = box_reader_table[i].form_box_type_func;
2851 reader_func = box_reader_table[i].reader_func;
2852 goto read_box;
2854 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2856 if( lsmash_bs_is_end ( bs, 3 ) == 0
2857 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2858 form_box_type_func = lsmash_form_iso_box_type;
2859 else
2860 form_box_type_func = lsmash_form_qtff_box_type;
2861 reader_func = isom_read_meta;
2862 goto read_box;
2864 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2866 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2867 form_box_type_func = lsmash_form_iso_box_type;
2868 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2869 form_box_type_func = lsmash_form_qtff_box_type;
2870 if( form_box_type_func )
2872 reader_func = isom_read_ilst;
2873 goto read_box;
2876 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2877 form_box_type_func = lsmash_form_iso_box_type;
2878 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2879 form_box_type_func = lsmash_form_qtff_box_type;
2880 if( form_box_type_func )
2882 reader_func = isom_read_metaitem;
2883 goto read_box;
2885 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2887 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2888 reader_func = isom_read_mean;
2889 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2890 reader_func = isom_read_name;
2891 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2892 reader_func = isom_read_data;
2893 if( reader_func )
2895 form_box_type_func = lsmash_form_iso_box_type;
2896 goto read_box;
2899 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2901 /* Avoid confusing udta.cprt with ilst.cprt. */
2902 form_box_type_func = lsmash_form_iso_box_type;
2903 reader_func = isom_read_cprt;
2904 goto read_box;
2906 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2908 static struct sample_description_extension_reader_table_tag
2910 lsmash_compact_box_type_t fourcc;
2911 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2912 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2913 } extension_reader_table[32] = { { 0, NULL, NULL } };
2914 if( !extension_reader_table[0].reader_func )
2916 /* Initialize the table. */
2917 int i = 0;
2918 #define ADD_EXTENSION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2919 extension_reader_table[i++] = (struct sample_description_extension_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2920 /* Audio */
2921 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type, isom_read_codec_specific );
2922 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type, isom_read_codec_specific );
2923 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type, isom_read_codec_specific );
2924 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type, isom_read_codec_specific );
2925 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type, isom_read_codec_specific );
2926 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2927 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type, isom_read_codec_specific );
2928 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2929 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2930 /* Video */
2931 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type, isom_read_codec_specific );
2932 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2933 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2934 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2935 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type, isom_read_codec_specific );
2936 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type, isom_read_codec_specific );
2937 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2938 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2939 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLLI, lsmash_form_qtff_box_type, isom_read_clli );
2940 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2941 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_MDCV, lsmash_form_qtff_box_type, isom_read_mdcv );
2942 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2943 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2944 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2945 ADD_EXTENSION_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2946 /* Others */
2947 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2948 ADD_EXTENSION_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2949 ADD_EXTENSION_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2950 assert( sizeof(extension_reader_table) >= (size_t)i * sizeof(extension_reader_table[0]) );
2951 #undef ADD_EXTENSION_READER_TABLE_ELEMENT
2953 for( int i = 0; extension_reader_table[i].reader_func; i++ )
2954 if( box->type.fourcc == extension_reader_table[i].fourcc )
2956 form_box_type_func = extension_reader_table[i].form_box_type_func;
2957 reader_func = extension_reader_table[i].reader_func;
2958 goto read_box;
2960 reader_func = isom_read_codec_specific;
2962 read_box:
2963 if( form_box_type_func )
2964 box->type = form_box_type_func( box->type.fourcc );
2965 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2966 return ret;
2967 return reader_func
2968 ? reader_func( file, box, parent, level )
2969 : isom_read_unknown_box( file, box, parent, level );
2972 int isom_read_file( lsmash_file_t *file )
2974 lsmash_bs_t *bs = file->bs;
2975 if( !bs )
2976 return LSMASH_ERR_NAMELESS;
2977 /* Reset the counter so that we can use it to get position within the box. */
2978 lsmash_bs_reset_counter( bs );
2979 if( file->flags & LSMASH_FILE_MODE_DUMP )
2981 file->print = isom_printer_create_list();
2982 if( !file->print )
2983 return LSMASH_ERR_MEMORY_ALLOC;
2985 file->size = UINT64_MAX;
2986 isom_box_t box;
2987 int ret = isom_read_children( file, &box, file, 0 );
2988 file->size = box.size;
2989 lsmash_bs_empty( bs );
2990 bs->error = 0; /* Clear error flag. */
2991 if( ret < 0 )
2992 return ret;
2993 return isom_check_compatibility( file );