MSVC: add missing source files.
[L-SMASH.git] / core / read.c
blob85d7c479f8e976d1e21df4ed49e6187c148d52a1
1 /*****************************************************************************
2 * read.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2015 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "box.h"
30 #include "file.h"
31 #include "print.h"
32 #include "read.h"
33 #include "write.h"
35 #include "codecs/mp4a.h"
36 #include "codecs/mp4sys.h"
37 #include "codecs/description.h"
39 static int isom_bs_read_box_common( lsmash_bs_t *bs, isom_box_t *box )
41 assert( bs && box && box->file );
42 /* Reset the counter so that we can use it to get position within the box. */
43 lsmash_bs_reset_counter( bs );
44 /* Read the common fields of box. */
45 box->pos = lsmash_bs_get_stream_pos( bs );
46 if( bs->eob )
47 /* No more read. */
48 return 1;
49 /* Read size and type. */
50 box->size = lsmash_bs_get_be32( bs );
51 box->type.fourcc = lsmash_bs_get_be32( bs );
52 /* If size is set to 1, the actual size is repersented in the next 8 bytes.
53 * If size is set to 0, this box ends at the end of the stream. */
54 if( box->size == 1 )
55 box->size = lsmash_bs_get_be64( bs );
56 if( box->size == 0 )
58 /* This box is the last box in the stream. */
59 box->manager |= LSMASH_LAST_BOX;
60 if( !bs->unseekable )
61 box->size = bs->written - (lsmash_bs_get_stream_pos( bs ) - lsmash_bs_count( bs ));
62 else
63 /* We haven't known the box size yet.
64 * To get the box size, read the stream until the end of the stream. */
65 while( 1 )
67 int ret = lsmash_bs_read( bs, 1 );
68 if( bs->eof || ret < 0 )
70 /* OK, now we know the box size. */
71 box->size = lsmash_bs_count( bs ) + lsmash_bs_get_remaining_buffer_size( bs );
72 if( ret < 0 )
73 /* This box may end incompletely at the end of the stream. */
74 box->manager |= LSMASH_INCOMPLETE_BOX;
75 break;
79 /* Here, we don't set up extended box type fields if this box is not a UUID Box. */
80 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc
81 && box->size >= lsmash_bs_count( bs ) + 16 )
83 /* Get UUID. */
84 lsmash_box_type_t *type = &box->type;
85 uint64_t temp64 = lsmash_bs_get_be64( bs );
86 type->user.fourcc = (temp64 >> 32) & 0xffffffff;
87 LSMASH_SET_BE32( &type->user.id[0], temp64 );
88 temp64 = lsmash_bs_get_be64( bs );
89 LSMASH_SET_BE64( &type->user.id[4], temp64 );
91 return bs->eob;
94 static int isom_read_fullbox_common_extension( lsmash_bs_t *bs, isom_box_t *box )
96 if( !isom_is_fullbox( box ) )
97 return 0;
98 /* Get version and flags. */
99 box->version = lsmash_bs_get_byte( bs );
100 box->flags = lsmash_bs_get_be24( bs );
101 box->manager |= LSMASH_FULLBOX;
102 return 0;
105 /* Don't copy destructor since a destructor is defined as box specific. */
106 static void isom_basebox_common_copy( isom_box_t *dst, isom_box_t *src )
108 dst->root = src->root;
109 dst->file = src->file;
110 dst->parent = src->parent;
111 dst->manager = src->manager;
112 dst->pos = src->pos;
113 dst->size = src->size;
114 dst->type = src->type;
117 static void isom_fullbox_common_copy( isom_box_t *dst, isom_box_t *src )
119 dst->root = src->root;
120 dst->file = src->file;
121 dst->parent = src->parent;
122 dst->manager = src->manager;
123 dst->pos = src->pos;
124 dst->size = src->size;
125 dst->type = src->type;
126 dst->version = src->version;
127 dst->flags = src->flags;
130 static void isom_box_common_copy( void *dst, void *src )
132 if( src && lsmash_check_box_type_identical( ((isom_box_t *)src)->type, ISOM_BOX_TYPE_STSD ) )
134 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
135 return;
137 if( isom_is_fullbox( src ) )
138 isom_fullbox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
139 else
140 isom_basebox_common_copy( (isom_box_t *)dst, (isom_box_t *)src );
143 static void isom_skip_box_rest( lsmash_bs_t *bs, isom_box_t *box )
145 if( box->manager & LSMASH_LAST_BOX )
147 box->size = (box->manager & LSMASH_FULLBOX) ? ISOM_FULLBOX_COMMON_SIZE : ISOM_BASEBOX_COMMON_SIZE;
148 uint64_t start = lsmash_bs_get_stream_pos( bs );
149 if( !bs->unseekable )
150 lsmash_bs_read_seek( bs, 0, SEEK_END );
151 else
152 while( !bs->eob )
153 lsmash_bs_skip_bytes( bs, UINT32_MAX );
154 uint64_t end = lsmash_bs_get_stream_pos( bs );
155 box->size += end - start;
156 return;
158 uint64_t skip_bytes = box->size - lsmash_bs_count( bs );
159 if( !bs->unseekable )
161 /* The stream is seekable. So, skip by seeking the stream. */
162 uint64_t start = lsmash_bs_get_stream_pos( bs );
163 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
164 uint64_t end = lsmash_bs_get_stream_pos( bs );
165 if( end - start != skip_bytes )
166 /* not match size */
167 box->manager |= LSMASH_INCOMPLETE_BOX;
168 return;
170 /* The stream is unseekable. So, skip by reading the stream. */
171 lsmash_bs_skip_bytes_64( bs, skip_bytes );
172 if( box->size > lsmash_bs_count( bs ) )
173 box->manager |= LSMASH_INCOMPLETE_BOX;
176 static void isom_check_box_size( lsmash_bs_t *bs, isom_box_t *box )
178 uint64_t pos = lsmash_bs_count( bs );
179 if( box->manager & LSMASH_LAST_BOX )
181 box->size = pos;
182 return;
184 if( box->size < pos )
186 printf( "[%s] box has more bytes: %"PRId64"\n", isom_4cc2str( box->type.fourcc ), pos - box->size );
187 box->size = pos;
191 static int isom_read_children( lsmash_file_t *file, isom_box_t *box, void *parent, int level )
193 int ret;
194 lsmash_bs_t *bs = file->bs;
195 isom_box_t *parent_box = (isom_box_t *)parent;
196 uint64_t parent_pos = lsmash_bs_count( bs );
197 while( !(ret = isom_read_box( file, box, parent_box, parent_pos, level )) )
199 parent_pos += box->size;
200 if( parent_box->size <= parent_pos || bs->eob || bs->error )
201 break;
203 box->size = parent_pos; /* for file size */
204 return ret;
207 static int isom_read_leaf_box_common_last_process( lsmash_file_t *file, isom_box_t *box, int level, void *instance )
209 isom_check_box_size( file->bs, box );
210 isom_box_common_copy( instance, box );
211 return isom_add_print_func( file, instance, level );
214 static int isom_read_unknown_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
216 lsmash_bs_t *bs = file->bs;
217 uint64_t read_size = box->size - lsmash_bs_count( bs );
218 if( box->manager & LSMASH_INCOMPLETE_BOX )
219 return LSMASH_ERR_INVALID_DATA;
220 isom_unknown_box_t *unknown = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
221 if( !unknown )
222 return LSMASH_ERR_MEMORY_ALLOC;
223 if( lsmash_add_entry( &parent->extensions, unknown ) < 0 )
225 lsmash_free( unknown );
226 return LSMASH_ERR_MEMORY_ALLOC;
228 isom_box_common_copy( unknown, box );
229 unknown->manager |= LSMASH_UNKNOWN_BOX;
230 unknown->destruct = (isom_extension_destructor_t)isom_remove_unknown_box;
231 isom_set_box_writer( (isom_box_t *)unknown );
232 if( read_size )
234 unknown->unknown_field = lsmash_bs_get_bytes( bs, read_size );
235 if( unknown->unknown_field )
236 unknown->unknown_size = read_size;
237 else
238 unknown->manager |= LSMASH_INCOMPLETE_BOX;
240 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
241 return 0;
242 /* Create a dummy for dump. */
243 isom_box_t *dummy = lsmash_malloc_zero( sizeof(isom_box_t) );
244 if( !dummy )
245 return LSMASH_ERR_MEMORY_ALLOC;
246 box->manager |= LSMASH_ABSENT_IN_FILE;
247 isom_box_common_copy( dummy, box );
248 int ret = isom_add_print_func( file, dummy, level );
249 if( ret < 0 )
251 lsmash_free( dummy );
252 return ret;
254 return 0;
257 #define ADD_BOX( box_name, parent_type ) \
258 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
259 if( !box_name ) \
260 return LSMASH_ERR_NAMELESS
262 static int isom_read_ftyp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
264 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->ftyp )
265 return isom_read_unknown_box( file, box, parent, level );
266 ADD_BOX( ftyp, lsmash_file_t );
267 lsmash_bs_t *bs = file->bs;
268 ftyp->major_brand = lsmash_bs_get_be32( bs );
269 ftyp->minor_version = lsmash_bs_get_be32( bs );
270 uint64_t pos = lsmash_bs_count( bs );
271 ftyp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
272 size_t alloc_size = ftyp->brand_count * sizeof(uint32_t);
273 ftyp->compatible_brands = ftyp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
274 if( ftyp->brand_count && !ftyp->compatible_brands )
275 return LSMASH_ERR_MEMORY_ALLOC;
276 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
277 ftyp->compatible_brands[i] = lsmash_bs_get_be32( bs );
278 if( !file->compatible_brands && ftyp->compatible_brands )
280 file->compatible_brands = lsmash_memdup( ftyp->compatible_brands, alloc_size );
281 if( !file->compatible_brands )
282 return LSMASH_ERR_MEMORY_ALLOC;
283 file->brand_count = ftyp->brand_count;
285 return isom_read_leaf_box_common_last_process( file, box, level, ftyp );
288 static int isom_read_styp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
290 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
291 return isom_read_unknown_box( file, box, parent, level );
292 ADD_BOX( styp, lsmash_file_t );
293 lsmash_bs_t *bs = file->bs;
294 styp->major_brand = lsmash_bs_get_be32( bs );
295 styp->minor_version = lsmash_bs_get_be32( bs );
296 uint64_t pos = lsmash_bs_count( bs );
297 styp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
298 size_t alloc_size = styp->brand_count * sizeof(uint32_t);
299 styp->compatible_brands = styp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
300 if( styp->brand_count && !styp->compatible_brands )
301 return LSMASH_ERR_MEMORY_ALLOC;
302 for( uint32_t i = 0; i < styp->brand_count; i++ )
303 styp->compatible_brands[i] = lsmash_bs_get_be32( bs );
304 if( !file->compatible_brands && styp->compatible_brands )
306 file->compatible_brands = lsmash_memdup( styp->compatible_brands, alloc_size );
307 if( !file->compatible_brands )
308 return LSMASH_ERR_MEMORY_ALLOC;
309 file->brand_count = styp->brand_count;
311 file->flags |= LSMASH_FILE_MODE_SEGMENT;
312 return isom_read_leaf_box_common_last_process( file, box, level, styp );
315 static int isom_read_sidx( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
317 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
318 return isom_read_unknown_box( file, box, parent, level );
319 ADD_BOX( sidx, lsmash_file_t );
320 lsmash_bs_t *bs = file->bs;
321 sidx->reference_ID = lsmash_bs_get_be32( bs );
322 sidx->timescale = lsmash_bs_get_be32( bs );
323 if( box->version == 0 )
325 sidx->earliest_presentation_time = lsmash_bs_get_be32( bs );
326 sidx->first_offset = lsmash_bs_get_be32( bs );
328 else
330 sidx->earliest_presentation_time = lsmash_bs_get_be64( bs );
331 sidx->first_offset = lsmash_bs_get_be64( bs );
333 sidx->reserved = lsmash_bs_get_be16( bs );
334 sidx->reference_count = lsmash_bs_get_be16( bs );
335 for( uint64_t pos = lsmash_bs_count( bs );
336 pos < box->size && sidx->list->entry_count < sidx->reference_count;
337 pos = lsmash_bs_count( bs ) )
339 isom_sidx_referenced_item_t *data = lsmash_malloc( sizeof(isom_sidx_referenced_item_t) );
340 if( !data )
341 return LSMASH_ERR_MEMORY_ALLOC;
342 if( lsmash_add_entry( sidx->list, data ) < 0 )
344 lsmash_free( data );
345 return LSMASH_ERR_MEMORY_ALLOC;
347 uint32_t temp32;
348 temp32 = lsmash_bs_get_be32( bs );
349 data->reference_type = (temp32 >> 31) & 0x00000001;
350 data->reference_size = temp32 & 0x7FFFFFFF;
351 data->subsegment_duration = lsmash_bs_get_be32( bs );
352 temp32 = lsmash_bs_get_be32( bs );
353 data->starts_with_SAP = (temp32 >> 31) & 0x00000001;
354 data->SAP_type = (temp32 >> 28) & 0x00000007;
355 data->SAP_delta_time = temp32 & 0x0FFFFFFF;
357 file->flags |= LSMASH_FILE_MODE_INDEX;
358 return isom_read_leaf_box_common_last_process( file, box, level, sidx );
361 static int isom_read_moov( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
363 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->moov )
364 return isom_read_unknown_box( file, box, parent, level );
365 ADD_BOX( moov, lsmash_file_t );
366 file->flags |= LSMASH_FILE_MODE_INITIALIZATION;
367 file->initializer = file;
368 isom_box_common_copy( moov, box );
369 int ret = isom_add_print_func( file, moov, level );
370 if( ret < 0 )
371 return ret;
372 return isom_read_children( file, box, moov, level );
375 static int isom_read_mvhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
377 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvhd )
378 return isom_read_unknown_box( file, box, parent, level );
379 ADD_BOX( mvhd, isom_moov_t );
380 lsmash_bs_t *bs = file->bs;
381 if( box->version )
383 mvhd->creation_time = lsmash_bs_get_be64( bs );
384 mvhd->modification_time = lsmash_bs_get_be64( bs );
385 mvhd->timescale = lsmash_bs_get_be32( bs );
386 mvhd->duration = lsmash_bs_get_be64( bs );
388 else
390 mvhd->creation_time = lsmash_bs_get_be32( bs );
391 mvhd->modification_time = lsmash_bs_get_be32( bs );
392 mvhd->timescale = lsmash_bs_get_be32( bs );
393 mvhd->duration = lsmash_bs_get_be32( bs );
395 mvhd->rate = lsmash_bs_get_be32( bs );
396 mvhd->volume = lsmash_bs_get_be16( bs );
397 mvhd->reserved = lsmash_bs_get_be16( bs );
398 mvhd->preferredLong[0] = lsmash_bs_get_be32( bs );
399 mvhd->preferredLong[1] = lsmash_bs_get_be32( bs );
400 for( int i = 0; i < 9; i++ )
401 mvhd->matrix[i] = lsmash_bs_get_be32( bs );
402 mvhd->previewTime = lsmash_bs_get_be32( bs );
403 mvhd->previewDuration = lsmash_bs_get_be32( bs );
404 mvhd->posterTime = lsmash_bs_get_be32( bs );
405 mvhd->selectionTime = lsmash_bs_get_be32( bs );
406 mvhd->selectionDuration = lsmash_bs_get_be32( bs );
407 mvhd->currentTime = lsmash_bs_get_be32( bs );
408 mvhd->next_track_ID = lsmash_bs_get_be32( bs );
409 return isom_read_leaf_box_common_last_process( file, box, level, mvhd );
412 static int isom_read_iods( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
414 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
415 return isom_read_unknown_box( file, box, parent, level );
416 ADD_BOX( iods, isom_moov_t );
417 lsmash_bs_t *bs = file->bs;
418 iods->OD = mp4sys_get_descriptor( bs, NULL );
419 if( !iods->OD )
420 return LSMASH_ERR_INVALID_DATA;
421 isom_skip_box_rest( file->bs, box );
422 return isom_read_leaf_box_common_last_process( file, box, level, iods );
425 static int isom_read_qt_color_table( lsmash_bs_t *bs, isom_qt_color_table_t *color_table )
427 color_table->seed = lsmash_bs_get_be32( bs );
428 color_table->flags = lsmash_bs_get_be16( bs );
429 color_table->size = lsmash_bs_get_be16( bs );
430 if( bs->eob )
431 return LSMASH_ERR_INVALID_DATA;
432 isom_qt_color_array_t *array = lsmash_malloc_zero( (color_table->size + 1) * sizeof(isom_qt_color_array_t) );
433 if( !array )
434 return LSMASH_ERR_MEMORY_ALLOC;
435 color_table->array = array;
436 for( uint16_t i = 0; i <= color_table->size; i++ )
438 uint64_t color = lsmash_bs_get_be64( bs );
439 array[i].value = (color >> 48) & 0xffff;
440 array[i].r = (color >> 32) & 0xffff;
441 array[i].g = (color >> 16) & 0xffff;
442 array[i].b = color & 0xffff;
444 return 0;
447 static int isom_read_ctab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
449 ADD_BOX( ctab, isom_moov_t );
450 lsmash_bs_t *bs = file->bs;
451 int ret = isom_read_qt_color_table( bs, &ctab->color_table );
452 if( ret < 0 )
453 return ret;
454 return isom_read_leaf_box_common_last_process( file, box, level, ctab );
457 static int isom_read_trak( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
459 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
460 return isom_read_unknown_box( file, box, parent, level );
461 ADD_BOX( trak, isom_moov_t );
462 box->parent = parent;
463 box->root = file->root;
464 box->file = file;
465 isom_box_common_copy( trak, box );
466 int ret = isom_add_print_func( file, trak, level );
467 if( ret < 0 )
468 return ret;
469 return isom_read_children( file, box, trak, level );
472 static int isom_read_tkhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
474 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tkhd )
475 return isom_read_unknown_box( file, box, parent, level );
476 ADD_BOX( tkhd, isom_trak_t );
477 lsmash_bs_t *bs = file->bs;
478 if( box->version )
480 tkhd->creation_time = lsmash_bs_get_be64( bs );
481 tkhd->modification_time = lsmash_bs_get_be64( bs );
482 tkhd->track_ID = lsmash_bs_get_be32( bs );
483 tkhd->reserved1 = lsmash_bs_get_be32( bs );
484 tkhd->duration = lsmash_bs_get_be64( bs );
486 else
488 tkhd->creation_time = lsmash_bs_get_be32( bs );
489 tkhd->modification_time = lsmash_bs_get_be32( bs );
490 tkhd->track_ID = lsmash_bs_get_be32( bs );
491 tkhd->reserved1 = lsmash_bs_get_be32( bs );
492 tkhd->duration = lsmash_bs_get_be32( bs );
494 tkhd->reserved2[0] = lsmash_bs_get_be32( bs );
495 tkhd->reserved2[1] = lsmash_bs_get_be32( bs );
496 tkhd->layer = lsmash_bs_get_be16( bs );
497 tkhd->alternate_group = lsmash_bs_get_be16( bs );
498 tkhd->volume = lsmash_bs_get_be16( bs );
499 tkhd->reserved3 = lsmash_bs_get_be16( bs );
500 for( int i = 0; i < 9; i++ )
501 tkhd->matrix[i] = lsmash_bs_get_be32( bs );
502 tkhd->width = lsmash_bs_get_be32( bs );
503 tkhd->height = lsmash_bs_get_be32( bs );
504 return isom_read_leaf_box_common_last_process( file, box, level, tkhd );
507 static int isom_read_tapt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
509 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tapt )
510 return isom_read_unknown_box( file, box, parent, level );
511 ADD_BOX( tapt, isom_trak_t );
512 isom_box_common_copy( tapt, box );
513 int ret = isom_add_print_func( file, tapt, level );
514 if( ret < 0 )
515 return ret;
516 return isom_read_children( file, box, tapt, level );
519 static int isom_read_clef( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
521 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->clef )
522 return isom_read_unknown_box( file, box, parent, level );
523 ADD_BOX( clef, isom_tapt_t );
524 lsmash_bs_t *bs = file->bs;
525 clef->width = lsmash_bs_get_be32( bs );
526 clef->height = lsmash_bs_get_be32( bs );
527 return isom_read_leaf_box_common_last_process( file, box, level, clef );
530 static int isom_read_prof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
532 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->prof )
533 return isom_read_unknown_box( file, box, parent, level );
534 ADD_BOX( prof, isom_tapt_t );
535 lsmash_bs_t *bs = file->bs;
536 prof->width = lsmash_bs_get_be32( bs );
537 prof->height = lsmash_bs_get_be32( bs );
538 return isom_read_leaf_box_common_last_process( file, box, level, prof );
541 static int isom_read_enof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
543 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->enof )
544 return isom_read_unknown_box( file, box, parent, level );
545 ADD_BOX( enof, isom_tapt_t );
546 lsmash_bs_t *bs = file->bs;
547 enof->width = lsmash_bs_get_be32( bs );
548 enof->height = lsmash_bs_get_be32( bs );
549 return isom_read_leaf_box_common_last_process( file, box, level, enof );
552 static int isom_read_edts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
554 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->edts )
555 return isom_read_unknown_box( file, box, parent, level );
556 ADD_BOX( edts, isom_trak_t );
557 isom_box_common_copy( edts, box );
558 if( isom_add_print_func( file, edts, level ) < 0 )
559 return -1;
560 return isom_read_children( file, box, edts, level );
563 static int isom_read_elst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
565 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_EDTS ) || ((isom_edts_t *)parent)->elst )
566 return isom_read_unknown_box( file, box, parent, level );
567 ADD_BOX( elst, isom_edts_t );
568 lsmash_bs_t *bs = file->bs;
569 uint32_t entry_count = lsmash_bs_get_be32( bs );
570 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && elst->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
572 isom_elst_entry_t *data = lsmash_malloc( sizeof(isom_elst_entry_t) );
573 if( !data )
574 return LSMASH_ERR_MEMORY_ALLOC;
575 if( lsmash_add_entry( elst->list, data ) < 0 )
577 lsmash_free( data );
578 return LSMASH_ERR_MEMORY_ALLOC;
580 if( box->version == 1 )
582 data->segment_duration = lsmash_bs_get_be64( bs );
583 data->media_time = (int64_t)lsmash_bs_get_be64( bs );
585 else
587 data->segment_duration = lsmash_bs_get_be32( bs );
588 data->media_time = (int32_t)lsmash_bs_get_be32( bs );
590 data->media_rate = lsmash_bs_get_be32( bs );
592 return isom_read_leaf_box_common_last_process( file, box, level, elst );
595 static int isom_read_tref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
597 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tref )
598 return isom_read_unknown_box( file, box, parent, level );
599 ADD_BOX( tref, isom_trak_t );
600 isom_box_common_copy( tref, box );
601 int ret = isom_add_print_func( file, tref, level );
602 if( ret < 0 )
603 return ret;
604 return isom_read_children( file, box, tref, level );
607 static int isom_read_track_reference_type( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
609 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
610 return isom_read_unknown_box( file, box, parent, level );
611 isom_tref_type_t *ref = isom_add_track_reference_type( (isom_tref_t *)parent, box->type.fourcc );
612 if( !ref )
613 return LSMASH_ERR_NAMELESS;
614 lsmash_bs_t *bs = file->bs;
615 ref->ref_count = (box->size - lsmash_bs_count( bs ) ) / sizeof(uint32_t);
616 if( ref->ref_count )
618 ref->track_ID = lsmash_malloc( ref->ref_count * sizeof(uint32_t) );
619 if( !ref->track_ID )
621 ref->ref_count = 0;
622 return LSMASH_ERR_MEMORY_ALLOC;
624 for( uint32_t i = 0; i < ref->ref_count; i++ )
625 ref->track_ID[i] = lsmash_bs_get_be32( bs );
627 return isom_read_leaf_box_common_last_process( file, box, level, ref );
630 static int isom_read_mdia( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
632 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->mdia )
633 return isom_read_unknown_box( file, box, parent, level );
634 ADD_BOX( mdia, isom_trak_t );
635 isom_box_common_copy( mdia, box );
636 int ret = isom_add_print_func( file, mdia, level );
637 if( ret < 0 )
638 return ret;
639 return isom_read_children( file, box, mdia, level );
642 static int isom_read_mdhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
644 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->mdhd )
645 return isom_read_unknown_box( file, box, parent, level );
646 ADD_BOX( mdhd, isom_mdia_t );
647 lsmash_bs_t *bs = file->bs;
648 if( box->version )
650 mdhd->creation_time = lsmash_bs_get_be64( bs );
651 mdhd->modification_time = lsmash_bs_get_be64( bs );
652 mdhd->timescale = lsmash_bs_get_be32( bs );
653 mdhd->duration = lsmash_bs_get_be64( bs );
655 else
657 mdhd->creation_time = lsmash_bs_get_be32( bs );
658 mdhd->modification_time = lsmash_bs_get_be32( bs );
659 mdhd->timescale = lsmash_bs_get_be32( bs );
660 mdhd->duration = lsmash_bs_get_be32( bs );
662 mdhd->language = lsmash_bs_get_be16( bs );
663 mdhd->quality = lsmash_bs_get_be16( bs );
664 return isom_read_leaf_box_common_last_process( file, box, level, mdhd );
667 static int isom_read_hdlr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
669 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
670 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
671 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META )
672 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ))
673 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) && ((isom_mdia_t *)parent)->hdlr)
674 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
675 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
676 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->hdlr) )
677 return isom_read_unknown_box( file, box, parent, level );
678 ADD_BOX( hdlr, void );
679 lsmash_bs_t *bs = file->bs;
680 hdlr->componentType = lsmash_bs_get_be32( bs );
681 hdlr->componentSubtype = lsmash_bs_get_be32( bs );
682 hdlr->componentManufacturer = lsmash_bs_get_be32( bs );
683 hdlr->componentFlags = lsmash_bs_get_be32( bs );
684 hdlr->componentFlagsMask = lsmash_bs_get_be32( bs );
685 uint64_t pos = lsmash_bs_count( bs );
686 hdlr->componentName_length = box->size - pos;
687 if( hdlr->componentName_length )
689 hdlr->componentName = lsmash_malloc( hdlr->componentName_length );
690 if( !hdlr->componentName )
691 return LSMASH_ERR_MEMORY_ALLOC;
692 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
693 hdlr->componentName[i++] = lsmash_bs_get_byte( bs );
695 return isom_read_leaf_box_common_last_process( file, box, level, hdlr );
698 static int isom_read_minf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
700 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->minf )
701 return isom_read_unknown_box( file, box, parent, level );
702 ADD_BOX( minf, isom_mdia_t );
703 isom_box_common_copy( minf, box );
704 int ret = isom_add_print_func( file, minf, level );
705 if( ret < 0 )
706 return ret;
707 return isom_read_children( file, box, minf, level );
710 static int isom_read_vmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
712 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->vmhd )
713 return isom_read_unknown_box( file, box, parent, level );
714 ADD_BOX( vmhd, isom_minf_t );
715 lsmash_bs_t *bs = file->bs;
716 vmhd->graphicsmode = lsmash_bs_get_be16( bs );
717 for( int i = 0; i < 3; i++ )
718 vmhd->opcolor[i] = lsmash_bs_get_be16( bs );
719 return isom_read_leaf_box_common_last_process( file, box, level, vmhd );
722 static int isom_read_smhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
724 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->smhd )
725 return isom_read_unknown_box( file, box, parent, level );
726 ADD_BOX( smhd, isom_minf_t );
727 lsmash_bs_t *bs = file->bs;
728 smhd->balance = lsmash_bs_get_be16( bs );
729 smhd->reserved = lsmash_bs_get_be16( bs );
730 return isom_read_leaf_box_common_last_process( file, box, level, smhd );
733 static int isom_read_hmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
735 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->hmhd )
736 return isom_read_unknown_box( file, box, parent, level );
737 ADD_BOX( hmhd, isom_minf_t );
738 lsmash_bs_t *bs = file->bs;
739 hmhd->maxPDUsize = lsmash_bs_get_be16( bs );
740 hmhd->avgPDUsize = lsmash_bs_get_be16( bs );
741 hmhd->maxbitrate = lsmash_bs_get_be32( bs );
742 hmhd->avgbitrate = lsmash_bs_get_be32( bs );
743 hmhd->reserved = lsmash_bs_get_be32( bs );
744 return isom_read_leaf_box_common_last_process( file, box, level, hmhd );
747 static int isom_read_nmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
749 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->nmhd )
750 return isom_read_unknown_box( file, box, parent, level );
751 ADD_BOX( nmhd, isom_minf_t );
752 return isom_read_leaf_box_common_last_process( file, box, level, nmhd );
755 static int isom_read_gmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
757 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->gmhd )
758 return isom_read_unknown_box( file, box, parent, level );
759 ADD_BOX( gmhd, isom_minf_t );
760 isom_box_common_copy( gmhd, box );
761 int ret = isom_add_print_func( file, gmhd, level );
762 if( ret < 0 )
763 return ret;
764 return isom_read_children( file, box, gmhd, level );
767 static int isom_read_gmin( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
769 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->gmin )
770 return isom_read_unknown_box( file, box, parent, level );
771 ADD_BOX( gmin, isom_gmhd_t );
772 lsmash_bs_t *bs = file->bs;
773 gmin->graphicsmode = lsmash_bs_get_be16( bs );
774 for( int i = 0; i < 3; i++ )
775 gmin->opcolor[i] = lsmash_bs_get_be16( bs );
776 gmin->balance = lsmash_bs_get_be16( bs );
777 gmin->reserved = lsmash_bs_get_be16( bs );
778 return isom_read_leaf_box_common_last_process( file, box, level, gmin );
781 static int isom_read_text( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
783 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->text )
784 return isom_read_unknown_box( file, box, parent, level );
785 ADD_BOX( text, isom_gmhd_t );
786 lsmash_bs_t *bs = file->bs;
787 for( int i = 0; i < 9; i++ )
788 text->matrix[i] = lsmash_bs_get_be32( bs );
789 return isom_read_leaf_box_common_last_process( file, box, level, text );
792 static int isom_read_dinf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
794 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
795 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
796 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
797 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->dinf)
798 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf)
799 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf) )
800 return isom_read_unknown_box( file, box, parent, level );
801 ADD_BOX( dinf, void );
802 isom_box_common_copy( dinf, box );
803 int ret = isom_add_print_func( file, dinf, level );
804 if( ret < 0 )
805 return ret;
806 return isom_read_children( file, box, dinf, level );
809 static int isom_read_dref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
811 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DINF ) || ((isom_dinf_t *)parent)->dref )
812 return isom_read_unknown_box( file, box, parent, level );
813 ADD_BOX( dref, isom_dinf_t );
814 lsmash_bs_t *bs = file->bs;
815 dref->list.entry_count = lsmash_bs_get_be32( bs );
816 isom_box_common_copy( dref, box );
817 int ret = isom_add_print_func( file, dref, level );
818 if( ret < 0 )
819 return ret;
820 return isom_read_children( file, box, dref, level );
823 static int isom_read_dref_entry( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
825 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
826 return isom_read_unknown_box( file, box, parent, level );
827 isom_dref_t *dref = (isom_dref_t *)parent;
828 if( !dref->list.head )
829 dref->list.entry_count = 0; /* discard entry_count gotten from the file */
830 isom_dref_entry_t *ref = isom_add_dref_entry( dref, box->type );
831 if( !ref )
832 return LSMASH_ERR_NAMELESS;
833 lsmash_bs_t *bs = file->bs;
834 if( lsmash_check_box_type_identical( ref->type, ISOM_BOX_TYPE_URL ) )
836 uint64_t pos = lsmash_bs_count( bs );
837 ref->location_length = box->size - pos;
838 if( ref->location_length )
840 ref->location = lsmash_malloc( ref->location_length );
841 if( !ref->location )
842 return LSMASH_ERR_MEMORY_ALLOC;
843 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
844 ref->location[i++] = lsmash_bs_get_byte( bs );
847 else
848 isom_skip_box_rest( bs, box );
849 if( box->flags & 0x000001 )
850 ref->ref_file = ref->file;
851 box->parent = parent;
852 return isom_read_leaf_box_common_last_process( file, box, level, ref );
855 static int isom_read_stbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
857 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->stbl )
858 return isom_read_unknown_box( file, box, parent, level );
859 ADD_BOX( stbl, isom_minf_t );
860 isom_box_common_copy( stbl, box );
861 int ret = isom_add_print_func( file, stbl, level );
862 if( ret < 0 )
863 return ret;
864 return isom_read_children( file, box, stbl, level );
867 static int isom_read_stsd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
869 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsd )
870 return isom_read_unknown_box( file, box, parent, level );
871 ADD_BOX( stsd, isom_stbl_t );
872 lsmash_bs_t *bs = file->bs;
873 stsd->entry_count = lsmash_bs_get_be32( bs );
874 isom_box_common_copy( stsd, box );
875 int ret = isom_add_print_func( file, stsd, level );
876 if( ret < 0 )
877 return ret;
878 uint64_t stsd_pos = lsmash_bs_count( bs );
879 for( uint32_t i = 0; i < stsd->entry_count || (stsd_pos + ISOM_BASEBOX_COMMON_SIZE) <= stsd->size; i++ )
881 if( (ret = isom_read_box( file, box, (isom_box_t *)stsd, stsd_pos, level )) != 0 )
882 break;
883 stsd_pos += box->size;
884 if( stsd->size <= stsd_pos || bs->eob || bs->error )
885 break;
887 if( stsd->size < stsd_pos )
889 printf( "[stsd] box has extra bytes: %"PRId64"\n", stsd_pos - stsd->size );
890 stsd->size = stsd_pos;
892 box->size = stsd->size;
893 return ret;
896 static int isom_read_codec_specific( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
898 lsmash_bs_t *bs = file->bs;
899 uint64_t opaque_pos = lsmash_bs_count( bs );
900 uint64_t exdata_length = box->size - opaque_pos;
901 if( exdata_length > UINT32_MAX )
902 return LSMASH_ERR_MEMORY_ALLOC;
903 uint8_t *exdata = lsmash_malloc( box->size );
904 if( !exdata )
905 return LSMASH_ERR_MEMORY_ALLOC;
906 int ret = lsmash_bs_get_bytes_ex( bs, exdata_length, exdata + (uintptr_t)opaque_pos );
907 if( ret < 0 )
908 goto fail;
909 LSMASH_SET_BE32( &exdata[0], box->size );
910 LSMASH_SET_BE32( &exdata[4], box->type.fourcc );
911 uintptr_t i = 8;
912 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc )
914 LSMASH_SET_BE32( &exdata[8], box->type.user.fourcc );
915 memcpy( &exdata[12], box->type.user.id, 12 );
916 i += 16;
918 if( box->manager & LSMASH_FULLBOX )
920 LSMASH_SET_BYTE( &exdata[i], box->version );
921 i += 1;
922 LSMASH_SET_BE24( &exdata[i], box->flags );
923 i += 3;
925 if( i != opaque_pos )
927 ret = LSMASH_ERR_INVALID_DATA;
928 goto fail;
930 if( (ret = isom_add_extension_binary( parent, box->type, LSMASH_BOX_PRECEDENCE_N, exdata, box->size )) < 0 )
931 goto fail;
932 isom_box_t *ext = (isom_box_t *)parent->extensions.tail->data;
933 box->manager |= ext->manager;
934 isom_check_box_size( file->bs, box );
935 isom_basebox_common_copy( ext, box );
936 return isom_add_print_func( file, ext, level );
937 fail:
938 lsmash_free( exdata );
939 return ret;
942 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
944 assert( isom_check_media_hdlr_from_stsd( stsd ) );
945 /* Determine suitable allocation size. */
946 size_t alloc_size = 0;
947 lsmash_media_type media_type = ((isom_mdia_t *)stsd->parent->parent->parent)->hdlr->componentSubtype;
948 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
949 alloc_size = sizeof(isom_visual_entry_t);
950 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
951 alloc_size = sizeof(isom_audio_entry_t);
952 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
954 if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
955 alloc_size = sizeof(isom_tx3g_entry_t);
956 else if( lsmash_check_codec_type_identical( sample_type, QT_CODEC_TYPE_TEXT_TEXT ) )
957 alloc_size = sizeof(isom_qt_text_entry_t);
959 else if( lsmash_check_codec_type_identical( sample_type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
960 alloc_size = sizeof(isom_mp4s_entry_t);
961 /* Return allocated memory block if the allocation size is non-zero. */
962 if( alloc_size == 0 )
963 return NULL;
964 return lsmash_malloc_zero( alloc_size );
967 static void *isom_add_description( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
969 void *sample = isom_sample_description_alloc( sample_type, stsd );
970 if( !sample )
971 return NULL;
972 if( lsmash_add_entry( &stsd->list, sample ) < 0 )
974 lsmash_free( sample );
975 return NULL;
977 if( lsmash_add_entry( &stsd->extensions, sample ) < 0 )
979 lsmash_remove_entry_tail( &stsd->list, lsmash_free );
980 return NULL;
982 ((isom_box_t *)sample)->destruct = (isom_extension_destructor_t)isom_remove_sample_description;
983 return sample;
986 static int isom_read_visual_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
988 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
989 return isom_read_unknown_box( file, box, parent, level );
990 isom_visual_entry_t *visual = (isom_visual_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
991 if( !visual )
992 return LSMASH_ERR_MEMORY_ALLOC;
993 lsmash_bs_t *bs = file->bs;
994 for( int i = 0; i < 6; i++ )
995 visual->reserved[i] = lsmash_bs_get_byte( bs );
996 visual->data_reference_index = lsmash_bs_get_be16( bs );
997 visual->version = lsmash_bs_get_be16( bs );
998 visual->revision_level = lsmash_bs_get_be16( bs );
999 visual->vendor = lsmash_bs_get_be32( bs );
1000 visual->temporalQuality = lsmash_bs_get_be32( bs );
1001 visual->spatialQuality = lsmash_bs_get_be32( bs );
1002 visual->width = lsmash_bs_get_be16( bs );
1003 visual->height = lsmash_bs_get_be16( bs );
1004 visual->horizresolution = lsmash_bs_get_be32( bs );
1005 visual->vertresolution = lsmash_bs_get_be32( bs );
1006 visual->dataSize = lsmash_bs_get_be32( bs );
1007 visual->frame_count = lsmash_bs_get_be16( bs );
1008 for( int i = 0; i < 32; i++ )
1009 visual->compressorname[i] = lsmash_bs_get_byte( bs );
1010 visual->depth = lsmash_bs_get_be16( bs );
1011 visual->color_table_ID = lsmash_bs_get_be16( bs );
1012 int ret;
1013 if( visual->color_table_ID == 0
1014 && lsmash_bs_get_pos( bs ) < box->size
1015 && (ret = isom_read_qt_color_table( bs, &visual->color_table )) < 0 )
1016 return ret;
1017 box->parent = parent;
1018 box->manager |= LSMASH_VIDEO_DESCRIPTION;
1019 isom_box_common_copy( visual, box );
1020 if( (ret = isom_add_print_func( file, visual, level )) < 0 )
1021 return ret;
1022 return isom_read_children( file, box, visual, level );
1025 static int isom_read_esds( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1027 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4V_VIDEO )
1028 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO )
1029 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_M4AE_AUDIO )
1030 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4S_SYSTEM )
1031 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1032 return isom_read_unknown_box( file, box, parent, level );
1033 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1035 box->type = QT_BOX_TYPE_ESDS;
1036 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO ) )
1037 parent->parent->type = QT_CODEC_TYPE_MP4A_AUDIO;
1039 else
1040 box->type = ISOM_BOX_TYPE_ESDS;
1041 ADD_BOX( esds, void );
1042 lsmash_bs_t *bs = file->bs;
1043 esds->ES = mp4sys_get_descriptor( bs, NULL );
1044 if( !esds->ES )
1045 return LSMASH_ERR_INVALID_DATA;
1046 return isom_read_leaf_box_common_last_process( file, box, level, esds );
1049 static int isom_read_btrt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1051 ADD_BOX( btrt, isom_visual_entry_t );
1052 lsmash_bs_t *bs = file->bs;
1053 btrt->bufferSizeDB = lsmash_bs_get_be32( bs );
1054 btrt->maxBitrate = lsmash_bs_get_be32( bs );
1055 btrt->avgBitrate = lsmash_bs_get_be32( bs );
1056 return isom_read_leaf_box_common_last_process( file, box, level, btrt );
1059 static int isom_read_glbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1061 ADD_BOX( glbl, isom_visual_entry_t );
1062 lsmash_bs_t *bs = file->bs;
1063 uint32_t header_size = box->size - ISOM_BASEBOX_COMMON_SIZE;
1064 if( header_size )
1066 glbl->header_data = lsmash_malloc( header_size );
1067 if( !glbl->header_data )
1068 return LSMASH_ERR_MEMORY_ALLOC;
1069 for( uint32_t i = 0; i < header_size; i++ )
1070 glbl->header_data[i] = lsmash_bs_get_byte( bs );
1072 glbl->header_size = header_size;
1073 return isom_read_leaf_box_common_last_process( file, box, level, glbl );
1076 static int isom_read_clap( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1078 ADD_BOX( clap, isom_visual_entry_t );
1079 lsmash_bs_t *bs = file->bs;
1080 clap->cleanApertureWidthN = lsmash_bs_get_be32( bs );
1081 clap->cleanApertureWidthD = lsmash_bs_get_be32( bs );
1082 clap->cleanApertureHeightN = lsmash_bs_get_be32( bs );
1083 clap->cleanApertureHeightD = lsmash_bs_get_be32( bs );
1084 clap->horizOffN = lsmash_bs_get_be32( bs );
1085 clap->horizOffD = lsmash_bs_get_be32( bs );
1086 clap->vertOffN = lsmash_bs_get_be32( bs );
1087 clap->vertOffD = lsmash_bs_get_be32( bs );
1088 return isom_read_leaf_box_common_last_process( file, box, level, clap );
1091 static int isom_read_pasp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1093 ADD_BOX( pasp, isom_visual_entry_t );
1094 lsmash_bs_t *bs = file->bs;
1095 pasp->hSpacing = lsmash_bs_get_be32( bs );
1096 pasp->vSpacing = lsmash_bs_get_be32( bs );
1097 return isom_read_leaf_box_common_last_process( file, box, level, pasp );
1100 static int isom_read_colr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1102 ADD_BOX( colr, isom_visual_entry_t );
1103 lsmash_bs_t *bs = file->bs;
1104 colr->color_parameter_type = lsmash_bs_get_be32( bs );
1105 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
1106 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1108 colr->primaries_index = lsmash_bs_get_be16( bs );
1109 colr->transfer_function_index = lsmash_bs_get_be16( bs );
1110 colr->matrix_index = lsmash_bs_get_be16( bs );
1111 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1113 if( lsmash_bs_count( bs ) < box->size )
1115 uint8_t temp8 = lsmash_bs_get_byte( bs );
1116 colr->full_range_flag = (temp8 >> 7) & 0x01;
1117 colr->reserved = temp8 & 0x7f;
1119 else
1121 /* It seems this box is broken or incomplete. */
1122 box->manager |= LSMASH_INCOMPLETE_BOX;
1123 colr->full_range_flag = 0;
1124 colr->reserved = 0;
1127 else
1128 box->manager |= LSMASH_QTFF_BASE;
1130 box->type = (box->manager & LSMASH_QTFF_BASE) ? QT_BOX_TYPE_COLR : ISOM_BOX_TYPE_COLR;
1131 return isom_read_leaf_box_common_last_process( file, box, level, colr );
1134 static int isom_read_gama( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1136 ADD_BOX( gama, isom_visual_entry_t );
1137 lsmash_bs_t *bs = file->bs;
1138 gama->level = lsmash_bs_get_be32( bs );
1139 return isom_read_leaf_box_common_last_process( file, box, level, gama );
1142 static int isom_read_fiel( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1144 ADD_BOX( fiel, isom_visual_entry_t );
1145 lsmash_bs_t *bs = file->bs;
1146 fiel->fields = lsmash_bs_get_byte( bs );
1147 fiel->detail = lsmash_bs_get_byte( bs );
1148 return isom_read_leaf_box_common_last_process( file, box, level, fiel );
1151 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1153 ADD_BOX( cspc, isom_visual_entry_t );
1154 lsmash_bs_t *bs = file->bs;
1155 cspc->pixel_format = lsmash_bs_get_be32( bs );
1156 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1159 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1161 ADD_BOX( sgbt, isom_visual_entry_t );
1162 lsmash_bs_t *bs = file->bs;
1163 sgbt->significantBits = lsmash_bs_get_byte( bs );
1164 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1167 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1169 ADD_BOX( stsl, isom_visual_entry_t );
1170 lsmash_bs_t *bs = file->bs;
1171 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1172 stsl->scale_method = lsmash_bs_get_byte( bs );
1173 stsl->display_center_x = lsmash_bs_get_be16( bs );
1174 stsl->display_center_y = lsmash_bs_get_be16( bs );
1175 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1178 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1180 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1181 return isom_read_unknown_box( file, box, parent, level );
1182 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1183 if( !audio )
1184 return LSMASH_ERR_MEMORY_ALLOC;
1185 lsmash_bs_t *bs = file->bs;
1186 for( int i = 0; i < 6; i++ )
1187 audio->reserved[i] = lsmash_bs_get_byte( bs );
1188 audio->data_reference_index = lsmash_bs_get_be16( bs );
1189 audio->version = lsmash_bs_get_be16( bs );
1190 audio->revision_level = lsmash_bs_get_be16( bs );
1191 audio->vendor = lsmash_bs_get_be32( bs );
1192 audio->channelcount = lsmash_bs_get_be16( bs );
1193 audio->samplesize = lsmash_bs_get_be16( bs );
1194 audio->compression_ID = lsmash_bs_get_be16( bs );
1195 audio->packet_size = lsmash_bs_get_be16( bs );
1196 audio->samplerate = lsmash_bs_get_be32( bs );
1197 if( audio->version == 0 && isom_is_qt_audio( box->type ) )
1199 /* Skip weird extra bytes.
1200 * About QTFF, extensions were first added with Sound Sample Description v1. */
1201 while( lsmash_bs_count( bs ) + ISOM_BASEBOX_COMMON_SIZE <= box->size )
1203 uint32_t size = lsmash_bs_show_be32( bs, 0 );
1204 if( size == 0 || lsmash_bs_count( bs ) + size > box->size )
1205 lsmash_bs_skip_bytes( bs, 1 );
1206 else
1207 break;
1210 else if( audio->version == 1 )
1212 if( ((isom_stsd_t *)parent)->version == 0 )
1214 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1215 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1216 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1217 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1218 box->manager |= LSMASH_QTFF_BASE;
1220 else
1221 /* AudioSampleEntryV1 has no additional fields. */
1222 box->manager &= ~LSMASH_QTFF_BASE;
1224 else if( audio->version == 2 )
1226 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1227 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1228 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1229 audio->always7F000000 = lsmash_bs_get_be32( bs );
1230 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1231 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1232 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1233 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1234 box->manager |= LSMASH_QTFF_BASE;
1236 box->parent = parent;
1237 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1238 isom_box_common_copy( audio, box );
1239 int ret = isom_add_print_func( file, audio, level );
1240 if( ret < 0 )
1241 return ret;
1242 return isom_read_children( file, box, audio, level );
1245 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1247 ADD_BOX( wave, isom_audio_entry_t );
1248 isom_box_common_copy( wave, box );
1249 int ret = isom_add_print_func( file, wave, level );
1250 if( ret < 0 )
1251 return ret;
1252 return isom_read_children( file, box, wave, level );
1255 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1257 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->frma )
1258 return isom_read_unknown_box( file, box, parent, level );
1259 ADD_BOX( frma, isom_wave_t );
1260 lsmash_bs_t *bs = file->bs;
1261 frma->data_format = lsmash_bs_get_be32( bs );
1262 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1265 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1267 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->enda )
1268 return isom_read_unknown_box( file, box, parent, level );
1269 ADD_BOX( enda, isom_wave_t );
1270 lsmash_bs_t *bs = file->bs;
1271 enda->littleEndian = lsmash_bs_get_be16( bs );
1272 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1275 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1277 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->terminator )
1278 return isom_read_unknown_box( file, box, parent, level );
1279 ADD_BOX( terminator, isom_wave_t );
1280 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1283 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1285 ADD_BOX( chan, isom_audio_entry_t );
1286 lsmash_bs_t *bs = file->bs;
1287 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1288 chan->channelBitmap = lsmash_bs_get_be32( bs );
1289 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1290 if( chan->numberChannelDescriptions )
1292 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1293 if( !desc )
1294 return LSMASH_ERR_MEMORY_ALLOC;
1295 chan->channelDescriptions = desc;
1296 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1298 desc->channelLabel = lsmash_bs_get_be32( bs );
1299 desc->channelFlags = lsmash_bs_get_be32( bs );
1300 for( int j = 0; j < 3; j++ )
1301 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1304 /* A 'chan' box often contains extra 20 bytes (= the number of bytes of one channel description). */
1305 isom_skip_box_rest( bs, box );
1306 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1309 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1311 ADD_BOX( srat, isom_audio_entry_t );
1312 lsmash_bs_t *bs = file->bs;
1313 srat->sampling_rate = lsmash_bs_get_be32( bs );
1314 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1317 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1319 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1320 return isom_read_unknown_box( file, box, parent, level );
1321 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1322 if( !text )
1323 return LSMASH_ERR_MEMORY_ALLOC;
1324 lsmash_bs_t *bs = file->bs;
1325 for( int i = 0; i < 6; i++ )
1326 text->reserved[i] = lsmash_bs_get_byte( bs );
1327 text->data_reference_index = lsmash_bs_get_be16( bs );
1328 text->displayFlags = lsmash_bs_get_be32( bs );
1329 text->textJustification = lsmash_bs_get_be32( bs );
1330 for( int i = 0; i < 3; i++ )
1331 text->bgColor[i] = lsmash_bs_get_be16( bs );
1332 text->top = lsmash_bs_get_be16( bs );
1333 text->left = lsmash_bs_get_be16( bs );
1334 text->bottom = lsmash_bs_get_be16( bs );
1335 text->right = lsmash_bs_get_be16( bs );
1336 text->scrpStartChar = lsmash_bs_get_be32( bs );
1337 text->scrpHeight = lsmash_bs_get_be16( bs );
1338 text->scrpAscent = lsmash_bs_get_be16( bs );
1339 text->scrpFont = lsmash_bs_get_be16( bs );
1340 text->scrpFace = lsmash_bs_get_be16( bs );
1341 text->scrpSize = lsmash_bs_get_be16( bs );
1342 for( int i = 0; i < 3; i++ )
1343 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1344 text->font_name_length = lsmash_bs_get_byte( bs );
1345 if( text->font_name_length )
1347 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1348 if( !text->font_name )
1349 return LSMASH_ERR_MEMORY_ALLOC;
1350 for( uint8_t i = 0; i < text->font_name_length; i++ )
1351 text->font_name[i] = lsmash_bs_get_byte( bs );
1352 text->font_name[text->font_name_length] = '\0';
1354 box->parent = parent;
1355 isom_box_common_copy( text, box );
1356 int ret = isom_add_print_func( file, text, level );
1357 if( ret < 0 )
1358 return ret;
1359 return isom_read_children( file, box, text, level );
1362 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1364 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1365 return isom_read_unknown_box( file, box, parent, level );
1366 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1367 if( !tx3g )
1368 return LSMASH_ERR_MEMORY_ALLOC;
1369 lsmash_bs_t *bs = file->bs;
1370 for( int i = 0; i < 6; i++ )
1371 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1372 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1373 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1374 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1375 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1376 for( int i = 0; i < 4; i++ )
1377 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1378 tx3g->top = lsmash_bs_get_be16( bs );
1379 tx3g->left = lsmash_bs_get_be16( bs );
1380 tx3g->bottom = lsmash_bs_get_be16( bs );
1381 tx3g->right = lsmash_bs_get_be16( bs );
1382 tx3g->startChar = lsmash_bs_get_be16( bs );
1383 tx3g->endChar = lsmash_bs_get_be16( bs );
1384 tx3g->font_ID = lsmash_bs_get_be16( bs );
1385 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1386 tx3g->font_size = lsmash_bs_get_byte( bs );
1387 for( int i = 0; i < 4; i++ )
1388 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1389 box->parent = parent;
1390 isom_box_common_copy( tx3g, box );
1391 int ret = isom_add_print_func( file, tx3g, level );
1392 if( ret < 0 )
1393 return ret;
1394 return isom_read_children( file, box, tx3g, level );
1397 static int isom_read_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1399 if( lsmash_check_codec_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1400 return isom_read_qt_text_description( file, box, parent, level );
1401 else if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1402 return isom_read_tx3g_description( file, box, parent, level );
1403 assert( 0 );
1404 return isom_read_unknown_box( file, box, parent, level );
1407 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1409 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1410 || ((isom_tx3g_entry_t *)parent)->ftab )
1411 return isom_read_unknown_box( file, box, parent, level );
1412 ADD_BOX( ftab, isom_tx3g_entry_t );
1413 lsmash_bs_t *bs = file->bs;
1414 uint32_t entry_count = lsmash_bs_get_be16( bs );
1415 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1417 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1418 if( !data )
1419 return LSMASH_ERR_MEMORY_ALLOC;
1420 if( lsmash_add_entry( ftab->list, data ) < 0 )
1422 lsmash_free( data );
1423 return LSMASH_ERR_MEMORY_ALLOC;
1425 data->font_ID = lsmash_bs_get_be16( bs );
1426 data->font_name_length = lsmash_bs_get_byte( bs );
1427 if( data->font_name_length )
1429 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1430 if( !data->font_name )
1431 return LSMASH_ERR_MEMORY_ALLOC;
1432 for( uint8_t i = 0; i < data->font_name_length; i++ )
1433 data->font_name[i] = lsmash_bs_get_byte( bs );
1434 data->font_name[data->font_name_length] = '\0';
1437 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1440 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1442 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1443 return isom_read_unknown_box( file, box, parent, level );
1444 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1445 if( !mp4s )
1446 return LSMASH_ERR_MEMORY_ALLOC;
1447 lsmash_bs_t *bs = file->bs;
1448 for( int i = 0; i < 6; i++ )
1449 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1450 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1451 box->parent = parent;
1452 isom_box_common_copy( mp4s, box );
1453 int ret = isom_add_print_func( file, mp4s, level );
1454 if( ret < 0 )
1455 return ret;
1456 return isom_read_children( file, box, mp4s, level );
1459 static int isom_read_other_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1461 if( lsmash_check_codec_type_identical( box->type, ISOM_CODEC_TYPE_MP4S_SYSTEM ) )
1462 return isom_read_mp4s_description( file, box, parent, level );
1463 return isom_read_unknown_box( file, box, parent, level );
1466 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1468 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stts )
1469 return isom_read_unknown_box( file, box, parent, level );
1470 ADD_BOX( stts, isom_stbl_t );
1471 lsmash_bs_t *bs = file->bs;
1472 uint32_t entry_count = lsmash_bs_get_be32( bs );
1473 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1475 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1476 if( !data )
1477 return LSMASH_ERR_MEMORY_ALLOC;
1478 if( lsmash_add_entry( stts->list, data ) < 0 )
1480 lsmash_free( data );
1481 return LSMASH_ERR_MEMORY_ALLOC;
1483 data->sample_count = lsmash_bs_get_be32( bs );
1484 data->sample_delta = lsmash_bs_get_be32( bs );
1486 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1489 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1491 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->ctts )
1492 return isom_read_unknown_box( file, box, parent, level );
1493 ADD_BOX( ctts, isom_stbl_t );
1494 lsmash_bs_t *bs = file->bs;
1495 uint32_t entry_count = lsmash_bs_get_be32( bs );
1496 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1498 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1499 if( !data )
1500 return LSMASH_ERR_MEMORY_ALLOC;
1501 if( lsmash_add_entry( ctts->list, data ) < 0 )
1503 lsmash_free( data );
1504 return LSMASH_ERR_MEMORY_ALLOC;
1506 data->sample_count = lsmash_bs_get_be32( bs );
1507 data->sample_offset = lsmash_bs_get_be32( bs );
1509 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1512 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1514 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->cslg )
1515 return isom_read_unknown_box( file, box, parent, level );
1516 ADD_BOX( cslg, isom_stbl_t );
1517 lsmash_bs_t *bs = file->bs;
1518 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1519 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1520 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1521 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1522 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1523 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1526 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1528 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stss )
1529 return isom_read_unknown_box( file, box, parent, level );
1530 ADD_BOX( stss, isom_stbl_t );
1531 lsmash_bs_t *bs = file->bs;
1532 uint32_t entry_count = lsmash_bs_get_be32( bs );
1533 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1535 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1536 if( !data )
1537 return LSMASH_ERR_MEMORY_ALLOC;
1538 if( lsmash_add_entry( stss->list, data ) < 0 )
1540 lsmash_free( data );
1541 return LSMASH_ERR_MEMORY_ALLOC;
1543 data->sample_number = lsmash_bs_get_be32( bs );
1545 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1548 static int isom_read_stps( 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 ) || ((isom_stbl_t *)parent)->stps )
1551 return isom_read_unknown_box( file, box, parent, level );
1552 ADD_BOX( stps, isom_stbl_t );
1553 lsmash_bs_t *bs = file->bs;
1554 uint32_t entry_count = lsmash_bs_get_be32( bs );
1555 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1557 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1558 if( !data )
1559 return LSMASH_ERR_MEMORY_ALLOC;
1560 if( lsmash_add_entry( stps->list, data ) < 0 )
1562 lsmash_free( data );
1563 return LSMASH_ERR_MEMORY_ALLOC;
1565 data->sample_number = lsmash_bs_get_be32( bs );
1567 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1570 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1572 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1573 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1574 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && ((isom_stbl_t *)parent)->sdtp)
1575 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && ((isom_traf_t *)parent)->sdtp))
1576 return isom_read_unknown_box( file, box, parent, level );
1577 ADD_BOX( sdtp, isom_box_t );
1578 lsmash_bs_t *bs = file->bs;
1579 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1581 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1582 if( !data )
1583 return LSMASH_ERR_MEMORY_ALLOC;
1584 if( lsmash_add_entry( sdtp->list, data ) < 0 )
1586 lsmash_free( data );
1587 return LSMASH_ERR_MEMORY_ALLOC;
1589 uint8_t temp = lsmash_bs_get_byte( bs );
1590 data->is_leading = (temp >> 6) & 0x3;
1591 data->sample_depends_on = (temp >> 4) & 0x3;
1592 data->sample_is_depended_on = (temp >> 2) & 0x3;
1593 data->sample_has_redundancy = temp & 0x3;
1595 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1598 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1600 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsc )
1601 return isom_read_unknown_box( file, box, parent, level );
1602 ADD_BOX( stsc, isom_stbl_t );
1603 lsmash_bs_t *bs = file->bs;
1604 uint32_t entry_count = lsmash_bs_get_be32( bs );
1605 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1607 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1608 if( !data )
1609 return LSMASH_ERR_MEMORY_ALLOC;
1610 if( lsmash_add_entry( stsc->list, data ) < 0 )
1612 lsmash_free( data );
1613 return LSMASH_ERR_MEMORY_ALLOC;
1615 data->first_chunk = lsmash_bs_get_be32( bs );
1616 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1617 data->sample_description_index = lsmash_bs_get_be32( bs );
1619 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1622 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1624 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsz )
1625 return isom_read_unknown_box( file, box, parent, level );
1626 ADD_BOX( stsz, isom_stbl_t );
1627 lsmash_bs_t *bs = file->bs;
1628 stsz->sample_size = lsmash_bs_get_be32( bs );
1629 stsz->sample_count = lsmash_bs_get_be32( bs );
1630 uint64_t pos = lsmash_bs_count( bs );
1631 if( pos < box->size )
1633 stsz->list = lsmash_create_entry_list();
1634 if( !stsz->list )
1635 return LSMASH_ERR_MEMORY_ALLOC;
1636 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1638 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1639 if( !data )
1640 return LSMASH_ERR_MEMORY_ALLOC;
1641 if( lsmash_add_entry( stsz->list, data ) < 0 )
1643 lsmash_free( data );
1644 return LSMASH_ERR_MEMORY_ALLOC;
1646 data->entry_size = lsmash_bs_get_be32( bs );
1649 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1652 static int isom_read_stz2( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1654 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stz2 )
1655 return isom_read_unknown_box( file, box, parent, level );
1656 ADD_BOX( stz2, isom_stbl_t );
1657 lsmash_bs_t *bs = file->bs;
1658 uint32_t temp32 = lsmash_bs_get_be32( bs );
1659 stz2->reserved = temp32 >> 24;
1660 stz2->field_size = temp32 & 0xff;
1661 stz2->sample_count = lsmash_bs_get_be32( bs );
1662 uint64_t pos = lsmash_bs_count( bs );
1663 if( pos < box->size )
1665 if( stz2->field_size == 16 || stz2->field_size == 8 )
1667 uint64_t (*bs_get_funcs[2])( lsmash_bs_t * ) =
1669 lsmash_bs_get_byte_to_64,
1670 lsmash_bs_get_be16_to_64
1672 uint64_t (*bs_get_entry_size)( lsmash_bs_t * ) = bs_get_funcs[ stz2->field_size == 16 ? 1 : 0 ];
1673 for( ; pos < box->size && stz2->list->entry_count < stz2->sample_count; pos = lsmash_bs_count( bs ) )
1675 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1676 if( !data )
1677 return LSMASH_ERR_MEMORY_ALLOC;
1678 if( lsmash_add_entry( stz2->list, data ) < 0 )
1680 lsmash_free( data );
1681 return LSMASH_ERR_MEMORY_ALLOC;
1683 data->entry_size = bs_get_entry_size( bs );
1686 else if( stz2->field_size == 4 )
1688 int parity = 1;
1689 uint8_t temp8;
1690 while( pos < box->size && stz2->list->entry_count < stz2->sample_count )
1692 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1693 if( !data )
1694 return LSMASH_ERR_MEMORY_ALLOC;
1695 if( lsmash_add_entry( stz2->list, data ) < 0 )
1697 lsmash_free( data );
1698 return LSMASH_ERR_MEMORY_ALLOC;
1700 /* Read a byte by two entries. */
1701 if( parity )
1703 temp8 = lsmash_bs_get_byte( bs );
1704 data->entry_size = (temp8 >> 4) & 0xf;
1706 else
1708 pos = lsmash_bs_count( bs );
1709 data->entry_size = temp8 & 0xf;
1711 parity ^= 1;
1714 else
1715 return LSMASH_ERR_INVALID_DATA;
1717 return isom_read_leaf_box_common_last_process( file, box, level, stz2 );
1720 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1722 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stco )
1723 return isom_read_unknown_box( file, box, parent, level );
1724 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1725 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1726 isom_stco_t *stco = is_stco
1727 ? isom_add_stco( (isom_stbl_t *)parent )
1728 : isom_add_co64( (isom_stbl_t *)parent );
1729 if( !stco )
1730 return LSMASH_ERR_NAMELESS;
1731 lsmash_bs_t *bs = file->bs;
1732 uint32_t entry_count = lsmash_bs_get_be32( bs );
1733 if( is_stco )
1734 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1736 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1737 if( !data )
1738 return LSMASH_ERR_MEMORY_ALLOC;
1739 if( lsmash_add_entry( stco->list, data ) < 0 )
1741 lsmash_free( data );
1742 return LSMASH_ERR_MEMORY_ALLOC;
1744 data->chunk_offset = lsmash_bs_get_be32( bs );
1746 else
1748 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1750 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1751 if( !data )
1752 return LSMASH_ERR_MEMORY_ALLOC;
1753 if( lsmash_add_entry( stco->list, data ) < 0 )
1755 lsmash_free( data );
1756 return LSMASH_ERR_MEMORY_ALLOC;
1758 data->chunk_offset = lsmash_bs_get_be64( bs );
1761 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1764 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1766 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1767 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1768 return isom_read_unknown_box( file, box, parent, level );
1769 ADD_BOX( sgpd, void );
1770 lsmash_bs_t *bs = file->bs;
1771 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1772 if( box->version == 1 )
1773 sgpd->default_length = lsmash_bs_get_be32( bs );
1774 uint32_t entry_count = lsmash_bs_get_be32( bs );
1775 switch( sgpd->grouping_type )
1777 case ISOM_GROUP_TYPE_RAP :
1779 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1781 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1782 if( !data )
1783 return LSMASH_ERR_MEMORY_ALLOC;
1784 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1786 lsmash_free( data );
1787 return LSMASH_ERR_MEMORY_ALLOC;
1789 memset( data, 0, sizeof(isom_rap_entry_t) );
1790 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1791 if( box->version == 1 && !sgpd->default_length )
1792 data->description_length = lsmash_bs_get_be32( bs );
1793 else
1795 uint8_t temp = lsmash_bs_get_byte( bs );
1796 data->num_leading_samples_known = (temp >> 7) & 0x01;
1797 data->num_leading_samples = temp & 0x7f;
1800 break;
1802 case ISOM_GROUP_TYPE_ROLL :
1803 case ISOM_GROUP_TYPE_PROL :
1805 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1807 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1808 if( !data )
1809 return LSMASH_ERR_MEMORY_ALLOC;
1810 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1812 lsmash_free( data );
1813 return LSMASH_ERR_MEMORY_ALLOC;
1815 memset( data, 0, sizeof(isom_roll_entry_t) );
1816 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1817 if( box->version == 1 && !sgpd->default_length )
1818 data->description_length = lsmash_bs_get_be32( bs );
1819 else
1820 data->roll_distance = lsmash_bs_get_be16( bs );
1822 break;
1824 default :
1825 break;
1827 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1830 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1832 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1833 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1834 return isom_read_unknown_box( file, box, parent, level );
1835 ADD_BOX( sbgp, void );
1836 lsmash_bs_t *bs = file->bs;
1837 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1838 if( box->version == 1 )
1839 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1840 uint32_t entry_count = lsmash_bs_get_be32( bs );
1841 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1843 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1844 if( !data )
1845 return LSMASH_ERR_MEMORY_ALLOC;
1846 if( lsmash_add_entry( sbgp->list, data ) < 0 )
1848 lsmash_free( data );
1849 return LSMASH_ERR_MEMORY_ALLOC;
1851 data->sample_count = lsmash_bs_get_be32( bs );
1852 data->group_description_index = lsmash_bs_get_be32( bs );
1854 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1857 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1859 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1860 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1861 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->udta)
1862 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->udta) )
1863 return isom_read_unknown_box( file, box, parent, level );
1864 ADD_BOX( udta, void );
1865 isom_box_common_copy( udta, box );
1866 int ret = isom_add_print_func( file, udta, level );
1867 if( ret < 0 )
1868 return ret;
1869 return isom_read_children( file, box, udta, level );
1872 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1874 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->chpl )
1875 return isom_read_unknown_box( file, box, parent, level );
1876 ADD_BOX( chpl, isom_udta_t );
1877 lsmash_bs_t *bs = file->bs;
1878 uint32_t entry_count;
1879 if( box->version == 1 )
1881 chpl->unknown = lsmash_bs_get_byte( bs );
1882 entry_count = lsmash_bs_get_be32( bs );
1884 else
1885 entry_count = lsmash_bs_get_byte( bs );
1886 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1888 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1889 if( !data )
1890 return LSMASH_ERR_MEMORY_ALLOC;
1891 if( lsmash_add_entry( chpl->list, data ) < 0 )
1893 lsmash_free( data );
1894 return LSMASH_ERR_MEMORY_ALLOC;
1896 data->start_time = lsmash_bs_get_be64( bs );
1897 data->chapter_name_length = lsmash_bs_get_byte( bs );
1898 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1899 if( !data->chapter_name )
1901 lsmash_free( data );
1902 return LSMASH_ERR_MEMORY_ALLOC;
1904 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1905 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1906 data->chapter_name[data->chapter_name_length] = '\0';
1908 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1911 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1913 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvex )
1914 return isom_read_unknown_box( file, box, parent, level );
1915 ADD_BOX( mvex, isom_moov_t );
1916 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1917 isom_box_common_copy( mvex, box );
1918 int ret = isom_add_print_func( file, mvex, level );
1919 if( ret < 0 )
1920 return ret;
1921 return isom_read_children( file, box, mvex, level );
1924 static int isom_read_mehd( 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_MVEX ) || ((isom_mvex_t *)parent)->mehd )
1927 return isom_read_unknown_box( file, box, parent, level );
1928 ADD_BOX( mehd, isom_mvex_t );
1929 lsmash_bs_t *bs = file->bs;
1930 if( box->version == 1 )
1931 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1932 else
1933 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1934 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1937 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1939 uint32_t temp = lsmash_bs_get_be32( bs );
1940 isom_sample_flags_t flags;
1941 flags.reserved = (temp >> 28) & 0xf;
1942 flags.is_leading = (temp >> 26) & 0x3;
1943 flags.sample_depends_on = (temp >> 24) & 0x3;
1944 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1945 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1946 flags.sample_padding_value = (temp >> 17) & 0x7;
1947 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1948 flags.sample_degradation_priority = temp & 0xffff;
1949 return flags;
1952 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1954 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
1955 return isom_read_unknown_box( file, box, parent, level );
1956 ADD_BOX( trex, isom_mvex_t );
1957 box->parent = parent;
1958 lsmash_bs_t *bs = file->bs;
1959 trex->track_ID = lsmash_bs_get_be32( bs );
1960 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
1961 trex->default_sample_duration = lsmash_bs_get_be32( bs );
1962 trex->default_sample_size = lsmash_bs_get_be32( bs );
1963 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
1964 return isom_read_leaf_box_common_last_process( file, box, level, trex );
1967 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1969 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
1970 return isom_read_unknown_box( file, box, parent, level );
1971 ADD_BOX( moof, lsmash_file_t );
1972 box->parent = parent;
1973 isom_box_common_copy( moof, box );
1974 int ret = isom_add_print_func( file, moof, level );
1975 if( ret < 0 )
1976 return ret;
1977 return isom_read_children( file, box, moof, level );
1980 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1982 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) || ((isom_moof_t *)parent)->mfhd )
1983 return isom_read_unknown_box( file, box, parent, level );
1984 ADD_BOX( mfhd, isom_moof_t );
1985 lsmash_bs_t *bs = file->bs;
1986 mfhd->sequence_number = lsmash_bs_get_be32( bs );
1987 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
1990 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1992 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
1993 return isom_read_unknown_box( file, box, parent, level );
1994 ADD_BOX( traf, isom_moof_t );
1995 box->parent = parent;
1996 isom_box_common_copy( traf, box );
1997 int ret = isom_add_print_func( file, traf, level );
1998 if( ret < 0 )
1999 return ret;
2000 return isom_read_children( file, box, traf, level );
2003 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2005 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfhd )
2006 return isom_read_unknown_box( file, box, parent, level );
2007 ADD_BOX( tfhd, isom_traf_t );
2008 lsmash_bs_t *bs = file->bs;
2009 tfhd->track_ID = lsmash_bs_get_be32( bs );
2010 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2011 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2012 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2013 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2014 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2015 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2018 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2020 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfdt )
2021 return isom_read_unknown_box( file, box, parent, level );
2022 ADD_BOX( tfdt, isom_traf_t );
2023 lsmash_bs_t *bs = file->bs;
2024 if( box->version == 1 )
2025 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2026 else
2027 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2028 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2031 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2033 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2034 return isom_read_unknown_box( file, box, parent, level );
2035 ADD_BOX( trun, isom_traf_t );
2036 box->parent = parent;
2037 lsmash_bs_t *bs = file->bs;
2038 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2039 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2040 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2041 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2042 has_optional_rows &= box->flags;
2043 trun->sample_count = lsmash_bs_get_be32( bs );
2044 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2045 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2046 if( trun->sample_count && has_optional_rows )
2048 trun->optional = lsmash_create_entry_list();
2049 if( !trun->optional )
2050 return LSMASH_ERR_MEMORY_ALLOC;
2051 for( uint32_t i = 0; i < trun->sample_count; i++ )
2053 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2054 if( !data )
2055 return LSMASH_ERR_MEMORY_ALLOC;
2056 if( lsmash_add_entry( trun->optional, data ) < 0 )
2058 lsmash_free( data );
2059 return LSMASH_ERR_MEMORY_ALLOC;
2061 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2062 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2063 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2064 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2067 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2070 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2072 if( file->fake_file_mode )
2073 return isom_read_unknown_box( file, box, parent, level );
2074 isom_box_t *skip = lsmash_malloc_zero( sizeof(isom_box_t) );
2075 if( !skip )
2076 return LSMASH_ERR_MEMORY_ALLOC;
2077 isom_skip_box_rest( file->bs, box );
2078 box->manager |= LSMASH_ABSENT_IN_FILE;
2079 isom_box_common_copy( skip, box );
2080 int ret = isom_add_print_func( file, skip, level );
2081 if( ret < 0 )
2083 lsmash_free( skip );
2084 return ret;
2086 return 0;
2089 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2091 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2092 return isom_read_unknown_box( file, box, parent, level );
2093 isom_box_t *mdat = lsmash_malloc_zero( sizeof(isom_box_t) );
2094 if( !mdat )
2095 return LSMASH_ERR_MEMORY_ALLOC;
2096 isom_skip_box_rest( file->bs, box );
2097 box->manager |= LSMASH_ABSENT_IN_FILE;
2098 file->flags |= LSMASH_FILE_MODE_MEDIA;
2099 isom_box_common_copy( mdat, box );
2100 int ret = isom_add_print_func( file, mdat, level );
2101 if( ret < 0 )
2103 lsmash_free( mdat );
2104 return ret;
2106 return 0;
2109 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2111 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2112 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2113 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2114 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2115 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && ((lsmash_file_t *)parent)->meta)
2116 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->meta)
2117 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->meta)
2118 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && ((isom_udta_t *)parent)->meta) )
2119 return isom_read_unknown_box( file, box, parent, level );
2120 ADD_BOX( meta, void );
2121 isom_box_common_copy( meta, box );
2122 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2123 if( is_qtff )
2125 box->manager |= LSMASH_QTFF_BASE;
2126 meta->manager |= LSMASH_QTFF_BASE;
2128 int ret = isom_add_print_func( file, meta, level );
2129 if( ret < 0 )
2130 return ret;
2131 return isom_read_children( file, box, meta, level );
2134 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2136 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2137 || ((isom_meta_t *)parent)->keys )
2138 return isom_read_unknown_box( file, box, parent, level );
2139 ADD_BOX( keys, isom_meta_t );
2140 lsmash_bs_t *bs = file->bs;
2141 uint32_t entry_count = lsmash_bs_get_be32( bs );
2142 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2144 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2145 if( !data )
2146 return LSMASH_ERR_MEMORY_ALLOC;
2147 if( lsmash_add_entry( keys->list, data ) < 0 )
2149 lsmash_free( data );
2150 return LSMASH_ERR_MEMORY_ALLOC;
2152 data->key_size = lsmash_bs_get_be32( bs );
2153 data->key_namespace = lsmash_bs_get_be32( bs );
2154 if( data->key_size > 8 )
2156 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2157 if( !data->key_value )
2158 return LSMASH_ERR_NAMELESS;
2160 else
2161 data->key_value = NULL;
2163 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2166 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2168 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2169 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2170 || ((isom_meta_t *)parent)->ilst )
2171 return isom_read_unknown_box( file, box, parent, level );
2172 ADD_BOX( ilst, isom_meta_t );
2173 isom_box_common_copy( ilst, box );
2174 int ret = isom_add_print_func( file, ilst, level );
2175 if( ret < 0 )
2176 return ret;
2177 return isom_read_children( file, box, ilst, level );
2180 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2182 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2183 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2184 return isom_read_unknown_box( file, box, parent, level );
2185 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2186 if( !metaitem )
2187 return -1;
2188 box->parent = parent;
2189 isom_box_common_copy( metaitem, box );
2190 int ret = isom_add_print_func( file, metaitem, level );
2191 if( ret < 0 )
2192 return ret;
2193 return isom_read_children( file, box, metaitem, level );
2196 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2198 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->mean )
2199 return isom_read_unknown_box( file, box, parent, level );
2200 ADD_BOX( mean, isom_metaitem_t );
2201 lsmash_bs_t *bs = file->bs;
2202 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2203 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2204 if( !mean->meaning_string )
2205 return LSMASH_ERR_NAMELESS;
2206 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2209 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2211 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->name )
2212 return isom_read_unknown_box( file, box, parent, level );
2213 ADD_BOX( name, isom_metaitem_t );
2214 lsmash_bs_t *bs = file->bs;
2215 name->name_length = box->size - lsmash_bs_count( bs );
2216 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2217 if( !name->name )
2218 return LSMASH_ERR_NAMELESS;
2219 return isom_read_leaf_box_common_last_process( file, box, level, name );
2222 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2224 if( ((isom_metaitem_t *)parent)->data )
2225 return isom_read_unknown_box( file, box, parent, level );
2226 ADD_BOX( data, isom_metaitem_t );
2227 lsmash_bs_t *bs = file->bs;
2228 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2229 data->reserved = lsmash_bs_get_be16( bs );
2230 data->type_set_identifier = lsmash_bs_get_byte( bs );
2231 data->type_code = lsmash_bs_get_byte( bs );
2232 data->the_locale = lsmash_bs_get_be32( bs );
2233 if( data->value_length )
2235 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2236 if( !data->value )
2237 return LSMASH_ERR_NAMELESS;
2239 return isom_read_leaf_box_common_last_process( file, box, level, data );
2242 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2244 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->WLOC )
2245 return isom_read_unknown_box( file, box, parent, level );
2246 ADD_BOX( WLOC, isom_udta_t );
2247 lsmash_bs_t *bs = file->bs;
2248 WLOC->x = lsmash_bs_get_be16( bs );
2249 WLOC->y = lsmash_bs_get_be16( bs );
2250 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2253 static int isom_read_LOOP( 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_UDTA ) || ((isom_udta_t *)parent)->LOOP )
2256 return isom_read_unknown_box( file, box, parent, level );
2257 ADD_BOX( LOOP, isom_udta_t );
2258 lsmash_bs_t *bs = file->bs;
2259 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2260 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2263 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2265 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->SelO )
2266 return isom_read_unknown_box( file, box, parent, level );
2267 ADD_BOX( SelO, isom_udta_t );
2268 lsmash_bs_t *bs = file->bs;
2269 SelO->selection_only = lsmash_bs_get_byte( bs );
2270 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2273 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2275 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->AllF )
2276 return isom_read_unknown_box( file, box, parent, level );
2277 ADD_BOX( AllF, isom_udta_t );
2278 lsmash_bs_t *bs = file->bs;
2279 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2280 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2283 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2285 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2286 return isom_read_unknown_box( file, box, parent, level );
2287 ADD_BOX( cprt, isom_udta_t );
2288 box->parent = parent;
2289 lsmash_bs_t *bs = file->bs;
2290 cprt->language = lsmash_bs_get_be16( bs );
2291 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2292 if( cprt->notice_length )
2294 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2295 if( !cprt->notice )
2297 cprt->notice_length = 0;
2298 return LSMASH_ERR_NAMELESS;
2301 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2304 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2306 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->mfra )
2307 return isom_read_unknown_box( file, box, parent, level );
2308 ADD_BOX( mfra, lsmash_file_t );
2309 isom_box_common_copy( mfra, box );
2310 int ret = isom_add_print_func( file, mfra, level );
2311 if( ret < 0 )
2312 return ret;
2313 return isom_read_children( file, box, mfra, level );
2316 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2318 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2319 return isom_read_unknown_box( file, box, parent, level );
2320 ADD_BOX( tfra, isom_mfra_t );
2321 box->parent = parent;
2322 lsmash_bs_t *bs = file->bs;
2323 tfra->track_ID = lsmash_bs_get_be32( bs );
2324 uint32_t temp = lsmash_bs_get_be32( bs );
2325 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2326 tfra->reserved = (temp >> 6) & 0x3ffffff;
2327 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2328 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2329 tfra->length_size_of_sample_num = temp & 0x3;
2330 if( tfra->number_of_entry )
2332 tfra->list = lsmash_create_entry_list();
2333 if( !tfra->list )
2334 return LSMASH_ERR_MEMORY_ALLOC;
2335 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2337 lsmash_bs_get_byte_to_64,
2338 lsmash_bs_get_be16_to_64,
2339 lsmash_bs_get_be24_to_64,
2340 lsmash_bs_get_be32_to_64,
2341 lsmash_bs_get_be64
2343 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2344 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2345 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2346 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2347 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2348 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2350 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2351 if( !data )
2352 return LSMASH_ERR_MEMORY_ALLOC;
2353 if( lsmash_add_entry( tfra->list, data ) < 0 )
2355 lsmash_free( data );
2356 return LSMASH_ERR_MEMORY_ALLOC;
2358 data->time = bs_put_time ( bs );
2359 data->moof_offset = bs_put_moof_offset ( bs );
2360 data->traf_number = bs_put_traf_number ( bs );
2361 data->trun_number = bs_put_trun_number ( bs );
2362 data->sample_number = bs_put_sample_number( bs );
2365 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2368 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2370 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) || ((isom_mfra_t *)parent)->mfro )
2371 return isom_read_unknown_box( file, box, parent, level );
2372 ADD_BOX( mfro, isom_mfra_t );
2373 lsmash_bs_t *bs = file->bs;
2374 mfro->length = lsmash_bs_get_be32( bs );
2375 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2378 static void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2380 if( !bs->unseekable )
2382 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2383 while( size > (INT64_MAX >> 1) )
2385 lsmash_bs_read_seek( bs, INT64_MAX >> 1, SEEK_CUR );
2386 if( lsmash_bs_is_end( bs, 0 ) )
2387 return;
2388 size -= (INT64_MAX >> 1);
2390 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2392 else
2393 lsmash_bs_skip_bytes_64( bs, size );
2396 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2398 lsmash_bs_t *bs = file->bs;
2399 /* Skip extra bytes of the parent box if any. */
2400 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2402 uint64_t extra_bytes = parent->size - parent_pos;
2403 isom_read_skip_extra_bytes( bs, extra_bytes );
2404 /* This is not the size of a box but makes sense in isom_read_children(). */
2405 box->size = extra_bytes;
2406 return 1;
2408 /* Check if the size is valid or not. */
2409 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2411 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2412 if( size > 1
2413 && size < ISOM_BASEBOX_COMMON_SIZE )
2415 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2416 * Skip bytes up to the next box of the parent box. */
2417 uint64_t extra_bytes = parent->size - parent_pos;
2418 isom_read_skip_extra_bytes( bs, extra_bytes );
2419 box->size = extra_bytes;
2420 return 1;
2422 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2423 size = lsmash_bs_show_be64( bs, 8 ); /* large size */
2424 if( size == 0 && parent != (isom_box_t *)file )
2426 /* Check if this box is actually the last box or not. */
2427 uint64_t extra_bytes = parent->size - parent_pos;
2428 if( !bs->unseekable )
2429 size = bs->written - lsmash_bs_get_stream_pos( bs );
2430 else
2432 size = lsmash_bs_get_remaining_buffer_size( bs );
2433 while( size <= extra_bytes )
2435 int ret = lsmash_bs_read( bs, 1 );
2436 if( bs->eof || ret < 0 )
2437 break;
2438 size = lsmash_bs_get_remaining_buffer_size( bs );
2441 if( size != extra_bytes )
2443 /* This is not the size of the last box.
2444 * It seems we are still within the box considered as the previous or the parent box.
2445 * Skip bytes up to the next box. */
2446 if( box->size > lsmash_bs_count( bs ) )
2448 /* within the previous */
2449 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2450 box->size = 0; /* already added to the size of the parent box */
2452 else
2454 /* within the parent */
2455 isom_read_skip_extra_bytes( bs, extra_bytes );
2456 box->size = extra_bytes;
2458 return 1;
2462 return 0;
2465 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2467 assert( parent && parent->root && parent->file );
2468 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2469 return 0;
2470 memset( box, 0, sizeof(isom_box_t) );
2471 box->root = parent->root;
2472 box->file = parent->file;
2473 box->parent = parent;
2474 lsmash_bs_t *bs = file->bs;
2475 int ret = isom_bs_read_box_common( bs, box );
2476 if( !!ret )
2477 return ret; /* return if reached EOF */
2478 ++level;
2479 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2480 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2481 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2483 /* OK, this box is a sample entry.
2484 * Here, determine the suitable sample entry reader by media type if possible. */
2485 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
2486 goto read_box;
2487 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
2488 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
2489 reader_func = isom_read_visual_description;
2490 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
2491 reader_func = isom_read_audio_description;
2492 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
2493 reader_func = isom_read_text_description;
2494 else
2495 reader_func = isom_read_other_description;
2496 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2497 static struct description_reader_table_tag
2499 lsmash_compact_box_type_t fourcc;
2500 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2501 } description_reader_table[160] = { { 0, NULL } };
2502 if( !description_reader_table[0].form_box_type_func )
2504 /* Initialize the table. */
2505 int i = 0;
2506 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2507 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2508 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type );
2509 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type );
2510 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type );
2511 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type );
2512 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type );
2513 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type );
2514 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type );
2515 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type );
2516 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type );
2517 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type );
2518 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type );
2519 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type );
2520 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type );
2521 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type );
2522 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type );
2523 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type );
2524 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type );
2525 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type );
2526 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type );
2527 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type );
2528 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type );
2529 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type );
2530 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type );
2531 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type );
2532 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type );
2533 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type );
2534 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type );
2535 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type );
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type );
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type );
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type );
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type );
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type );
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type );
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type );
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type );
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type );
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type );
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type );
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO, lsmash_form_qtff_box_type );
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type );
2549 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type );
2551 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type );
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type );
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type );
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type );
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type );
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type );
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type );
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type );
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type );
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type );
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type );
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type );
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type );
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type );
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type );
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO, lsmash_form_qtff_box_type );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type );
2606 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type );
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type );
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW, lsmash_form_qtff_box_type );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL );
2642 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2644 for( int i = 0; description_reader_table[i].form_box_type_func; i++ )
2645 if( box->type.fourcc == description_reader_table[i].fourcc )
2647 form_box_type_func = description_reader_table[i].form_box_type_func;
2648 goto read_box;
2650 goto read_box;
2652 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2654 form_box_type_func = lsmash_form_qtff_box_type;
2655 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2656 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2657 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2658 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2659 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2660 else reader_func = isom_read_codec_specific;
2661 goto read_box;
2663 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2665 form_box_type_func = lsmash_form_iso_box_type;
2666 reader_func = isom_read_track_reference_type;
2667 goto read_box;
2669 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2671 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2672 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2673 form_box_type_func = lsmash_form_iso_box_type;
2674 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2675 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2676 form_box_type_func = lsmash_form_qtff_box_type;
2677 reader_func = isom_read_dref_entry;
2678 goto read_box;
2680 static struct box_reader_table_tag
2682 lsmash_compact_box_type_t fourcc;
2683 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2684 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2685 } box_reader_table[128] = { { 0, NULL, NULL } };
2686 if( !box_reader_table[0].reader_func )
2688 /* Initialize the table. */
2689 int i = 0;
2690 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2691 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2692 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2693 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2694 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2695 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2696 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2697 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2698 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2699 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2700 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2701 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2702 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2703 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2704 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2705 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2706 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2707 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2708 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2709 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2710 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2711 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2712 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2713 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2714 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2715 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2716 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2717 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2718 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2719 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2720 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2721 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2722 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2724 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2726 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2727 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2728 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2729 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2730 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2731 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2732 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2733 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2734 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2735 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2736 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2737 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2738 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2739 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2740 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2741 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2742 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2743 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2744 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2745 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2746 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, lsmash_form_iso_box_type, isom_read_stz2 );
2747 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2748 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2749 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2750 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2753 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2754 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2755 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2756 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2757 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2758 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2760 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2761 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2762 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2763 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2769 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2773 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2774 #undef ADD_BOX_READER_TABLE_ELEMENT
2776 for( int i = 0; box_reader_table[i].reader_func; i++ )
2777 if( box->type.fourcc == box_reader_table[i].fourcc )
2779 form_box_type_func = box_reader_table[i].form_box_type_func;
2780 reader_func = box_reader_table[i].reader_func;
2781 goto read_box;
2783 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2785 if( lsmash_bs_is_end ( bs, 3 ) == 0
2786 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2787 form_box_type_func = lsmash_form_iso_box_type;
2788 else
2789 form_box_type_func = lsmash_form_qtff_box_type;
2790 reader_func = isom_read_meta;
2791 goto read_box;
2793 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2795 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2796 form_box_type_func = lsmash_form_iso_box_type;
2797 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2798 form_box_type_func = lsmash_form_qtff_box_type;
2799 if( form_box_type_func )
2801 reader_func = isom_read_ilst;
2802 goto read_box;
2805 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2806 form_box_type_func = lsmash_form_iso_box_type;
2807 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2808 form_box_type_func = lsmash_form_qtff_box_type;
2809 if( form_box_type_func )
2811 reader_func = isom_read_metaitem;
2812 goto read_box;
2814 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2816 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2817 reader_func = isom_read_mean;
2818 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2819 reader_func = isom_read_name;
2820 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2821 reader_func = isom_read_data;
2822 if( reader_func )
2824 form_box_type_func = lsmash_form_iso_box_type;
2825 goto read_box;
2828 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2830 /* Avoid confusing udta.cprt with ilst.cprt. */
2831 form_box_type_func = lsmash_form_iso_box_type;
2832 reader_func = isom_read_cprt;
2833 goto read_box;
2835 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2837 static struct codec_specific_marker_table_tag
2839 lsmash_compact_box_type_t fourcc;
2840 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2841 } codec_specific_marker_table[16] = { { 0, NULL } };
2842 if( !codec_specific_marker_table[0].form_box_type_func )
2844 /* Initialize the table. */
2845 int i = 0;
2846 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2847 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2848 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type );
2849 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type );
2850 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type );
2851 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type );
2852 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type );
2853 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type );
2854 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type );
2855 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type );
2856 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type );
2857 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type );
2858 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2859 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2861 for( int i = 0; codec_specific_marker_table[i].form_box_type_func; i++ )
2862 if( box->type.fourcc == codec_specific_marker_table[i].fourcc )
2864 form_box_type_func = codec_specific_marker_table[i].form_box_type_func;
2865 break;
2867 reader_func = isom_read_codec_specific;
2869 read_box:
2870 if( form_box_type_func )
2871 box->type = form_box_type_func( box->type.fourcc );
2872 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2873 return ret;
2874 return reader_func
2875 ? reader_func( file, box, parent, level )
2876 : isom_read_unknown_box( file, box, parent, level );
2879 int isom_read_file( lsmash_file_t *file )
2881 lsmash_bs_t *bs = file->bs;
2882 if( !bs )
2883 return LSMASH_ERR_NAMELESS;
2884 /* Reset the counter so that we can use it to get position within the box. */
2885 lsmash_bs_reset_counter( bs );
2886 if( file->flags & LSMASH_FILE_MODE_DUMP )
2888 file->print = lsmash_create_entry_list();
2889 if( !file->print )
2890 return LSMASH_ERR_MEMORY_ALLOC;
2892 file->size = UINT64_MAX;
2893 isom_box_t box;
2894 int ret = isom_read_children( file, &box, file, 0 );
2895 file->size = box.size;
2896 lsmash_bs_empty( bs );
2897 bs->error = 0; /* Clear error flag. */
2898 if( ret < 0 )
2899 return ret;
2900 return isom_check_compatibility( file );