file: Support writing of multiple segments.
[L-SMASH.git] / core / read.c
blob1f1624fbaa3612bb41d0ce7c6ca9cc959b9cae1c
1 /*****************************************************************************
2 * read.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2014 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 -1;
220 isom_unknown_box_t *unknown = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
221 if( !unknown )
222 return -1;
223 if( lsmash_add_entry( &parent->extensions, unknown ) )
225 lsmash_free( unknown );
226 return -1;
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 -1;
246 box->manager |= LSMASH_ABSENT_IN_FILE;
247 isom_box_common_copy( dummy, box );
248 if( isom_add_print_func( file, dummy, level ) < 0 )
250 lsmash_free( dummy );
251 return -1;
253 return 0;
256 #define ADD_BOX( box_name, parent_type ) \
257 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
258 if( !box_name ) \
259 return -1
261 static int isom_read_ftyp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
263 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->ftyp )
264 return isom_read_unknown_box( file, box, parent, level );
265 ADD_BOX( ftyp, lsmash_file_t );
266 lsmash_bs_t *bs = file->bs;
267 ftyp->major_brand = lsmash_bs_get_be32( bs );
268 ftyp->minor_version = lsmash_bs_get_be32( bs );
269 uint64_t pos = lsmash_bs_count( bs );
270 ftyp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
271 size_t alloc_size = ftyp->brand_count * sizeof(uint32_t);
272 ftyp->compatible_brands = ftyp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
273 if( ftyp->brand_count && !ftyp->compatible_brands )
274 return -1;
275 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
276 ftyp->compatible_brands[i] = lsmash_bs_get_be32( bs );
277 if( !file->compatible_brands && ftyp->compatible_brands )
279 file->compatible_brands = lsmash_memdup( ftyp->compatible_brands, alloc_size );
280 if( !file->compatible_brands )
281 return -1;
282 file->brand_count = ftyp->brand_count;
284 return isom_read_leaf_box_common_last_process( file, box, level, ftyp );
287 static int isom_read_styp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
289 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
290 return isom_read_unknown_box( file, box, parent, level );
291 ADD_BOX( styp, lsmash_file_t );
292 lsmash_bs_t *bs = file->bs;
293 styp->major_brand = lsmash_bs_get_be32( bs );
294 styp->minor_version = lsmash_bs_get_be32( bs );
295 uint64_t pos = lsmash_bs_count( bs );
296 styp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
297 size_t alloc_size = styp->brand_count * sizeof(uint32_t);
298 styp->compatible_brands = styp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
299 if( styp->brand_count && !styp->compatible_brands )
300 return -1;
301 for( uint32_t i = 0; i < styp->brand_count; i++ )
302 styp->compatible_brands[i] = lsmash_bs_get_be32( bs );
303 if( !file->compatible_brands && styp->compatible_brands )
305 file->compatible_brands = lsmash_memdup( styp->compatible_brands, alloc_size );
306 if( !file->compatible_brands )
307 return -1;
308 file->brand_count = styp->brand_count;
310 file->flags |= LSMASH_FILE_MODE_SEGMENT;
311 return isom_read_leaf_box_common_last_process( file, box, level, styp );
314 static int isom_read_sidx( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
316 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
317 return isom_read_unknown_box( file, box, parent, level );
318 ADD_BOX( sidx, lsmash_file_t );
319 lsmash_bs_t *bs = file->bs;
320 sidx->reference_ID = lsmash_bs_get_be32( bs );
321 sidx->timescale = lsmash_bs_get_be32( bs );
322 if( box->version == 0 )
324 sidx->earliest_presentation_time = lsmash_bs_get_be32( bs );
325 sidx->first_offset = lsmash_bs_get_be32( bs );
327 else
329 sidx->earliest_presentation_time = lsmash_bs_get_be64( bs );
330 sidx->first_offset = lsmash_bs_get_be64( bs );
332 sidx->reserved = lsmash_bs_get_be16( bs );
333 sidx->reference_count = lsmash_bs_get_be16( bs );
334 for( uint64_t pos = lsmash_bs_count( bs );
335 pos < box->size && sidx->list->entry_count < sidx->reference_count;
336 pos = lsmash_bs_count( bs ) )
338 isom_sidx_referenced_item_t *data = lsmash_malloc( sizeof(isom_sidx_referenced_item_t) );
339 if( !data )
340 return -1;
341 if( lsmash_add_entry( sidx->list, data ) )
343 lsmash_free( data );
344 return -1;
346 uint32_t temp32;
347 temp32 = lsmash_bs_get_be32( bs );
348 data->reference_type = (temp32 >> 31) & 0x00000001;
349 data->reference_size = temp32 & 0x7FFFFFFF;
350 data->subsegment_duration = lsmash_bs_get_be32( bs );
351 temp32 = lsmash_bs_get_be32( bs );
352 data->starts_with_SAP = (temp32 >> 31) & 0x00000001;
353 data->SAP_type = (temp32 >> 28) & 0x00000007;
354 data->SAP_delta_time = temp32 & 0x0FFFFFFF;
356 file->flags |= LSMASH_FILE_MODE_INDEX;
357 return isom_read_leaf_box_common_last_process( file, box, level, sidx );
360 static int isom_read_moov( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
362 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->moov )
363 return isom_read_unknown_box( file, box, parent, level );
364 ADD_BOX( moov, lsmash_file_t );
365 file->flags |= LSMASH_FILE_MODE_INITIALIZATION;
366 file->initializer = file;
367 isom_box_common_copy( moov, box );
368 if( isom_add_print_func( file, moov, level ) )
369 return -1;
370 return isom_read_children( file, box, moov, level );
373 static int isom_read_mvhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
375 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvhd )
376 return isom_read_unknown_box( file, box, parent, level );
377 ADD_BOX( mvhd, isom_moov_t );
378 lsmash_bs_t *bs = file->bs;
379 if( box->version )
381 mvhd->creation_time = lsmash_bs_get_be64( bs );
382 mvhd->modification_time = lsmash_bs_get_be64( bs );
383 mvhd->timescale = lsmash_bs_get_be32( bs );
384 mvhd->duration = lsmash_bs_get_be64( bs );
386 else
388 mvhd->creation_time = lsmash_bs_get_be32( bs );
389 mvhd->modification_time = lsmash_bs_get_be32( bs );
390 mvhd->timescale = lsmash_bs_get_be32( bs );
391 mvhd->duration = lsmash_bs_get_be32( bs );
393 mvhd->rate = lsmash_bs_get_be32( bs );
394 mvhd->volume = lsmash_bs_get_be16( bs );
395 mvhd->reserved = lsmash_bs_get_be16( bs );
396 mvhd->preferredLong[0] = lsmash_bs_get_be32( bs );
397 mvhd->preferredLong[1] = lsmash_bs_get_be32( bs );
398 for( int i = 0; i < 9; i++ )
399 mvhd->matrix[i] = lsmash_bs_get_be32( bs );
400 mvhd->previewTime = lsmash_bs_get_be32( bs );
401 mvhd->previewDuration = lsmash_bs_get_be32( bs );
402 mvhd->posterTime = lsmash_bs_get_be32( bs );
403 mvhd->selectionTime = lsmash_bs_get_be32( bs );
404 mvhd->selectionDuration = lsmash_bs_get_be32( bs );
405 mvhd->currentTime = lsmash_bs_get_be32( bs );
406 mvhd->next_track_ID = lsmash_bs_get_be32( bs );
407 return isom_read_leaf_box_common_last_process( file, box, level, mvhd );
410 static int isom_read_iods( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
412 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
413 return isom_read_unknown_box( file, box, parent, level );
414 ADD_BOX( iods, isom_moov_t );
415 lsmash_bs_t *bs = file->bs;
416 iods->OD = mp4sys_get_descriptor( bs, NULL );
417 if( !iods->OD )
418 return -1;
419 isom_skip_box_rest( file->bs, box );
420 return isom_read_leaf_box_common_last_process( file, box, level, iods );
423 static int isom_read_qt_color_table( lsmash_bs_t *bs, isom_qt_color_table_t *color_table )
425 color_table->seed = lsmash_bs_get_be32( bs );
426 color_table->flags = lsmash_bs_get_be16( bs );
427 color_table->size = lsmash_bs_get_be16( bs );
428 if( bs->eob )
429 return -1;
430 isom_qt_color_array_t *array = lsmash_malloc_zero( (color_table->size + 1) * sizeof(isom_qt_color_array_t) );
431 if( !array )
432 return -1;
433 color_table->array = array;
434 for( uint16_t i = 0; i <= color_table->size; i++ )
436 uint64_t color = lsmash_bs_get_be64( bs );
437 array[i].value = (color >> 48) & 0xffff;
438 array[i].r = (color >> 32) & 0xffff;
439 array[i].g = (color >> 16) & 0xffff;
440 array[i].b = color & 0xffff;
442 return 0;
445 static int isom_read_ctab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
447 ADD_BOX( ctab, isom_moov_t );
448 lsmash_bs_t *bs = file->bs;
449 if( isom_read_qt_color_table( bs, &ctab->color_table ) < 0 )
450 return -1;
451 return isom_read_leaf_box_common_last_process( file, box, level, ctab );
454 static int isom_read_trak( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
456 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
457 return isom_read_unknown_box( file, box, parent, level );
458 ADD_BOX( trak, isom_moov_t );
459 box->parent = parent;
460 box->root = file->root;
461 box->file = file;
462 isom_box_common_copy( trak, box );
463 if( isom_add_print_func( file, trak, level ) )
464 return -1;
465 return isom_read_children( file, box, trak, level );
468 static int isom_read_tkhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
470 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tkhd )
471 return isom_read_unknown_box( file, box, parent, level );
472 ADD_BOX( tkhd, isom_trak_t );
473 lsmash_bs_t *bs = file->bs;
474 if( box->version )
476 tkhd->creation_time = lsmash_bs_get_be64( bs );
477 tkhd->modification_time = lsmash_bs_get_be64( bs );
478 tkhd->track_ID = lsmash_bs_get_be32( bs );
479 tkhd->reserved1 = lsmash_bs_get_be32( bs );
480 tkhd->duration = lsmash_bs_get_be64( bs );
482 else
484 tkhd->creation_time = lsmash_bs_get_be32( bs );
485 tkhd->modification_time = lsmash_bs_get_be32( bs );
486 tkhd->track_ID = lsmash_bs_get_be32( bs );
487 tkhd->reserved1 = lsmash_bs_get_be32( bs );
488 tkhd->duration = lsmash_bs_get_be32( bs );
490 tkhd->reserved2[0] = lsmash_bs_get_be32( bs );
491 tkhd->reserved2[1] = lsmash_bs_get_be32( bs );
492 tkhd->layer = lsmash_bs_get_be16( bs );
493 tkhd->alternate_group = lsmash_bs_get_be16( bs );
494 tkhd->volume = lsmash_bs_get_be16( bs );
495 tkhd->reserved3 = lsmash_bs_get_be16( bs );
496 for( int i = 0; i < 9; i++ )
497 tkhd->matrix[i] = lsmash_bs_get_be32( bs );
498 tkhd->width = lsmash_bs_get_be32( bs );
499 tkhd->height = lsmash_bs_get_be32( bs );
500 return isom_read_leaf_box_common_last_process( file, box, level, tkhd );
503 static int isom_read_tapt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
505 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tapt )
506 return isom_read_unknown_box( file, box, parent, level );
507 ADD_BOX( tapt, isom_trak_t );
508 isom_box_common_copy( tapt, box );
509 if( isom_add_print_func( file, tapt, level ) )
510 return -1;
511 return isom_read_children( file, box, tapt, level );
514 static int isom_read_clef( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
516 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->clef )
517 return isom_read_unknown_box( file, box, parent, level );
518 ADD_BOX( clef, isom_tapt_t );
519 lsmash_bs_t *bs = file->bs;
520 clef->width = lsmash_bs_get_be32( bs );
521 clef->height = lsmash_bs_get_be32( bs );
522 return isom_read_leaf_box_common_last_process( file, box, level, clef );
525 static int isom_read_prof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
527 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->prof )
528 return isom_read_unknown_box( file, box, parent, level );
529 ADD_BOX( prof, isom_tapt_t );
530 lsmash_bs_t *bs = file->bs;
531 prof->width = lsmash_bs_get_be32( bs );
532 prof->height = lsmash_bs_get_be32( bs );
533 return isom_read_leaf_box_common_last_process( file, box, level, prof );
536 static int isom_read_enof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
538 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->enof )
539 return isom_read_unknown_box( file, box, parent, level );
540 ADD_BOX( enof, isom_tapt_t );
541 lsmash_bs_t *bs = file->bs;
542 enof->width = lsmash_bs_get_be32( bs );
543 enof->height = lsmash_bs_get_be32( bs );
544 return isom_read_leaf_box_common_last_process( file, box, level, enof );
547 static int isom_read_edts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
549 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->edts )
550 return isom_read_unknown_box( file, box, parent, level );
551 ADD_BOX( edts, isom_trak_t );
552 isom_box_common_copy( edts, box );
553 if( isom_add_print_func( file, edts, level ) )
554 return -1;
555 return isom_read_children( file, box, edts, level );
558 static int isom_read_elst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
560 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_EDTS ) || ((isom_edts_t *)parent)->elst )
561 return isom_read_unknown_box( file, box, parent, level );
562 ADD_BOX( elst, isom_edts_t );
563 lsmash_bs_t *bs = file->bs;
564 uint32_t entry_count = lsmash_bs_get_be32( bs );
565 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && elst->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
567 isom_elst_entry_t *data = lsmash_malloc( sizeof(isom_elst_entry_t) );
568 if( !data )
569 return -1;
570 if( lsmash_add_entry( elst->list, data ) )
572 lsmash_free( data );
573 return -1;
575 if( box->version == 1 )
577 data->segment_duration = lsmash_bs_get_be64( bs );
578 data->media_time = (int64_t)lsmash_bs_get_be64( bs );
580 else
582 data->segment_duration = lsmash_bs_get_be32( bs );
583 data->media_time = (int32_t)lsmash_bs_get_be32( bs );
585 data->media_rate = lsmash_bs_get_be32( bs );
587 return isom_read_leaf_box_common_last_process( file, box, level, elst );
590 static int isom_read_tref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
592 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tref )
593 return isom_read_unknown_box( file, box, parent, level );
594 ADD_BOX( tref, isom_trak_t );
595 isom_box_common_copy( tref, box );
596 if( isom_add_print_func( file, tref, level ) )
597 return -1;
598 return isom_read_children( file, box, tref, level );
601 static int isom_read_track_reference_type( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
603 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
604 return isom_read_unknown_box( file, box, parent, level );
605 isom_tref_type_t *ref = isom_add_track_reference_type( (isom_tref_t *)parent, box->type.fourcc );
606 if( !ref )
607 return -1;
608 lsmash_bs_t *bs = file->bs;
609 ref->ref_count = (box->size - lsmash_bs_count( bs ) ) / sizeof(uint32_t);
610 if( ref->ref_count )
612 ref->track_ID = lsmash_malloc( ref->ref_count * sizeof(uint32_t) );
613 if( !ref->track_ID )
615 ref->ref_count = 0;
616 return -1;
618 for( uint32_t i = 0; i < ref->ref_count; i++ )
619 ref->track_ID[i] = lsmash_bs_get_be32( bs );
621 return isom_read_leaf_box_common_last_process( file, box, level, ref );
624 static int isom_read_mdia( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
626 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->mdia )
627 return isom_read_unknown_box( file, box, parent, level );
628 ADD_BOX( mdia, isom_trak_t );
629 isom_box_common_copy( mdia, box );
630 if( isom_add_print_func( file, mdia, level ) )
631 return -1;
632 return isom_read_children( file, box, mdia, level );
635 static int isom_read_mdhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
637 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->mdhd )
638 return isom_read_unknown_box( file, box, parent, level );
639 ADD_BOX( mdhd, isom_mdia_t );
640 lsmash_bs_t *bs = file->bs;
641 if( box->version )
643 mdhd->creation_time = lsmash_bs_get_be64( bs );
644 mdhd->modification_time = lsmash_bs_get_be64( bs );
645 mdhd->timescale = lsmash_bs_get_be32( bs );
646 mdhd->duration = lsmash_bs_get_be64( bs );
648 else
650 mdhd->creation_time = lsmash_bs_get_be32( bs );
651 mdhd->modification_time = lsmash_bs_get_be32( bs );
652 mdhd->timescale = lsmash_bs_get_be32( bs );
653 mdhd->duration = lsmash_bs_get_be32( bs );
655 mdhd->language = lsmash_bs_get_be16( bs );
656 mdhd->quality = lsmash_bs_get_be16( bs );
657 return isom_read_leaf_box_common_last_process( file, box, level, mdhd );
660 static int isom_read_hdlr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
662 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
663 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
664 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META )
665 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ))
666 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) && ((isom_mdia_t *)parent)->hdlr)
667 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
668 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
669 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->hdlr) )
670 return isom_read_unknown_box( file, box, parent, level );
671 ADD_BOX( hdlr, void );
672 lsmash_bs_t *bs = file->bs;
673 hdlr->componentType = lsmash_bs_get_be32( bs );
674 hdlr->componentSubtype = lsmash_bs_get_be32( bs );
675 hdlr->componentManufacturer = lsmash_bs_get_be32( bs );
676 hdlr->componentFlags = lsmash_bs_get_be32( bs );
677 hdlr->componentFlagsMask = lsmash_bs_get_be32( bs );
678 uint64_t pos = lsmash_bs_count( bs );
679 hdlr->componentName_length = box->size - pos;
680 if( hdlr->componentName_length )
682 hdlr->componentName = lsmash_malloc( hdlr->componentName_length );
683 if( !hdlr->componentName )
684 return -1;
685 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
686 hdlr->componentName[i++] = lsmash_bs_get_byte( bs );
688 return isom_read_leaf_box_common_last_process( file, box, level, hdlr );
691 static int isom_read_minf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
693 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->minf )
694 return isom_read_unknown_box( file, box, parent, level );
695 ADD_BOX( minf, isom_mdia_t );
696 isom_box_common_copy( minf, box );
697 if( isom_add_print_func( file, minf, level ) )
698 return -1;
699 return isom_read_children( file, box, minf, level );
702 static int isom_read_vmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
704 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->vmhd )
705 return isom_read_unknown_box( file, box, parent, level );
706 ADD_BOX( vmhd, isom_minf_t );
707 lsmash_bs_t *bs = file->bs;
708 vmhd->graphicsmode = lsmash_bs_get_be16( bs );
709 for( int i = 0; i < 3; i++ )
710 vmhd->opcolor[i] = lsmash_bs_get_be16( bs );
711 return isom_read_leaf_box_common_last_process( file, box, level, vmhd );
714 static int isom_read_smhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
716 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->smhd )
717 return isom_read_unknown_box( file, box, parent, level );
718 ADD_BOX( smhd, isom_minf_t );
719 lsmash_bs_t *bs = file->bs;
720 smhd->balance = lsmash_bs_get_be16( bs );
721 smhd->reserved = lsmash_bs_get_be16( bs );
722 return isom_read_leaf_box_common_last_process( file, box, level, smhd );
725 static int isom_read_hmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
727 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->hmhd )
728 return isom_read_unknown_box( file, box, parent, level );
729 ADD_BOX( hmhd, isom_minf_t );
730 lsmash_bs_t *bs = file->bs;
731 hmhd->maxPDUsize = lsmash_bs_get_be16( bs );
732 hmhd->avgPDUsize = lsmash_bs_get_be16( bs );
733 hmhd->maxbitrate = lsmash_bs_get_be32( bs );
734 hmhd->avgbitrate = lsmash_bs_get_be32( bs );
735 hmhd->reserved = lsmash_bs_get_be32( bs );
736 return isom_read_leaf_box_common_last_process( file, box, level, hmhd );
739 static int isom_read_nmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
741 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->nmhd )
742 return isom_read_unknown_box( file, box, parent, level );
743 ADD_BOX( nmhd, isom_minf_t );
744 return isom_read_leaf_box_common_last_process( file, box, level, nmhd );
747 static int isom_read_gmhd( 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)->gmhd )
750 return isom_read_unknown_box( file, box, parent, level );
751 ADD_BOX( gmhd, isom_minf_t );
752 isom_box_common_copy( gmhd, box );
753 if( isom_add_print_func( file, gmhd, level ) )
754 return -1;
755 return isom_read_children( file, box, gmhd, level );
758 static int isom_read_gmin( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
760 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->gmin )
761 return isom_read_unknown_box( file, box, parent, level );
762 ADD_BOX( gmin, isom_gmhd_t );
763 lsmash_bs_t *bs = file->bs;
764 gmin->graphicsmode = lsmash_bs_get_be16( bs );
765 for( int i = 0; i < 3; i++ )
766 gmin->opcolor[i] = lsmash_bs_get_be16( bs );
767 gmin->balance = lsmash_bs_get_be16( bs );
768 gmin->reserved = lsmash_bs_get_be16( bs );
769 return isom_read_leaf_box_common_last_process( file, box, level, gmin );
772 static int isom_read_text( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
774 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->text )
775 return isom_read_unknown_box( file, box, parent, level );
776 ADD_BOX( text, isom_gmhd_t );
777 lsmash_bs_t *bs = file->bs;
778 for( int i = 0; i < 9; i++ )
779 text->matrix[i] = lsmash_bs_get_be32( bs );
780 return isom_read_leaf_box_common_last_process( file, box, level, text );
783 static int isom_read_dinf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
785 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
786 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
787 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
788 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->dinf)
789 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf)
790 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf) )
791 return isom_read_unknown_box( file, box, parent, level );
792 ADD_BOX( dinf, void );
793 isom_box_common_copy( dinf, box );
794 if( isom_add_print_func( file, dinf, level ) )
795 return -1;
796 return isom_read_children( file, box, dinf, level );
799 static int isom_read_dref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
801 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DINF ) || ((isom_dinf_t *)parent)->dref )
802 return isom_read_unknown_box( file, box, parent, level );
803 ADD_BOX( dref, isom_dinf_t );
804 lsmash_bs_t *bs = file->bs;
805 dref->list.entry_count = lsmash_bs_get_be32( bs );
806 isom_box_common_copy( dref, box );
807 if( isom_add_print_func( file, dref, level ) )
808 return -1;
809 return isom_read_children( file, box, dref, level );
812 static int isom_read_url( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
814 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
815 return isom_read_unknown_box( file, box, parent, level );
816 isom_dref_t *dref = (isom_dref_t *)parent;
817 if( !dref->list.head )
818 dref->list.entry_count = 0; /* discard entry_count gotten from the file */
819 isom_dref_entry_t *url = isom_add_dref_entry( dref );
820 if( !url )
821 return -1;
822 lsmash_bs_t *bs = file->bs;
823 uint64_t pos = lsmash_bs_count( bs );
824 url->location_length = box->size - pos;
825 if( url->location_length )
827 url->location = lsmash_malloc( url->location_length );
828 if( !url->location )
829 return -1;
830 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
831 url->location[i++] = lsmash_bs_get_byte( bs );
833 if( box->flags & 0x000001 )
834 url->ref_file = url->file;
835 box->parent = parent;
836 return isom_read_leaf_box_common_last_process( file, box, level, url );
839 static int isom_read_stbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
841 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->stbl )
842 return isom_read_unknown_box( file, box, parent, level );
843 ADD_BOX( stbl, isom_minf_t );
844 isom_box_common_copy( stbl, box );
845 if( isom_add_print_func( file, stbl, level ) )
846 return -1;
847 return isom_read_children( file, box, stbl, level );
850 static int isom_read_stsd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
852 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsd )
853 return isom_read_unknown_box( file, box, parent, level );
854 ADD_BOX( stsd, isom_stbl_t );
855 lsmash_bs_t *bs = file->bs;
856 stsd->entry_count = lsmash_bs_get_be32( bs );
857 isom_box_common_copy( stsd, box );
858 if( isom_add_print_func( file, stsd, level ) )
859 return -1;
860 int ret = 0;
861 uint64_t stsd_pos = lsmash_bs_count( bs );
862 for( uint32_t i = 0; i < stsd->entry_count || (stsd_pos + ISOM_BASEBOX_COMMON_SIZE) <= stsd->size; i++ )
864 ret = isom_read_box( file, box, (isom_box_t *)stsd, stsd_pos, level );
865 if( ret )
866 break;
867 stsd_pos += box->size;
868 if( stsd->size <= stsd_pos || bs->eob || bs->error )
869 break;
871 if( stsd->size < stsd_pos )
873 printf( "[stsd] box has extra bytes: %"PRId64"\n", stsd_pos - stsd->size );
874 stsd->size = stsd_pos;
876 box->size = stsd->size;
877 return ret;
880 static int isom_read_codec_specific( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
882 lsmash_bs_t *bs = file->bs;
883 uint64_t opaque_pos = lsmash_bs_count( bs );
884 uint64_t exdata_length = box->size - opaque_pos;
885 if( exdata_length > UINT32_MAX )
886 return -1;
887 uint8_t *exdata = lsmash_malloc( box->size );
888 if( !exdata )
889 return -1;
890 if( lsmash_bs_get_bytes_ex( bs, exdata_length, exdata + (uintptr_t)opaque_pos ) < 0 )
891 goto fail;
892 LSMASH_SET_BE32( &exdata[0], box->size );
893 LSMASH_SET_BE32( &exdata[4], box->type.fourcc );
894 uintptr_t i = 8;
895 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc )
897 LSMASH_SET_BE32( &exdata[8], box->type.user.fourcc );
898 memcpy( &exdata[12], box->type.user.id, 12 );
899 i += 16;
901 if( box->manager & LSMASH_FULLBOX )
903 LSMASH_SET_BYTE( &exdata[i], box->version );
904 i += 1;
905 LSMASH_SET_BE24( &exdata[i], box->flags );
906 i += 3;
908 if( i != opaque_pos )
909 goto fail;
910 if( isom_add_extension_binary( parent, box->type, LSMASH_BOX_PRECEDENCE_N, exdata, box->size ) < 0 )
911 goto fail;
912 isom_box_t *ext = (isom_box_t *)parent->extensions.tail->data;
913 box->manager |= ext->manager;
914 isom_check_box_size( file->bs, box );
915 isom_basebox_common_copy( ext, box );
916 return isom_add_print_func( file, ext, level );
917 fail:
918 lsmash_free( exdata );
919 return -1;
922 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type )
924 static struct description_alloc_table_tag
926 lsmash_codec_type_t type;
927 size_t alloc_size;
928 } description_alloc_table[160] = { { LSMASH_CODEC_TYPE_INITIALIZER, 0 } };
929 if( description_alloc_table[0].alloc_size == 0 )
931 /* Initialize the table. */
932 int i = 0;
933 #define ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( type, alloc_size ) \
934 description_alloc_table[i++] = (struct description_alloc_table_tag){ type, alloc_size }
935 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, sizeof(isom_visual_entry_t) );
936 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, sizeof(isom_visual_entry_t) );
937 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, sizeof(isom_visual_entry_t) );
938 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, sizeof(isom_visual_entry_t) );
939 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, sizeof(isom_visual_entry_t) );
940 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, sizeof(isom_visual_entry_t) );
941 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, sizeof(isom_visual_entry_t) );
942 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, sizeof(isom_visual_entry_t) );
943 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, sizeof(isom_visual_entry_t) );
944 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, sizeof(isom_visual_entry_t) );
945 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, sizeof(isom_visual_entry_t) );
946 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, sizeof(isom_visual_entry_t) );
947 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, sizeof(isom_visual_entry_t) );
948 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, sizeof(isom_visual_entry_t) );
949 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, sizeof(isom_visual_entry_t) );
950 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, sizeof(isom_visual_entry_t) );
951 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, sizeof(isom_visual_entry_t) );
952 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, sizeof(isom_visual_entry_t) );
953 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, sizeof(isom_visual_entry_t) );
954 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, sizeof(isom_visual_entry_t) );
955 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, sizeof(isom_visual_entry_t) );
956 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, sizeof(isom_visual_entry_t) );
957 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, sizeof(isom_visual_entry_t) );
958 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, sizeof(isom_visual_entry_t) );
959 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, sizeof(isom_visual_entry_t) );
960 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, sizeof(isom_visual_entry_t) );
961 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, sizeof(isom_visual_entry_t) );
962 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, sizeof(isom_visual_entry_t) );
963 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, sizeof(isom_visual_entry_t) );
964 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, sizeof(isom_visual_entry_t) );
965 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, sizeof(isom_visual_entry_t) );
966 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, sizeof(isom_visual_entry_t) );
967 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, sizeof(isom_visual_entry_t) );
968 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, sizeof(isom_visual_entry_t) );
969 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, sizeof(isom_visual_entry_t) );
970 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, sizeof(isom_visual_entry_t) );
971 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, sizeof(isom_visual_entry_t) );
972 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, sizeof(isom_visual_entry_t) );
973 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, sizeof(isom_visual_entry_t) );
974 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, sizeof(isom_visual_entry_t) );
975 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, sizeof(isom_visual_entry_t) );
976 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, sizeof(isom_visual_entry_t) );
977 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, sizeof(isom_visual_entry_t) );
978 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, sizeof(isom_visual_entry_t) );
979 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, sizeof(isom_visual_entry_t) );
980 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, sizeof(isom_visual_entry_t) );
981 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, sizeof(isom_visual_entry_t) );
982 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, sizeof(isom_visual_entry_t) );
983 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, sizeof(isom_visual_entry_t) );
984 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, sizeof(isom_visual_entry_t) );
985 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, sizeof(isom_visual_entry_t) );
986 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, sizeof(isom_visual_entry_t) );
987 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, sizeof(isom_visual_entry_t) );
988 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, sizeof(isom_visual_entry_t) );
989 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, sizeof(isom_visual_entry_t) );
990 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, sizeof(isom_visual_entry_t) );
991 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, sizeof(isom_visual_entry_t) );
992 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, sizeof(isom_visual_entry_t) );
993 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, sizeof(isom_visual_entry_t) );
994 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, sizeof(isom_visual_entry_t) );
995 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, sizeof(isom_visual_entry_t) );
996 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, sizeof(isom_visual_entry_t) );
997 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, sizeof(isom_visual_entry_t) );
998 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, sizeof(isom_visual_entry_t) );
999 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, sizeof(isom_visual_entry_t) );
1000 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, sizeof(isom_visual_entry_t) );
1001 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, sizeof(isom_visual_entry_t) );
1002 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, sizeof(isom_visual_entry_t) );
1003 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, sizeof(isom_visual_entry_t) );
1004 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, sizeof(isom_visual_entry_t) );
1005 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, sizeof(isom_visual_entry_t) );
1006 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, sizeof(isom_visual_entry_t) );
1007 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, sizeof(isom_visual_entry_t) );
1008 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, sizeof(isom_visual_entry_t) );
1009 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, sizeof(isom_visual_entry_t) );
1010 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, sizeof(isom_visual_entry_t) );
1011 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, sizeof(isom_audio_entry_t) );
1012 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, sizeof(isom_audio_entry_t) );
1013 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, sizeof(isom_audio_entry_t) );
1014 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, sizeof(isom_audio_entry_t) );
1015 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, sizeof(isom_audio_entry_t) );
1016 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, sizeof(isom_audio_entry_t) );
1017 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, sizeof(isom_audio_entry_t) );
1018 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, sizeof(isom_audio_entry_t) );
1019 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, sizeof(isom_audio_entry_t) );
1020 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, sizeof(isom_audio_entry_t) );
1021 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, sizeof(isom_audio_entry_t) );
1022 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, sizeof(isom_audio_entry_t) );
1023 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, sizeof(isom_audio_entry_t) );
1024 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, sizeof(isom_audio_entry_t) );
1025 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_RAW_AUDIO, sizeof(isom_audio_entry_t) );
1026 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, sizeof(isom_audio_entry_t) );
1027 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, sizeof(isom_audio_entry_t) );
1028 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, sizeof(isom_audio_entry_t) );
1029 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, sizeof(isom_audio_entry_t) );
1030 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, sizeof(isom_audio_entry_t) );
1031 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, sizeof(isom_audio_entry_t) );
1032 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, sizeof(isom_audio_entry_t) );
1033 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MP4A_AUDIO, sizeof(isom_audio_entry_t) );
1034 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, sizeof(isom_audio_entry_t) );
1035 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, sizeof(isom_audio_entry_t) );
1036 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, sizeof(isom_audio_entry_t) );
1037 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, sizeof(isom_audio_entry_t) );
1038 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, sizeof(isom_audio_entry_t) );
1039 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, sizeof(isom_audio_entry_t) );
1040 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, sizeof(isom_audio_entry_t) );
1041 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, sizeof(isom_audio_entry_t) );
1042 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, sizeof(isom_audio_entry_t) );
1043 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, sizeof(isom_audio_entry_t) );
1044 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, sizeof(isom_audio_entry_t) );
1045 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, sizeof(isom_audio_entry_t) );
1046 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, sizeof(isom_audio_entry_t) );
1047 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, sizeof(isom_audio_entry_t) );
1048 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, sizeof(isom_audio_entry_t) );
1049 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, sizeof(isom_audio_entry_t) );
1050 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, sizeof(isom_audio_entry_t) );
1051 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, sizeof(isom_audio_entry_t) );
1052 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, sizeof(isom_audio_entry_t) );
1053 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_RAW_AUDIO, sizeof(isom_audio_entry_t) );
1054 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, sizeof(isom_audio_entry_t) );
1055 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, sizeof(isom_audio_entry_t) );
1056 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, sizeof(isom_audio_entry_t) );
1057 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, sizeof(isom_audio_entry_t) );
1058 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, sizeof(isom_audio_entry_t) );
1059 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, sizeof(isom_audio_entry_t) );
1060 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, sizeof(isom_audio_entry_t) );
1061 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, sizeof(isom_audio_entry_t) );
1062 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, sizeof(isom_audio_entry_t) );
1063 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, sizeof(isom_audio_entry_t) );
1064 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, sizeof(isom_tx3g_entry_t) );
1065 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, sizeof(isom_qt_text_entry_t) );
1066 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, sizeof(isom_mp4s_entry_t) );
1067 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, 0 );
1068 #undef ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT
1070 for( int i = 0; description_alloc_table[i].alloc_size; i++ )
1071 if( lsmash_check_codec_type_identical( sample_type, description_alloc_table[i].type ) )
1072 return lsmash_malloc_zero( description_alloc_table[i].alloc_size );
1073 return NULL;
1076 static void *isom_add_description( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
1078 void *sample = isom_sample_description_alloc( sample_type );
1079 if( !sample )
1080 return NULL;
1081 if( lsmash_add_entry( &stsd->list, sample ) )
1083 lsmash_free( sample );
1084 return NULL;
1086 if( lsmash_add_entry( &stsd->extensions, sample ) )
1088 lsmash_remove_entry_tail( &stsd->list, lsmash_free );
1089 return NULL;
1091 ((isom_box_t *)sample)->destruct = (isom_extension_destructor_t)isom_remove_sample_description;
1092 return sample;
1095 static int isom_read_visual_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1097 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1098 return isom_read_unknown_box( file, box, parent, level );
1099 isom_visual_entry_t *visual = (isom_visual_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1100 if( !visual )
1101 return -1;
1102 lsmash_bs_t *bs = file->bs;
1103 for( int i = 0; i < 6; i++ )
1104 visual->reserved[i] = lsmash_bs_get_byte( bs );
1105 visual->data_reference_index = lsmash_bs_get_be16( bs );
1106 visual->version = lsmash_bs_get_be16( bs );
1107 visual->revision_level = lsmash_bs_get_be16( bs );
1108 visual->vendor = lsmash_bs_get_be32( bs );
1109 visual->temporalQuality = lsmash_bs_get_be32( bs );
1110 visual->spatialQuality = lsmash_bs_get_be32( bs );
1111 visual->width = lsmash_bs_get_be16( bs );
1112 visual->height = lsmash_bs_get_be16( bs );
1113 visual->horizresolution = lsmash_bs_get_be32( bs );
1114 visual->vertresolution = lsmash_bs_get_be32( bs );
1115 visual->dataSize = lsmash_bs_get_be32( bs );
1116 visual->frame_count = lsmash_bs_get_be16( bs );
1117 for( int i = 0; i < 32; i++ )
1118 visual->compressorname[i] = lsmash_bs_get_byte( bs );
1119 visual->depth = lsmash_bs_get_be16( bs );
1120 visual->color_table_ID = lsmash_bs_get_be16( bs );
1121 if( visual->color_table_ID == 0
1122 && lsmash_bs_get_pos( bs ) < box->size
1123 && isom_read_qt_color_table( bs, &visual->color_table ) )
1124 return -1;
1125 box->parent = parent;
1126 box->manager |= LSMASH_VIDEO_DESCRIPTION;
1127 isom_box_common_copy( visual, box );
1128 if( isom_add_print_func( file, visual, level ) )
1129 return -1;
1130 return isom_read_children( file, box, visual, level );
1133 static int isom_read_esds( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1135 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4V_VIDEO )
1136 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO )
1137 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_M4AE_AUDIO )
1138 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4S_SYSTEM )
1139 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1140 return isom_read_unknown_box( file, box, parent, level );
1141 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1143 box->type = QT_BOX_TYPE_ESDS;
1144 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO ) )
1145 parent->parent->type = QT_CODEC_TYPE_MP4A_AUDIO;
1147 else
1148 box->type = ISOM_BOX_TYPE_ESDS;
1149 ADD_BOX( esds, void );
1150 lsmash_bs_t *bs = file->bs;
1151 esds->ES = mp4sys_get_descriptor( bs, NULL );
1152 if( !esds->ES )
1153 return -1;
1154 return isom_read_leaf_box_common_last_process( file, box, level, esds );
1157 static int isom_read_btrt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1159 ADD_BOX( btrt, isom_visual_entry_t );
1160 lsmash_bs_t *bs = file->bs;
1161 btrt->bufferSizeDB = lsmash_bs_get_be32( bs );
1162 btrt->maxBitrate = lsmash_bs_get_be32( bs );
1163 btrt->avgBitrate = lsmash_bs_get_be32( bs );
1164 return isom_read_leaf_box_common_last_process( file, box, level, btrt );
1167 static int isom_read_glbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1169 ADD_BOX( glbl, isom_visual_entry_t );
1170 lsmash_bs_t *bs = file->bs;
1171 uint32_t header_size = box->size - ISOM_BASEBOX_COMMON_SIZE;
1172 if( header_size )
1174 glbl->header_data = lsmash_malloc( header_size );
1175 if( !glbl->header_data )
1176 return -1;
1177 for( uint32_t i = 0; i < header_size; i++ )
1178 glbl->header_data[i] = lsmash_bs_get_byte( bs );
1180 glbl->header_size = header_size;
1181 return isom_read_leaf_box_common_last_process( file, box, level, glbl );
1184 static int isom_read_clap( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1186 ADD_BOX( clap, isom_visual_entry_t );
1187 lsmash_bs_t *bs = file->bs;
1188 clap->cleanApertureWidthN = lsmash_bs_get_be32( bs );
1189 clap->cleanApertureWidthD = lsmash_bs_get_be32( bs );
1190 clap->cleanApertureHeightN = lsmash_bs_get_be32( bs );
1191 clap->cleanApertureHeightD = lsmash_bs_get_be32( bs );
1192 clap->horizOffN = lsmash_bs_get_be32( bs );
1193 clap->horizOffD = lsmash_bs_get_be32( bs );
1194 clap->vertOffN = lsmash_bs_get_be32( bs );
1195 clap->vertOffD = lsmash_bs_get_be32( bs );
1196 return isom_read_leaf_box_common_last_process( file, box, level, clap );
1199 static int isom_read_pasp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1201 ADD_BOX( pasp, isom_visual_entry_t );
1202 lsmash_bs_t *bs = file->bs;
1203 pasp->hSpacing = lsmash_bs_get_be32( bs );
1204 pasp->vSpacing = lsmash_bs_get_be32( bs );
1205 return isom_read_leaf_box_common_last_process( file, box, level, pasp );
1208 static int isom_read_colr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1210 ADD_BOX( colr, isom_visual_entry_t );
1211 lsmash_bs_t *bs = file->bs;
1212 colr->color_parameter_type = lsmash_bs_get_be32( bs );
1213 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
1214 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1216 colr->primaries_index = lsmash_bs_get_be16( bs );
1217 colr->transfer_function_index = lsmash_bs_get_be16( bs );
1218 colr->matrix_index = lsmash_bs_get_be16( bs );
1219 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1221 if( lsmash_bs_count( bs ) < box->size )
1223 uint8_t temp8 = lsmash_bs_get_byte( bs );
1224 colr->full_range_flag = (temp8 >> 7) & 0x01;
1225 colr->reserved = temp8 & 0x7f;
1227 else
1229 /* It seems this box is broken or incomplete. */
1230 box->manager |= LSMASH_INCOMPLETE_BOX;
1231 colr->full_range_flag = 0;
1232 colr->reserved = 0;
1235 else
1236 box->manager |= LSMASH_QTFF_BASE;
1238 box->type = (box->manager & LSMASH_QTFF_BASE) ? QT_BOX_TYPE_COLR : ISOM_BOX_TYPE_COLR;
1239 return isom_read_leaf_box_common_last_process( file, box, level, colr );
1242 static int isom_read_gama( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1244 ADD_BOX( gama, isom_visual_entry_t );
1245 lsmash_bs_t *bs = file->bs;
1246 gama->level = lsmash_bs_get_be32( bs );
1247 return isom_read_leaf_box_common_last_process( file, box, level, gama );
1250 static int isom_read_fiel( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1252 ADD_BOX( fiel, isom_visual_entry_t );
1253 lsmash_bs_t *bs = file->bs;
1254 fiel->fields = lsmash_bs_get_byte( bs );
1255 fiel->detail = lsmash_bs_get_byte( bs );
1256 return isom_read_leaf_box_common_last_process( file, box, level, fiel );
1259 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1261 ADD_BOX( cspc, isom_visual_entry_t );
1262 lsmash_bs_t *bs = file->bs;
1263 cspc->pixel_format = lsmash_bs_get_be32( bs );
1264 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1267 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1269 ADD_BOX( sgbt, isom_visual_entry_t );
1270 lsmash_bs_t *bs = file->bs;
1271 sgbt->significantBits = lsmash_bs_get_byte( bs );
1272 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1275 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1277 ADD_BOX( stsl, isom_visual_entry_t );
1278 lsmash_bs_t *bs = file->bs;
1279 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1280 stsl->scale_method = lsmash_bs_get_byte( bs );
1281 stsl->display_center_x = lsmash_bs_get_be16( bs );
1282 stsl->display_center_y = lsmash_bs_get_be16( bs );
1283 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1286 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1288 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1289 return isom_read_unknown_box( file, box, parent, level );
1290 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1291 if( !audio )
1292 return -1;
1293 lsmash_bs_t *bs = file->bs;
1294 for( int i = 0; i < 6; i++ )
1295 audio->reserved[i] = lsmash_bs_get_byte( bs );
1296 audio->data_reference_index = lsmash_bs_get_be16( bs );
1297 audio->version = lsmash_bs_get_be16( bs );
1298 audio->revision_level = lsmash_bs_get_be16( bs );
1299 audio->vendor = lsmash_bs_get_be32( bs );
1300 audio->channelcount = lsmash_bs_get_be16( bs );
1301 audio->samplesize = lsmash_bs_get_be16( bs );
1302 audio->compression_ID = lsmash_bs_get_be16( bs );
1303 audio->packet_size = lsmash_bs_get_be16( bs );
1304 audio->samplerate = lsmash_bs_get_be32( bs );
1305 if( audio->version == 1 )
1307 if( ((isom_stsd_t *)parent)->version == 0 )
1309 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1310 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1311 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1312 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1313 box->manager |= LSMASH_QTFF_BASE;
1315 else
1316 /* AudioSampleEntryV1 has no additional fields. */
1317 box->manager &= ~LSMASH_QTFF_BASE;
1319 else if( audio->version == 2 )
1321 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1322 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1323 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1324 audio->always7F000000 = lsmash_bs_get_be32( bs );
1325 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1326 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1327 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1328 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1329 box->manager |= LSMASH_QTFF_BASE;
1331 box->parent = parent;
1332 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1333 isom_box_common_copy( audio, box );
1334 if( isom_add_print_func( file, audio, level ) )
1335 return -1;
1336 return isom_read_children( file, box, audio, level );
1339 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1341 ADD_BOX( wave, isom_audio_entry_t );
1342 isom_box_common_copy( wave, box );
1343 if( isom_add_print_func( file, wave, level ) )
1344 return -1;
1345 return isom_read_children( file, box, wave, level );
1348 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1350 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->frma )
1351 return isom_read_unknown_box( file, box, parent, level );
1352 ADD_BOX( frma, isom_wave_t );
1353 lsmash_bs_t *bs = file->bs;
1354 frma->data_format = lsmash_bs_get_be32( bs );
1355 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1358 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1360 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->enda )
1361 return isom_read_unknown_box( file, box, parent, level );
1362 ADD_BOX( enda, isom_wave_t );
1363 lsmash_bs_t *bs = file->bs;
1364 enda->littleEndian = lsmash_bs_get_be16( bs );
1365 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1368 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1370 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->terminator )
1371 return isom_read_unknown_box( file, box, parent, level );
1372 ADD_BOX( terminator, isom_wave_t );
1373 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1376 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1378 ADD_BOX( chan, isom_audio_entry_t );
1379 lsmash_bs_t *bs = file->bs;
1380 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1381 chan->channelBitmap = lsmash_bs_get_be32( bs );
1382 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1383 if( chan->numberChannelDescriptions )
1385 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1386 if( !desc )
1387 return -1;
1388 chan->channelDescriptions = desc;
1389 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1391 desc->channelLabel = lsmash_bs_get_be32( bs );
1392 desc->channelFlags = lsmash_bs_get_be32( bs );
1393 for( int j = 0; j < 3; j++ )
1394 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1397 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1400 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1402 ADD_BOX( srat, isom_audio_entry_t );
1403 lsmash_bs_t *bs = file->bs;
1404 srat->sampling_rate = lsmash_bs_get_be32( bs );
1405 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1408 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1410 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1411 return isom_read_unknown_box( file, box, parent, level );
1412 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1413 if( !text )
1414 return -1;
1415 lsmash_bs_t *bs = file->bs;
1416 for( int i = 0; i < 6; i++ )
1417 text->reserved[i] = lsmash_bs_get_byte( bs );
1418 text->data_reference_index = lsmash_bs_get_be16( bs );
1419 text->displayFlags = lsmash_bs_get_be32( bs );
1420 text->textJustification = lsmash_bs_get_be32( bs );
1421 for( int i = 0; i < 3; i++ )
1422 text->bgColor[i] = lsmash_bs_get_be16( bs );
1423 text->top = lsmash_bs_get_be16( bs );
1424 text->left = lsmash_bs_get_be16( bs );
1425 text->bottom = lsmash_bs_get_be16( bs );
1426 text->right = lsmash_bs_get_be16( bs );
1427 text->scrpStartChar = lsmash_bs_get_be32( bs );
1428 text->scrpHeight = lsmash_bs_get_be16( bs );
1429 text->scrpAscent = lsmash_bs_get_be16( bs );
1430 text->scrpFont = lsmash_bs_get_be16( bs );
1431 text->scrpFace = lsmash_bs_get_be16( bs );
1432 text->scrpSize = lsmash_bs_get_be16( bs );
1433 for( int i = 0; i < 3; i++ )
1434 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1435 text->font_name_length = lsmash_bs_get_byte( bs );
1436 if( text->font_name_length )
1438 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1439 if( !text->font_name )
1440 return -1;
1441 for( uint8_t i = 0; i < text->font_name_length; i++ )
1442 text->font_name[i] = lsmash_bs_get_byte( bs );
1443 text->font_name[text->font_name_length] = '\0';
1445 box->parent = parent;
1446 isom_box_common_copy( text, box );
1447 if( isom_add_print_func( file, text, level ) )
1448 return -1;
1449 return isom_read_children( file, box, text, level );
1452 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1454 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1455 return isom_read_unknown_box( file, box, parent, level );
1456 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1457 if( !tx3g )
1458 return -1;
1459 lsmash_bs_t *bs = file->bs;
1460 for( int i = 0; i < 6; i++ )
1461 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1462 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1463 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1464 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1465 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1466 for( int i = 0; i < 4; i++ )
1467 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1468 tx3g->top = lsmash_bs_get_be16( bs );
1469 tx3g->left = lsmash_bs_get_be16( bs );
1470 tx3g->bottom = lsmash_bs_get_be16( bs );
1471 tx3g->right = lsmash_bs_get_be16( bs );
1472 tx3g->startChar = lsmash_bs_get_be16( bs );
1473 tx3g->endChar = lsmash_bs_get_be16( bs );
1474 tx3g->font_ID = lsmash_bs_get_be16( bs );
1475 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1476 tx3g->font_size = lsmash_bs_get_byte( bs );
1477 for( int i = 0; i < 4; i++ )
1478 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1479 box->parent = parent;
1480 isom_box_common_copy( tx3g, box );
1481 if( isom_add_print_func( file, tx3g, level ) )
1482 return -1;
1483 return isom_read_children( file, box, tx3g, level );
1486 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1488 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1489 || ((isom_tx3g_entry_t *)parent)->ftab )
1490 return isom_read_unknown_box( file, box, parent, level );
1491 ADD_BOX( ftab, isom_tx3g_entry_t );
1492 lsmash_bs_t *bs = file->bs;
1493 uint32_t entry_count = lsmash_bs_get_be16( bs );
1494 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1496 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1497 if( !data )
1498 return -1;
1499 if( lsmash_add_entry( ftab->list, data ) )
1501 lsmash_free( data );
1502 return -1;
1504 data->font_ID = lsmash_bs_get_be16( bs );
1505 data->font_name_length = lsmash_bs_get_byte( bs );
1506 if( data->font_name_length )
1508 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1509 if( !data->font_name )
1510 return -1;
1511 for( uint8_t i = 0; i < data->font_name_length; i++ )
1512 data->font_name[i] = lsmash_bs_get_byte( bs );
1513 data->font_name[data->font_name_length] = '\0';
1516 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1519 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1521 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1522 return isom_read_unknown_box( file, box, parent, level );
1523 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1524 if( !mp4s )
1525 return -1;
1526 lsmash_bs_t *bs = file->bs;
1527 for( int i = 0; i < 6; i++ )
1528 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1529 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1530 box->parent = parent;
1531 isom_box_common_copy( mp4s, box );
1532 if( isom_add_print_func( file, mp4s, level ) )
1533 return -1;
1534 return isom_read_children( file, box, mp4s, level );
1537 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1539 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stts )
1540 return isom_read_unknown_box( file, box, parent, level );
1541 ADD_BOX( stts, isom_stbl_t );
1542 lsmash_bs_t *bs = file->bs;
1543 uint32_t entry_count = lsmash_bs_get_be32( bs );
1544 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1546 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1547 if( !data )
1548 return -1;
1549 if( lsmash_add_entry( stts->list, data ) )
1551 lsmash_free( data );
1552 return -1;
1554 data->sample_count = lsmash_bs_get_be32( bs );
1555 data->sample_delta = lsmash_bs_get_be32( bs );
1557 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1560 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1562 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->ctts )
1563 return isom_read_unknown_box( file, box, parent, level );
1564 ADD_BOX( ctts, isom_stbl_t );
1565 lsmash_bs_t *bs = file->bs;
1566 uint32_t entry_count = lsmash_bs_get_be32( bs );
1567 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1569 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1570 if( !data )
1571 return -1;
1572 if( lsmash_add_entry( ctts->list, data ) )
1574 lsmash_free( data );
1575 return -1;
1577 data->sample_count = lsmash_bs_get_be32( bs );
1578 data->sample_offset = lsmash_bs_get_be32( bs );
1580 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1583 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1585 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->cslg )
1586 return isom_read_unknown_box( file, box, parent, level );
1587 ADD_BOX( cslg, isom_stbl_t );
1588 lsmash_bs_t *bs = file->bs;
1589 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1590 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1591 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1592 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1593 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1594 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1597 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1599 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stss )
1600 return isom_read_unknown_box( file, box, parent, level );
1601 ADD_BOX( stss, isom_stbl_t );
1602 lsmash_bs_t *bs = file->bs;
1603 uint32_t entry_count = lsmash_bs_get_be32( bs );
1604 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1606 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1607 if( !data )
1608 return -1;
1609 if( lsmash_add_entry( stss->list, data ) )
1611 lsmash_free( data );
1612 return -1;
1614 data->sample_number = lsmash_bs_get_be32( bs );
1616 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1619 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1621 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stps )
1622 return isom_read_unknown_box( file, box, parent, level );
1623 ADD_BOX( stps, isom_stbl_t );
1624 lsmash_bs_t *bs = file->bs;
1625 uint32_t entry_count = lsmash_bs_get_be32( bs );
1626 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1628 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1629 if( !data )
1630 return -1;
1631 if( lsmash_add_entry( stps->list, data ) )
1633 lsmash_free( data );
1634 return -1;
1636 data->sample_number = lsmash_bs_get_be32( bs );
1638 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1641 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1643 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1644 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1645 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && ((isom_stbl_t *)parent)->sdtp)
1646 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && ((isom_traf_t *)parent)->sdtp))
1647 return isom_read_unknown_box( file, box, parent, level );
1648 ADD_BOX( sdtp, isom_box_t );
1649 lsmash_bs_t *bs = file->bs;
1650 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1652 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1653 if( !data )
1654 return -1;
1655 if( lsmash_add_entry( sdtp->list, data ) )
1657 lsmash_free( data );
1658 return -1;
1660 uint8_t temp = lsmash_bs_get_byte( bs );
1661 data->is_leading = (temp >> 6) & 0x3;
1662 data->sample_depends_on = (temp >> 4) & 0x3;
1663 data->sample_is_depended_on = (temp >> 2) & 0x3;
1664 data->sample_has_redundancy = temp & 0x3;
1666 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1669 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1671 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsc )
1672 return isom_read_unknown_box( file, box, parent, level );
1673 ADD_BOX( stsc, isom_stbl_t );
1674 lsmash_bs_t *bs = file->bs;
1675 uint32_t entry_count = lsmash_bs_get_be32( bs );
1676 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1678 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1679 if( !data )
1680 return -1;
1681 if( lsmash_add_entry( stsc->list, data ) )
1683 lsmash_free( data );
1684 return -1;
1686 data->first_chunk = lsmash_bs_get_be32( bs );
1687 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1688 data->sample_description_index = lsmash_bs_get_be32( bs );
1690 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1693 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1695 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsz )
1696 return isom_read_unknown_box( file, box, parent, level );
1697 ADD_BOX( stsz, isom_stbl_t );
1698 lsmash_bs_t *bs = file->bs;
1699 stsz->sample_size = lsmash_bs_get_be32( bs );
1700 stsz->sample_count = lsmash_bs_get_be32( bs );
1701 uint64_t pos = lsmash_bs_count( bs );
1702 if( pos < box->size )
1704 stsz->list = lsmash_create_entry_list();
1705 if( !stsz->list )
1706 return -1;
1707 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1709 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1710 if( !data )
1711 return -1;
1712 if( lsmash_add_entry( stsz->list, data ) )
1714 lsmash_free( data );
1715 return -1;
1717 data->entry_size = lsmash_bs_get_be32( bs );
1720 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1723 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1725 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stco )
1726 return isom_read_unknown_box( file, box, parent, level );
1727 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1728 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1729 isom_stco_t *stco = is_stco
1730 ? isom_add_stco( (isom_stbl_t *)parent )
1731 : isom_add_co64( (isom_stbl_t *)parent );
1732 if( !stco )
1733 return -1;
1734 lsmash_bs_t *bs = file->bs;
1735 uint32_t entry_count = lsmash_bs_get_be32( bs );
1736 if( is_stco )
1737 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1739 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1740 if( !data )
1741 return -1;
1742 if( lsmash_add_entry( stco->list, data ) )
1744 lsmash_free( data );
1745 return -1;
1747 data->chunk_offset = lsmash_bs_get_be32( bs );
1749 else
1751 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1753 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1754 if( !data )
1755 return -1;
1756 if( lsmash_add_entry( stco->list, data ) )
1758 lsmash_free( data );
1759 return -1;
1761 data->chunk_offset = lsmash_bs_get_be64( bs );
1764 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1767 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1769 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1770 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1771 return isom_read_unknown_box( file, box, parent, level );
1772 ADD_BOX( sgpd, void );
1773 lsmash_bs_t *bs = file->bs;
1774 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1775 if( box->version == 1 )
1776 sgpd->default_length = lsmash_bs_get_be32( bs );
1777 uint32_t entry_count = lsmash_bs_get_be32( bs );
1778 switch( sgpd->grouping_type )
1780 case ISOM_GROUP_TYPE_RAP :
1782 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1784 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1785 if( !data )
1786 return -1;
1787 if( lsmash_add_entry( sgpd->list, data ) )
1789 lsmash_free( data );
1790 return -1;
1792 memset( data, 0, sizeof(isom_rap_entry_t) );
1793 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1794 if( box->version == 1 && !sgpd->default_length )
1795 data->description_length = lsmash_bs_get_be32( bs );
1796 else
1798 uint8_t temp = lsmash_bs_get_byte( bs );
1799 data->num_leading_samples_known = (temp >> 7) & 0x01;
1800 data->num_leading_samples = temp & 0x7f;
1803 break;
1805 case ISOM_GROUP_TYPE_ROLL :
1806 case ISOM_GROUP_TYPE_PROL :
1808 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1810 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1811 if( !data )
1812 return -1;
1813 if( lsmash_add_entry( sgpd->list, data ) )
1815 lsmash_free( data );
1816 return -1;
1818 memset( data, 0, sizeof(isom_roll_entry_t) );
1819 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1820 if( box->version == 1 && !sgpd->default_length )
1821 data->description_length = lsmash_bs_get_be32( bs );
1822 else
1823 data->roll_distance = lsmash_bs_get_be16( bs );
1825 break;
1827 default :
1828 break;
1830 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1833 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1835 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1836 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1837 return isom_read_unknown_box( file, box, parent, level );
1838 ADD_BOX( sbgp, void );
1839 lsmash_bs_t *bs = file->bs;
1840 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1841 if( box->version == 1 )
1842 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1843 uint32_t entry_count = lsmash_bs_get_be32( bs );
1844 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1846 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1847 if( !data )
1848 return -1;
1849 if( lsmash_add_entry( sbgp->list, data ) )
1851 lsmash_free( data );
1852 return -1;
1854 data->sample_count = lsmash_bs_get_be32( bs );
1855 data->group_description_index = lsmash_bs_get_be32( bs );
1857 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1860 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1862 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1863 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1864 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->udta)
1865 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->udta) )
1866 return isom_read_unknown_box( file, box, parent, level );
1867 ADD_BOX( udta, void );
1868 isom_box_common_copy( udta, box );
1869 if( isom_add_print_func( file, udta, level ) )
1870 return -1;
1871 return isom_read_children( file, box, udta, level );
1874 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1876 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->chpl )
1877 return isom_read_unknown_box( file, box, parent, level );
1878 ADD_BOX( chpl, isom_udta_t );
1879 lsmash_bs_t *bs = file->bs;
1880 uint32_t entry_count;
1881 if( box->version == 1 )
1883 chpl->unknown = lsmash_bs_get_byte( bs );
1884 entry_count = lsmash_bs_get_be32( bs );
1886 else
1887 entry_count = lsmash_bs_get_byte( bs );
1888 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1890 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1891 if( !data )
1892 return -1;
1893 if( lsmash_add_entry( chpl->list, data ) )
1895 lsmash_free( data );
1896 return -1;
1898 data->start_time = lsmash_bs_get_be64( bs );
1899 data->chapter_name_length = lsmash_bs_get_byte( bs );
1900 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1901 if( !data->chapter_name )
1903 lsmash_free( data );
1904 return -1;
1906 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1907 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1908 data->chapter_name[data->chapter_name_length] = '\0';
1910 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1913 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1915 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvex )
1916 return isom_read_unknown_box( file, box, parent, level );
1917 ADD_BOX( mvex, isom_moov_t );
1918 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1919 isom_box_common_copy( mvex, box );
1920 if( isom_add_print_func( file, mvex, level ) )
1921 return -1;
1922 return isom_read_children( file, box, mvex, level );
1925 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1927 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) || ((isom_mvex_t *)parent)->mehd )
1928 return isom_read_unknown_box( file, box, parent, level );
1929 ADD_BOX( mehd, isom_mvex_t );
1930 lsmash_bs_t *bs = file->bs;
1931 if( box->version == 1 )
1932 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1933 else
1934 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1935 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1938 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1940 uint32_t temp = lsmash_bs_get_be32( bs );
1941 isom_sample_flags_t flags;
1942 flags.reserved = (temp >> 28) & 0xf;
1943 flags.is_leading = (temp >> 26) & 0x3;
1944 flags.sample_depends_on = (temp >> 24) & 0x3;
1945 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1946 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1947 flags.sample_padding_value = (temp >> 17) & 0x7;
1948 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1949 flags.sample_degradation_priority = temp & 0xffff;
1950 return flags;
1953 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1955 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
1956 return isom_read_unknown_box( file, box, parent, level );
1957 ADD_BOX( trex, isom_mvex_t );
1958 box->parent = parent;
1959 lsmash_bs_t *bs = file->bs;
1960 trex->track_ID = lsmash_bs_get_be32( bs );
1961 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
1962 trex->default_sample_duration = lsmash_bs_get_be32( bs );
1963 trex->default_sample_size = lsmash_bs_get_be32( bs );
1964 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
1965 return isom_read_leaf_box_common_last_process( file, box, level, trex );
1968 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1970 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
1971 return isom_read_unknown_box( file, box, parent, level );
1972 ADD_BOX( moof, lsmash_file_t );
1973 box->parent = parent;
1974 isom_box_common_copy( moof, box );
1975 if( isom_add_print_func( file, moof, level ) )
1976 return -1;
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 if( isom_add_print_func( file, traf, level ) )
1998 return -1;
1999 return isom_read_children( file, box, traf, level );
2002 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2004 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfhd )
2005 return isom_read_unknown_box( file, box, parent, level );
2006 ADD_BOX( tfhd, isom_traf_t );
2007 lsmash_bs_t *bs = file->bs;
2008 tfhd->track_ID = lsmash_bs_get_be32( bs );
2009 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2010 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2011 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2012 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2013 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2014 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2017 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2019 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfdt )
2020 return isom_read_unknown_box( file, box, parent, level );
2021 ADD_BOX( tfdt, isom_traf_t );
2022 lsmash_bs_t *bs = file->bs;
2023 if( box->version == 1 )
2024 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2025 else
2026 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2027 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2030 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2032 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2033 return isom_read_unknown_box( file, box, parent, level );
2034 ADD_BOX( trun, isom_traf_t );
2035 box->parent = parent;
2036 lsmash_bs_t *bs = file->bs;
2037 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2038 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2039 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2040 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2041 has_optional_rows &= box->flags;
2042 trun->sample_count = lsmash_bs_get_be32( bs );
2043 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2044 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2045 if( trun->sample_count && has_optional_rows )
2047 trun->optional = lsmash_create_entry_list();
2048 if( !trun->optional )
2049 return -1;
2050 for( uint32_t i = 0; i < trun->sample_count; i++ )
2052 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2053 if( !data )
2054 return -1;
2055 if( lsmash_add_entry( trun->optional, data ) )
2057 lsmash_free( data );
2058 return -1;
2060 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2061 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2062 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2063 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2066 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2069 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2071 if( file->fake_file_mode )
2072 return isom_read_unknown_box( file, box, parent, level );
2073 isom_box_t *skip = lsmash_malloc_zero( sizeof(isom_box_t) );
2074 if( !skip )
2075 return -1;
2076 isom_skip_box_rest( file->bs, box );
2077 box->manager |= LSMASH_ABSENT_IN_FILE;
2078 isom_box_common_copy( skip, box );
2079 if( isom_add_print_func( file, skip, level ) < 0 )
2081 lsmash_free( skip );
2082 return -1;
2084 return 0;
2087 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2089 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2090 return isom_read_unknown_box( file, box, parent, level );
2091 isom_box_t *mdat = lsmash_malloc_zero( sizeof(isom_box_t) );
2092 if( !mdat )
2093 return -1;
2094 isom_skip_box_rest( file->bs, box );
2095 box->manager |= LSMASH_ABSENT_IN_FILE;
2096 file->flags |= LSMASH_FILE_MODE_MEDIA;
2097 isom_box_common_copy( mdat, box );
2098 if( isom_add_print_func( file, mdat, level ) < 0 )
2100 lsmash_free( mdat );
2101 return -1;
2103 return 0;
2106 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2108 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2109 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2110 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2111 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2112 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && ((lsmash_file_t *)parent)->meta)
2113 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->meta)
2114 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->meta)
2115 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && ((isom_udta_t *)parent)->meta) )
2116 return isom_read_unknown_box( file, box, parent, level );
2117 ADD_BOX( meta, void );
2118 isom_box_common_copy( meta, box );
2119 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2120 if( is_qtff )
2122 box->manager |= LSMASH_QTFF_BASE;
2123 meta->manager |= LSMASH_QTFF_BASE;
2125 if( isom_add_print_func( file, meta, level ) )
2126 return -1;
2127 return isom_read_children( file, box, meta, level );
2130 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2132 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2133 || ((isom_meta_t *)parent)->keys )
2134 return isom_read_unknown_box( file, box, parent, level );
2135 ADD_BOX( keys, isom_meta_t );
2136 lsmash_bs_t *bs = file->bs;
2137 uint32_t entry_count = lsmash_bs_get_be32( bs );
2138 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2140 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2141 if( !data )
2142 return -1;
2143 if( lsmash_add_entry( keys->list, data ) )
2145 lsmash_free( data );
2146 return -1;
2148 data->key_size = lsmash_bs_get_be32( bs );
2149 data->key_namespace = lsmash_bs_get_be32( bs );
2150 if( data->key_size > 8 )
2152 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2153 if( !data->key_value )
2154 return -1;
2156 else
2157 data->key_value = NULL;
2159 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2162 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2164 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2165 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2166 || ((isom_meta_t *)parent)->ilst )
2167 return isom_read_unknown_box( file, box, parent, level );
2168 ADD_BOX( ilst, isom_meta_t );
2169 isom_box_common_copy( ilst, box );
2170 if( isom_add_print_func( file, ilst, level ) )
2171 return -1;
2172 return isom_read_children( file, box, ilst, level );
2175 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2177 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2178 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2179 return isom_read_unknown_box( file, box, parent, level );
2180 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2181 if( !metaitem )
2182 return -1;
2183 box->parent = parent;
2184 isom_box_common_copy( metaitem, box );
2185 if( isom_add_print_func( file, metaitem, level ) )
2186 return -1;
2187 return isom_read_children( file, box, metaitem, level );
2190 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2192 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->mean )
2193 return isom_read_unknown_box( file, box, parent, level );
2194 ADD_BOX( mean, isom_metaitem_t );
2195 lsmash_bs_t *bs = file->bs;
2196 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2197 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2198 if( !mean->meaning_string )
2199 return -1;
2200 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2203 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2205 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->name )
2206 return isom_read_unknown_box( file, box, parent, level );
2207 ADD_BOX( name, isom_metaitem_t );
2208 lsmash_bs_t *bs = file->bs;
2209 name->name_length = box->size - lsmash_bs_count( bs );
2210 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2211 if( !name->name )
2212 return -1;
2213 return isom_read_leaf_box_common_last_process( file, box, level, name );
2216 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2218 if( ((isom_metaitem_t *)parent)->data )
2219 return isom_read_unknown_box( file, box, parent, level );
2220 ADD_BOX( data, isom_metaitem_t );
2221 lsmash_bs_t *bs = file->bs;
2222 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2223 data->reserved = lsmash_bs_get_be16( bs );
2224 data->type_set_identifier = lsmash_bs_get_byte( bs );
2225 data->type_code = lsmash_bs_get_byte( bs );
2226 data->the_locale = lsmash_bs_get_be32( bs );
2227 if( data->value_length )
2229 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2230 if( !data->value )
2231 return -1;
2233 return isom_read_leaf_box_common_last_process( file, box, level, data );
2236 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2238 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->WLOC )
2239 return isom_read_unknown_box( file, box, parent, level );
2240 ADD_BOX( WLOC, isom_udta_t );
2241 lsmash_bs_t *bs = file->bs;
2242 WLOC->x = lsmash_bs_get_be16( bs );
2243 WLOC->y = lsmash_bs_get_be16( bs );
2244 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2247 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2249 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->LOOP )
2250 return isom_read_unknown_box( file, box, parent, level );
2251 ADD_BOX( LOOP, isom_udta_t );
2252 lsmash_bs_t *bs = file->bs;
2253 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2254 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2257 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2259 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->SelO )
2260 return isom_read_unknown_box( file, box, parent, level );
2261 ADD_BOX( SelO, isom_udta_t );
2262 lsmash_bs_t *bs = file->bs;
2263 SelO->selection_only = lsmash_bs_get_byte( bs );
2264 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2267 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2269 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->AllF )
2270 return isom_read_unknown_box( file, box, parent, level );
2271 ADD_BOX( AllF, isom_udta_t );
2272 lsmash_bs_t *bs = file->bs;
2273 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2274 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2277 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2279 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2280 return isom_read_unknown_box( file, box, parent, level );
2281 ADD_BOX( cprt, isom_udta_t );
2282 box->parent = parent;
2283 lsmash_bs_t *bs = file->bs;
2284 cprt->language = lsmash_bs_get_be16( bs );
2285 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2286 if( cprt->notice_length )
2288 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2289 if( !cprt->notice )
2291 cprt->notice_length = 0;
2292 return -1;
2295 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2298 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2300 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->mfra )
2301 return isom_read_unknown_box( file, box, parent, level );
2302 ADD_BOX( mfra, lsmash_file_t );
2303 isom_box_common_copy( mfra, box );
2304 if( isom_add_print_func( file, mfra, level ) )
2305 return -1;
2306 return isom_read_children( file, box, mfra, level );
2309 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2311 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2312 return isom_read_unknown_box( file, box, parent, level );
2313 ADD_BOX( tfra, isom_mfra_t );
2314 box->parent = parent;
2315 lsmash_bs_t *bs = file->bs;
2316 tfra->track_ID = lsmash_bs_get_be32( bs );
2317 uint32_t temp = lsmash_bs_get_be32( bs );
2318 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2319 tfra->reserved = (temp >> 6) & 0x3ffffff;
2320 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2321 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2322 tfra->length_size_of_sample_num = temp & 0x3;
2323 if( tfra->number_of_entry )
2325 tfra->list = lsmash_create_entry_list();
2326 if( !tfra->list )
2327 return -1;
2328 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2330 lsmash_bs_get_byte_to_64,
2331 lsmash_bs_get_be16_to_64,
2332 lsmash_bs_get_be24_to_64,
2333 lsmash_bs_get_be32_to_64,
2334 lsmash_bs_get_be64
2336 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2337 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2338 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2339 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2340 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2341 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2343 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2344 if( !data )
2345 return -1;
2346 if( lsmash_add_entry( tfra->list, data ) )
2348 lsmash_free( data );
2349 return -1;
2351 data->time = bs_put_time ( bs );
2352 data->moof_offset = bs_put_moof_offset ( bs );
2353 data->traf_number = bs_put_traf_number ( bs );
2354 data->trun_number = bs_put_trun_number ( bs );
2355 data->sample_number = bs_put_sample_number( bs );
2358 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2361 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2363 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) || ((isom_mfra_t *)parent)->mfro )
2364 return isom_read_unknown_box( file, box, parent, level );
2365 ADD_BOX( mfro, isom_mfra_t );
2366 lsmash_bs_t *bs = file->bs;
2367 mfro->length = lsmash_bs_get_be32( bs );
2368 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2371 static inline void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2373 if( !bs->unseekable )
2374 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2375 else
2376 lsmash_bs_skip_bytes_64( bs, size );
2379 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2381 lsmash_bs_t *bs = file->bs;
2382 /* Skip extra bytes of the parent box if any. */
2383 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2385 uint64_t extra_bytes = parent->size - parent_pos;
2386 isom_read_skip_extra_bytes( bs, extra_bytes );
2387 /* This is not the size of a box but makes sense in isom_read_children(). */
2388 box->size = extra_bytes;
2389 return 1;
2391 /* Check if the size is valid or not. */
2392 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2394 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2395 if( size > 1
2396 && size < ISOM_BASEBOX_COMMON_SIZE )
2398 /* It seems we are still within the box considered as previous.
2399 * Skip bytes up to the next box. */
2400 isom_read_skip_extra_bytes( bs, parent->size - parent_pos );
2401 box->size = 0;
2402 return 1;
2404 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2405 size = lsmash_bs_show_be64( bs, 8 );
2406 if( size == 0 && parent != (isom_box_t *)file )
2408 /* Check if this box is actually the last box or not. */
2409 size = parent->size - parent_pos;
2410 uint64_t extra_bytes;
2411 if( !bs->unseekable )
2412 extra_bytes = bs->written - lsmash_bs_get_stream_pos( bs );
2413 else
2415 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2416 while( size < extra_bytes )
2418 int ret = lsmash_bs_read( bs, 1 );
2419 if( bs->eof || ret < 0 )
2420 break;
2421 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2424 if( size != extra_bytes )
2426 /* This is not the size of the last box.
2427 * It seems we are still within the box considered as previous.
2428 * Skip bytes up to the next box. */
2429 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2430 box->size = 0;
2431 return 1;
2435 return 0;
2438 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2440 assert( parent && parent->root && parent->file );
2441 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2442 return 0;
2443 memset( box, 0, sizeof(isom_box_t) );
2444 box->root = parent->root;
2445 box->file = parent->file;
2446 box->parent = parent;
2447 lsmash_bs_t *bs = file->bs;
2448 int ret = isom_bs_read_box_common( bs, box );
2449 if( !!ret )
2450 return ret; /* return if reached EOF */
2451 ++level;
2452 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2453 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2454 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2456 /* Check whether CODEC is RAW Video/Audio encapsulated in QTFF. */
2457 if( box->type.fourcc == LSMASH_CODEC_TYPE_RAW.fourcc )
2459 if( ((isom_minf_t *)parent->parent->parent)->vmhd )
2461 form_box_type_func = lsmash_form_qtff_box_type;
2462 reader_func = isom_read_visual_description;
2464 else if( ((isom_minf_t *)parent->parent->parent)->smhd )
2466 form_box_type_func = lsmash_form_qtff_box_type;
2467 reader_func = isom_read_audio_description;
2469 goto read_box;
2471 static struct description_reader_table_tag
2473 lsmash_compact_box_type_t fourcc;
2474 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2475 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2476 } description_reader_table[160] = { { 0, NULL, NULL } };
2477 if( !description_reader_table[0].reader_func )
2479 /* Initialize the table. */
2480 int i = 0;
2481 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2482 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2483 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2484 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2485 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2486 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2487 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2488 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2489 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2490 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2491 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2492 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2493 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2494 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2495 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2496 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2497 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2498 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2499 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2500 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2501 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2502 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2503 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2504 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2505 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2506 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2507 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2508 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2509 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2510 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2511 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2512 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2513 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2514 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2515 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2516 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2517 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2518 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2519 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2520 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2521 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2522 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2523 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2524 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2525 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2526 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2527 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2528 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2529 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2530 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2531 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2532 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2533 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2534 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2535 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2549 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2551 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2579 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type, isom_read_audio_description );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type, isom_read_qt_text_description );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type, isom_read_tx3g_description );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type, isom_read_mp4s_description );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL, NULL );
2613 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2615 for( int i = 0; description_reader_table[i].reader_func; i++ )
2616 if( box->type.fourcc == description_reader_table[i].fourcc )
2618 form_box_type_func = description_reader_table[i].form_box_type_func;
2619 reader_func = description_reader_table[i].reader_func;
2620 goto read_box;
2622 goto read_box;
2624 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2626 form_box_type_func = lsmash_form_qtff_box_type;
2627 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2628 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2629 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2630 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2631 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2632 else reader_func = isom_read_codec_specific;
2633 goto read_box;
2635 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2637 form_box_type_func = lsmash_form_iso_box_type;
2638 reader_func = isom_read_track_reference_type;
2639 goto read_box;
2641 static struct box_reader_table_tag
2643 lsmash_compact_box_type_t fourcc;
2644 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2645 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2646 } box_reader_table[128] = { { 0, NULL, NULL } };
2647 if( !box_reader_table[0].reader_func )
2649 /* Initialize the table. */
2650 int i = 0;
2651 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2652 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2653 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2654 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2655 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2656 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2657 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2658 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2659 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2660 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2661 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2662 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2663 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2664 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2665 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2666 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2667 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2668 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2669 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2670 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2671 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2672 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2673 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2674 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2675 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2676 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2677 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2678 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2679 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2680 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2681 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2682 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2683 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL, lsmash_form_iso_box_type, isom_read_url );
2684 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2685 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2686 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2687 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2688 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2689 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2690 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2691 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2692 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2693 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2694 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2695 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2696 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2697 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2698 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2699 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2700 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2701 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2702 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2703 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2704 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2705 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2706 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2707 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2708 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2709 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2710 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2711 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2712 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2713 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2714 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2715 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2716 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2717 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2718 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2719 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2720 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2721 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2722 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2724 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2726 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2727 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2728 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2729 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2730 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2731 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2732 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2733 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2734 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2735 #undef ADD_BOX_READER_TABLE_ELEMENT
2737 for( int i = 0; box_reader_table[i].reader_func; i++ )
2738 if( box->type.fourcc == box_reader_table[i].fourcc )
2740 form_box_type_func = box_reader_table[i].form_box_type_func;
2741 reader_func = box_reader_table[i].reader_func;
2742 goto read_box;
2744 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2746 if( lsmash_bs_is_end ( bs, 3 ) == 0
2747 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2748 form_box_type_func = lsmash_form_iso_box_type;
2749 else
2750 form_box_type_func = lsmash_form_qtff_box_type;
2751 reader_func = isom_read_meta;
2752 goto read_box;
2754 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2756 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2757 form_box_type_func = lsmash_form_iso_box_type;
2758 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2759 form_box_type_func = lsmash_form_qtff_box_type;
2760 if( form_box_type_func )
2762 reader_func = isom_read_ilst;
2763 goto read_box;
2766 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2767 form_box_type_func = lsmash_form_iso_box_type;
2768 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2769 form_box_type_func = lsmash_form_qtff_box_type;
2770 if( form_box_type_func )
2772 reader_func = isom_read_metaitem;
2773 goto read_box;
2775 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2777 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2778 reader_func = isom_read_mean;
2779 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2780 reader_func = isom_read_name;
2781 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2782 reader_func = isom_read_data;
2783 if( reader_func )
2785 form_box_type_func = lsmash_form_iso_box_type;
2786 goto read_box;
2789 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2791 /* Avoid confusing udta.cprt with ilst.cprt. */
2792 form_box_type_func = lsmash_form_iso_box_type;
2793 reader_func = isom_read_cprt;
2794 goto read_box;
2796 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2798 static struct codec_specific_marker_table_tag
2800 lsmash_compact_box_type_t fourcc;
2801 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2802 } codec_specific_marker_table[16] = { { 0, NULL } };
2803 if( !codec_specific_marker_table[0].form_box_type_func )
2805 /* Initialize the table. */
2806 int i = 0;
2807 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2808 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2809 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type );
2810 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type );
2811 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type );
2812 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type );
2813 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type );
2814 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type );
2815 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type );
2816 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type );
2817 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type );
2818 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2819 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2821 for( int i = 0; codec_specific_marker_table[i].form_box_type_func; i++ )
2822 if( box->type.fourcc == codec_specific_marker_table[i].fourcc )
2824 form_box_type_func = codec_specific_marker_table[i].form_box_type_func;
2825 break;
2827 reader_func = isom_read_codec_specific;
2829 read_box:
2830 if( form_box_type_func )
2831 box->type = form_box_type_func( box->type.fourcc );
2832 if( isom_read_fullbox_common_extension( bs, box ) )
2833 return -1;
2834 return reader_func
2835 ? reader_func( file, box, parent, level )
2836 : isom_read_unknown_box( file, box, parent, level );
2839 int isom_read_file( lsmash_file_t *file )
2841 lsmash_bs_t *bs = file->bs;
2842 if( !bs )
2843 return -1;
2844 /* Reset the counter so that we can use it to get position within the box. */
2845 lsmash_bs_reset_counter( bs );
2846 if( file->flags & LSMASH_FILE_MODE_DUMP )
2848 file->print = lsmash_create_entry_list();
2849 if( !file->print )
2850 return -1;
2852 file->size = UINT64_MAX;
2853 isom_box_t box;
2854 int ret = isom_read_children( file, &box, file, 0 );
2855 file->size = box.size;
2856 lsmash_bs_empty( bs );
2857 bs->error = 0; /* Clear error flag. */
2858 if( ret < 0 )
2859 return ret;
2860 return isom_check_compatibility( file );