read: Skip weird extra bytes of 'chan' box.
[L-SMASH.git] / core / read.c
bloba7d9788816a1d25ada681a8dc53674eb98aaa9fe
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 LSMASH_ERR_INVALID_DATA;
220 isom_unknown_box_t *unknown = lsmash_malloc_zero( sizeof(isom_unknown_box_t) );
221 if( !unknown )
222 return LSMASH_ERR_MEMORY_ALLOC;
223 if( lsmash_add_entry( &parent->extensions, unknown ) < 0 )
225 lsmash_free( unknown );
226 return LSMASH_ERR_MEMORY_ALLOC;
228 isom_box_common_copy( unknown, box );
229 unknown->manager |= LSMASH_UNKNOWN_BOX;
230 unknown->destruct = (isom_extension_destructor_t)isom_remove_unknown_box;
231 isom_set_box_writer( (isom_box_t *)unknown );
232 if( read_size )
234 unknown->unknown_field = lsmash_bs_get_bytes( bs, read_size );
235 if( unknown->unknown_field )
236 unknown->unknown_size = read_size;
237 else
238 unknown->manager |= LSMASH_INCOMPLETE_BOX;
240 if( !(file->flags & LSMASH_FILE_MODE_DUMP) )
241 return 0;
242 /* Create a dummy for dump. */
243 isom_box_t *dummy = lsmash_malloc_zero( sizeof(isom_box_t) );
244 if( !dummy )
245 return LSMASH_ERR_MEMORY_ALLOC;
246 box->manager |= LSMASH_ABSENT_IN_FILE;
247 isom_box_common_copy( dummy, box );
248 int ret = isom_add_print_func( file, dummy, level );
249 if( ret < 0 )
251 lsmash_free( dummy );
252 return ret;
254 return 0;
257 #define ADD_BOX( box_name, parent_type ) \
258 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
259 if( !box_name ) \
260 return LSMASH_ERR_NAMELESS
262 static int isom_read_ftyp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
264 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->ftyp )
265 return isom_read_unknown_box( file, box, parent, level );
266 ADD_BOX( ftyp, lsmash_file_t );
267 lsmash_bs_t *bs = file->bs;
268 ftyp->major_brand = lsmash_bs_get_be32( bs );
269 ftyp->minor_version = lsmash_bs_get_be32( bs );
270 uint64_t pos = lsmash_bs_count( bs );
271 ftyp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
272 size_t alloc_size = ftyp->brand_count * sizeof(uint32_t);
273 ftyp->compatible_brands = ftyp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
274 if( ftyp->brand_count && !ftyp->compatible_brands )
275 return LSMASH_ERR_MEMORY_ALLOC;
276 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
277 ftyp->compatible_brands[i] = lsmash_bs_get_be32( bs );
278 if( !file->compatible_brands && ftyp->compatible_brands )
280 file->compatible_brands = lsmash_memdup( ftyp->compatible_brands, alloc_size );
281 if( !file->compatible_brands )
282 return LSMASH_ERR_MEMORY_ALLOC;
283 file->brand_count = ftyp->brand_count;
285 return isom_read_leaf_box_common_last_process( file, box, level, ftyp );
288 static int isom_read_styp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
290 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
291 return isom_read_unknown_box( file, box, parent, level );
292 ADD_BOX( styp, lsmash_file_t );
293 lsmash_bs_t *bs = file->bs;
294 styp->major_brand = lsmash_bs_get_be32( bs );
295 styp->minor_version = lsmash_bs_get_be32( bs );
296 uint64_t pos = lsmash_bs_count( bs );
297 styp->brand_count = box->size > pos ? (box->size - pos) / sizeof(uint32_t) : 0;
298 size_t alloc_size = styp->brand_count * sizeof(uint32_t);
299 styp->compatible_brands = styp->brand_count ? lsmash_malloc( alloc_size ) : NULL;
300 if( styp->brand_count && !styp->compatible_brands )
301 return LSMASH_ERR_MEMORY_ALLOC;
302 for( uint32_t i = 0; i < styp->brand_count; i++ )
303 styp->compatible_brands[i] = lsmash_bs_get_be32( bs );
304 if( !file->compatible_brands && styp->compatible_brands )
306 file->compatible_brands = lsmash_memdup( styp->compatible_brands, alloc_size );
307 if( !file->compatible_brands )
308 return LSMASH_ERR_MEMORY_ALLOC;
309 file->brand_count = styp->brand_count;
311 file->flags |= LSMASH_FILE_MODE_SEGMENT;
312 return isom_read_leaf_box_common_last_process( file, box, level, styp );
315 static int isom_read_sidx( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
317 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
318 return isom_read_unknown_box( file, box, parent, level );
319 ADD_BOX( sidx, lsmash_file_t );
320 lsmash_bs_t *bs = file->bs;
321 sidx->reference_ID = lsmash_bs_get_be32( bs );
322 sidx->timescale = lsmash_bs_get_be32( bs );
323 if( box->version == 0 )
325 sidx->earliest_presentation_time = lsmash_bs_get_be32( bs );
326 sidx->first_offset = lsmash_bs_get_be32( bs );
328 else
330 sidx->earliest_presentation_time = lsmash_bs_get_be64( bs );
331 sidx->first_offset = lsmash_bs_get_be64( bs );
333 sidx->reserved = lsmash_bs_get_be16( bs );
334 sidx->reference_count = lsmash_bs_get_be16( bs );
335 for( uint64_t pos = lsmash_bs_count( bs );
336 pos < box->size && sidx->list->entry_count < sidx->reference_count;
337 pos = lsmash_bs_count( bs ) )
339 isom_sidx_referenced_item_t *data = lsmash_malloc( sizeof(isom_sidx_referenced_item_t) );
340 if( !data )
341 return LSMASH_ERR_MEMORY_ALLOC;
342 if( lsmash_add_entry( sidx->list, data ) < 0 )
344 lsmash_free( data );
345 return LSMASH_ERR_MEMORY_ALLOC;
347 uint32_t temp32;
348 temp32 = lsmash_bs_get_be32( bs );
349 data->reference_type = (temp32 >> 31) & 0x00000001;
350 data->reference_size = temp32 & 0x7FFFFFFF;
351 data->subsegment_duration = lsmash_bs_get_be32( bs );
352 temp32 = lsmash_bs_get_be32( bs );
353 data->starts_with_SAP = (temp32 >> 31) & 0x00000001;
354 data->SAP_type = (temp32 >> 28) & 0x00000007;
355 data->SAP_delta_time = temp32 & 0x0FFFFFFF;
357 file->flags |= LSMASH_FILE_MODE_INDEX;
358 return isom_read_leaf_box_common_last_process( file, box, level, sidx );
361 static int isom_read_moov( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
363 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->moov )
364 return isom_read_unknown_box( file, box, parent, level );
365 ADD_BOX( moov, lsmash_file_t );
366 file->flags |= LSMASH_FILE_MODE_INITIALIZATION;
367 file->initializer = file;
368 isom_box_common_copy( moov, box );
369 int ret = isom_add_print_func( file, moov, level );
370 if( ret < 0 )
371 return ret;
372 return isom_read_children( file, box, moov, level );
375 static int isom_read_mvhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
377 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvhd )
378 return isom_read_unknown_box( file, box, parent, level );
379 ADD_BOX( mvhd, isom_moov_t );
380 lsmash_bs_t *bs = file->bs;
381 if( box->version )
383 mvhd->creation_time = lsmash_bs_get_be64( bs );
384 mvhd->modification_time = lsmash_bs_get_be64( bs );
385 mvhd->timescale = lsmash_bs_get_be32( bs );
386 mvhd->duration = lsmash_bs_get_be64( bs );
388 else
390 mvhd->creation_time = lsmash_bs_get_be32( bs );
391 mvhd->modification_time = lsmash_bs_get_be32( bs );
392 mvhd->timescale = lsmash_bs_get_be32( bs );
393 mvhd->duration = lsmash_bs_get_be32( bs );
395 mvhd->rate = lsmash_bs_get_be32( bs );
396 mvhd->volume = lsmash_bs_get_be16( bs );
397 mvhd->reserved = lsmash_bs_get_be16( bs );
398 mvhd->preferredLong[0] = lsmash_bs_get_be32( bs );
399 mvhd->preferredLong[1] = lsmash_bs_get_be32( bs );
400 for( int i = 0; i < 9; i++ )
401 mvhd->matrix[i] = lsmash_bs_get_be32( bs );
402 mvhd->previewTime = lsmash_bs_get_be32( bs );
403 mvhd->previewDuration = lsmash_bs_get_be32( bs );
404 mvhd->posterTime = lsmash_bs_get_be32( bs );
405 mvhd->selectionTime = lsmash_bs_get_be32( bs );
406 mvhd->selectionDuration = lsmash_bs_get_be32( bs );
407 mvhd->currentTime = lsmash_bs_get_be32( bs );
408 mvhd->next_track_ID = lsmash_bs_get_be32( bs );
409 return isom_read_leaf_box_common_last_process( file, box, level, mvhd );
412 static int isom_read_iods( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
414 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
415 return isom_read_unknown_box( file, box, parent, level );
416 ADD_BOX( iods, isom_moov_t );
417 lsmash_bs_t *bs = file->bs;
418 iods->OD = mp4sys_get_descriptor( bs, NULL );
419 if( !iods->OD )
420 return LSMASH_ERR_INVALID_DATA;
421 isom_skip_box_rest( file->bs, box );
422 return isom_read_leaf_box_common_last_process( file, box, level, iods );
425 static int isom_read_qt_color_table( lsmash_bs_t *bs, isom_qt_color_table_t *color_table )
427 color_table->seed = lsmash_bs_get_be32( bs );
428 color_table->flags = lsmash_bs_get_be16( bs );
429 color_table->size = lsmash_bs_get_be16( bs );
430 if( bs->eob )
431 return LSMASH_ERR_INVALID_DATA;
432 isom_qt_color_array_t *array = lsmash_malloc_zero( (color_table->size + 1) * sizeof(isom_qt_color_array_t) );
433 if( !array )
434 return LSMASH_ERR_MEMORY_ALLOC;
435 color_table->array = array;
436 for( uint16_t i = 0; i <= color_table->size; i++ )
438 uint64_t color = lsmash_bs_get_be64( bs );
439 array[i].value = (color >> 48) & 0xffff;
440 array[i].r = (color >> 32) & 0xffff;
441 array[i].g = (color >> 16) & 0xffff;
442 array[i].b = color & 0xffff;
444 return 0;
447 static int isom_read_ctab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
449 ADD_BOX( ctab, isom_moov_t );
450 lsmash_bs_t *bs = file->bs;
451 int ret = isom_read_qt_color_table( bs, &ctab->color_table );
452 if( ret < 0 )
453 return ret;
454 return isom_read_leaf_box_common_last_process( file, box, level, ctab );
457 static int isom_read_trak( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
459 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) )
460 return isom_read_unknown_box( file, box, parent, level );
461 ADD_BOX( trak, isom_moov_t );
462 box->parent = parent;
463 box->root = file->root;
464 box->file = file;
465 isom_box_common_copy( trak, box );
466 int ret = isom_add_print_func( file, trak, level );
467 if( ret < 0 )
468 return ret;
469 return isom_read_children( file, box, trak, level );
472 static int isom_read_tkhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
474 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tkhd )
475 return isom_read_unknown_box( file, box, parent, level );
476 ADD_BOX( tkhd, isom_trak_t );
477 lsmash_bs_t *bs = file->bs;
478 if( box->version )
480 tkhd->creation_time = lsmash_bs_get_be64( bs );
481 tkhd->modification_time = lsmash_bs_get_be64( bs );
482 tkhd->track_ID = lsmash_bs_get_be32( bs );
483 tkhd->reserved1 = lsmash_bs_get_be32( bs );
484 tkhd->duration = lsmash_bs_get_be64( bs );
486 else
488 tkhd->creation_time = lsmash_bs_get_be32( bs );
489 tkhd->modification_time = lsmash_bs_get_be32( bs );
490 tkhd->track_ID = lsmash_bs_get_be32( bs );
491 tkhd->reserved1 = lsmash_bs_get_be32( bs );
492 tkhd->duration = lsmash_bs_get_be32( bs );
494 tkhd->reserved2[0] = lsmash_bs_get_be32( bs );
495 tkhd->reserved2[1] = lsmash_bs_get_be32( bs );
496 tkhd->layer = lsmash_bs_get_be16( bs );
497 tkhd->alternate_group = lsmash_bs_get_be16( bs );
498 tkhd->volume = lsmash_bs_get_be16( bs );
499 tkhd->reserved3 = lsmash_bs_get_be16( bs );
500 for( int i = 0; i < 9; i++ )
501 tkhd->matrix[i] = lsmash_bs_get_be32( bs );
502 tkhd->width = lsmash_bs_get_be32( bs );
503 tkhd->height = lsmash_bs_get_be32( bs );
504 return isom_read_leaf_box_common_last_process( file, box, level, tkhd );
507 static int isom_read_tapt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
509 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tapt )
510 return isom_read_unknown_box( file, box, parent, level );
511 ADD_BOX( tapt, isom_trak_t );
512 isom_box_common_copy( tapt, box );
513 int ret = isom_add_print_func( file, tapt, level );
514 if( ret < 0 )
515 return ret;
516 return isom_read_children( file, box, tapt, level );
519 static int isom_read_clef( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
521 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->clef )
522 return isom_read_unknown_box( file, box, parent, level );
523 ADD_BOX( clef, isom_tapt_t );
524 lsmash_bs_t *bs = file->bs;
525 clef->width = lsmash_bs_get_be32( bs );
526 clef->height = lsmash_bs_get_be32( bs );
527 return isom_read_leaf_box_common_last_process( file, box, level, clef );
530 static int isom_read_prof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
532 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->prof )
533 return isom_read_unknown_box( file, box, parent, level );
534 ADD_BOX( prof, isom_tapt_t );
535 lsmash_bs_t *bs = file->bs;
536 prof->width = lsmash_bs_get_be32( bs );
537 prof->height = lsmash_bs_get_be32( bs );
538 return isom_read_leaf_box_common_last_process( file, box, level, prof );
541 static int isom_read_enof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
543 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_TAPT ) || ((isom_tapt_t *)parent)->enof )
544 return isom_read_unknown_box( file, box, parent, level );
545 ADD_BOX( enof, isom_tapt_t );
546 lsmash_bs_t *bs = file->bs;
547 enof->width = lsmash_bs_get_be32( bs );
548 enof->height = lsmash_bs_get_be32( bs );
549 return isom_read_leaf_box_common_last_process( file, box, level, enof );
552 static int isom_read_edts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
554 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->edts )
555 return isom_read_unknown_box( file, box, parent, level );
556 ADD_BOX( edts, isom_trak_t );
557 isom_box_common_copy( edts, box );
558 if( isom_add_print_func( file, edts, level ) < 0 )
559 return -1;
560 return isom_read_children( file, box, edts, level );
563 static int isom_read_elst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
565 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_EDTS ) || ((isom_edts_t *)parent)->elst )
566 return isom_read_unknown_box( file, box, parent, level );
567 ADD_BOX( elst, isom_edts_t );
568 lsmash_bs_t *bs = file->bs;
569 uint32_t entry_count = lsmash_bs_get_be32( bs );
570 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && elst->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
572 isom_elst_entry_t *data = lsmash_malloc( sizeof(isom_elst_entry_t) );
573 if( !data )
574 return LSMASH_ERR_MEMORY_ALLOC;
575 if( lsmash_add_entry( elst->list, data ) < 0 )
577 lsmash_free( data );
578 return LSMASH_ERR_MEMORY_ALLOC;
580 if( box->version == 1 )
582 data->segment_duration = lsmash_bs_get_be64( bs );
583 data->media_time = (int64_t)lsmash_bs_get_be64( bs );
585 else
587 data->segment_duration = lsmash_bs_get_be32( bs );
588 data->media_time = (int32_t)lsmash_bs_get_be32( bs );
590 data->media_rate = lsmash_bs_get_be32( bs );
592 return isom_read_leaf_box_common_last_process( file, box, level, elst );
595 static int isom_read_tref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
597 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->tref )
598 return isom_read_unknown_box( file, box, parent, level );
599 ADD_BOX( tref, isom_trak_t );
600 isom_box_common_copy( tref, box );
601 int ret = isom_add_print_func( file, tref, level );
602 if( ret < 0 )
603 return ret;
604 return isom_read_children( file, box, tref, level );
607 static int isom_read_track_reference_type( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
609 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
610 return isom_read_unknown_box( file, box, parent, level );
611 isom_tref_type_t *ref = isom_add_track_reference_type( (isom_tref_t *)parent, box->type.fourcc );
612 if( !ref )
613 return LSMASH_ERR_NAMELESS;
614 lsmash_bs_t *bs = file->bs;
615 ref->ref_count = (box->size - lsmash_bs_count( bs ) ) / sizeof(uint32_t);
616 if( ref->ref_count )
618 ref->track_ID = lsmash_malloc( ref->ref_count * sizeof(uint32_t) );
619 if( !ref->track_ID )
621 ref->ref_count = 0;
622 return LSMASH_ERR_MEMORY_ALLOC;
624 for( uint32_t i = 0; i < ref->ref_count; i++ )
625 ref->track_ID[i] = lsmash_bs_get_be32( bs );
627 return isom_read_leaf_box_common_last_process( file, box, level, ref );
630 static int isom_read_mdia( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
632 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) || ((isom_trak_t *)parent)->mdia )
633 return isom_read_unknown_box( file, box, parent, level );
634 ADD_BOX( mdia, isom_trak_t );
635 isom_box_common_copy( mdia, box );
636 int ret = isom_add_print_func( file, mdia, level );
637 if( ret < 0 )
638 return ret;
639 return isom_read_children( file, box, mdia, level );
642 static int isom_read_mdhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
644 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->mdhd )
645 return isom_read_unknown_box( file, box, parent, level );
646 ADD_BOX( mdhd, isom_mdia_t );
647 lsmash_bs_t *bs = file->bs;
648 if( box->version )
650 mdhd->creation_time = lsmash_bs_get_be64( bs );
651 mdhd->modification_time = lsmash_bs_get_be64( bs );
652 mdhd->timescale = lsmash_bs_get_be32( bs );
653 mdhd->duration = lsmash_bs_get_be64( bs );
655 else
657 mdhd->creation_time = lsmash_bs_get_be32( bs );
658 mdhd->modification_time = lsmash_bs_get_be32( bs );
659 mdhd->timescale = lsmash_bs_get_be32( bs );
660 mdhd->duration = lsmash_bs_get_be32( bs );
662 mdhd->language = lsmash_bs_get_be16( bs );
663 mdhd->quality = lsmash_bs_get_be16( bs );
664 return isom_read_leaf_box_common_last_process( file, box, level, mdhd );
667 static int isom_read_hdlr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
669 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA )
670 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
671 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META )
672 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ))
673 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) && ((isom_mdia_t *)parent)->hdlr)
674 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
675 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->hdlr)
676 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->hdlr) )
677 return isom_read_unknown_box( file, box, parent, level );
678 ADD_BOX( hdlr, void );
679 lsmash_bs_t *bs = file->bs;
680 hdlr->componentType = lsmash_bs_get_be32( bs );
681 hdlr->componentSubtype = lsmash_bs_get_be32( bs );
682 hdlr->componentManufacturer = lsmash_bs_get_be32( bs );
683 hdlr->componentFlags = lsmash_bs_get_be32( bs );
684 hdlr->componentFlagsMask = lsmash_bs_get_be32( bs );
685 uint64_t pos = lsmash_bs_count( bs );
686 hdlr->componentName_length = box->size - pos;
687 if( hdlr->componentName_length )
689 hdlr->componentName = lsmash_malloc( hdlr->componentName_length );
690 if( !hdlr->componentName )
691 return LSMASH_ERR_MEMORY_ALLOC;
692 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
693 hdlr->componentName[i++] = lsmash_bs_get_byte( bs );
695 return isom_read_leaf_box_common_last_process( file, box, level, hdlr );
698 static int isom_read_minf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
700 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MDIA ) || ((isom_mdia_t *)parent)->minf )
701 return isom_read_unknown_box( file, box, parent, level );
702 ADD_BOX( minf, isom_mdia_t );
703 isom_box_common_copy( minf, box );
704 int ret = isom_add_print_func( file, minf, level );
705 if( ret < 0 )
706 return ret;
707 return isom_read_children( file, box, minf, level );
710 static int isom_read_vmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
712 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->vmhd )
713 return isom_read_unknown_box( file, box, parent, level );
714 ADD_BOX( vmhd, isom_minf_t );
715 lsmash_bs_t *bs = file->bs;
716 vmhd->graphicsmode = lsmash_bs_get_be16( bs );
717 for( int i = 0; i < 3; i++ )
718 vmhd->opcolor[i] = lsmash_bs_get_be16( bs );
719 return isom_read_leaf_box_common_last_process( file, box, level, vmhd );
722 static int isom_read_smhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
724 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->smhd )
725 return isom_read_unknown_box( file, box, parent, level );
726 ADD_BOX( smhd, isom_minf_t );
727 lsmash_bs_t *bs = file->bs;
728 smhd->balance = lsmash_bs_get_be16( bs );
729 smhd->reserved = lsmash_bs_get_be16( bs );
730 return isom_read_leaf_box_common_last_process( file, box, level, smhd );
733 static int isom_read_hmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
735 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->hmhd )
736 return isom_read_unknown_box( file, box, parent, level );
737 ADD_BOX( hmhd, isom_minf_t );
738 lsmash_bs_t *bs = file->bs;
739 hmhd->maxPDUsize = lsmash_bs_get_be16( bs );
740 hmhd->avgPDUsize = lsmash_bs_get_be16( bs );
741 hmhd->maxbitrate = lsmash_bs_get_be32( bs );
742 hmhd->avgbitrate = lsmash_bs_get_be32( bs );
743 hmhd->reserved = lsmash_bs_get_be32( bs );
744 return isom_read_leaf_box_common_last_process( file, box, level, hmhd );
747 static int isom_read_nmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
749 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->nmhd )
750 return isom_read_unknown_box( file, box, parent, level );
751 ADD_BOX( nmhd, isom_minf_t );
752 return isom_read_leaf_box_common_last_process( file, box, level, nmhd );
755 static int isom_read_gmhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
757 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->gmhd )
758 return isom_read_unknown_box( file, box, parent, level );
759 ADD_BOX( gmhd, isom_minf_t );
760 isom_box_common_copy( gmhd, box );
761 int ret = isom_add_print_func( file, gmhd, level );
762 if( ret < 0 )
763 return ret;
764 return isom_read_children( file, box, gmhd, level );
767 static int isom_read_gmin( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
769 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->gmin )
770 return isom_read_unknown_box( file, box, parent, level );
771 ADD_BOX( gmin, isom_gmhd_t );
772 lsmash_bs_t *bs = file->bs;
773 gmin->graphicsmode = lsmash_bs_get_be16( bs );
774 for( int i = 0; i < 3; i++ )
775 gmin->opcolor[i] = lsmash_bs_get_be16( bs );
776 gmin->balance = lsmash_bs_get_be16( bs );
777 gmin->reserved = lsmash_bs_get_be16( bs );
778 return isom_read_leaf_box_common_last_process( file, box, level, gmin );
781 static int isom_read_text( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
783 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_GMHD ) || ((isom_gmhd_t *)parent)->text )
784 return isom_read_unknown_box( file, box, parent, level );
785 ADD_BOX( text, isom_gmhd_t );
786 lsmash_bs_t *bs = file->bs;
787 for( int i = 0; i < 9; i++ )
788 text->matrix[i] = lsmash_bs_get_be32( bs );
789 return isom_read_leaf_box_common_last_process( file, box, level, text );
792 static int isom_read_dinf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
794 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF )
795 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
796 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
797 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) && ((isom_minf_t *)parent)->dinf)
798 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf)
799 || (lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && ((isom_meta_t *)parent)->dinf) )
800 return isom_read_unknown_box( file, box, parent, level );
801 ADD_BOX( dinf, void );
802 isom_box_common_copy( dinf, box );
803 int ret = isom_add_print_func( file, dinf, level );
804 if( ret < 0 )
805 return ret;
806 return isom_read_children( file, box, dinf, level );
809 static int isom_read_dref( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
811 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DINF ) || ((isom_dinf_t *)parent)->dref )
812 return isom_read_unknown_box( file, box, parent, level );
813 ADD_BOX( dref, isom_dinf_t );
814 lsmash_bs_t *bs = file->bs;
815 dref->list.entry_count = lsmash_bs_get_be32( bs );
816 isom_box_common_copy( dref, box );
817 int ret = isom_add_print_func( file, dref, level );
818 if( ret < 0 )
819 return ret;
820 return isom_read_children( file, box, dref, level );
823 static int isom_read_dref_entry( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
825 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
826 return isom_read_unknown_box( file, box, parent, level );
827 isom_dref_t *dref = (isom_dref_t *)parent;
828 if( !dref->list.head )
829 dref->list.entry_count = 0; /* discard entry_count gotten from the file */
830 isom_dref_entry_t *ref = isom_add_dref_entry( dref, box->type );
831 if( !ref )
832 return LSMASH_ERR_NAMELESS;
833 lsmash_bs_t *bs = file->bs;
834 if( lsmash_check_box_type_identical( ref->type, ISOM_BOX_TYPE_URL ) )
836 uint64_t pos = lsmash_bs_count( bs );
837 ref->location_length = box->size - pos;
838 if( ref->location_length )
840 ref->location = lsmash_malloc( ref->location_length );
841 if( !ref->location )
842 return LSMASH_ERR_MEMORY_ALLOC;
843 for( uint32_t i = 0; pos < box->size; pos = lsmash_bs_count( bs ) )
844 ref->location[i++] = lsmash_bs_get_byte( bs );
847 else
848 isom_skip_box_rest( bs, box );
849 if( box->flags & 0x000001 )
850 ref->ref_file = ref->file;
851 box->parent = parent;
852 return isom_read_leaf_box_common_last_process( file, box, level, ref );
855 static int isom_read_stbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
857 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MINF ) || ((isom_minf_t *)parent)->stbl )
858 return isom_read_unknown_box( file, box, parent, level );
859 ADD_BOX( stbl, isom_minf_t );
860 isom_box_common_copy( stbl, box );
861 int ret = isom_add_print_func( file, stbl, level );
862 if( ret < 0 )
863 return ret;
864 return isom_read_children( file, box, stbl, level );
867 static int isom_read_stsd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
869 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsd )
870 return isom_read_unknown_box( file, box, parent, level );
871 ADD_BOX( stsd, isom_stbl_t );
872 lsmash_bs_t *bs = file->bs;
873 stsd->entry_count = lsmash_bs_get_be32( bs );
874 isom_box_common_copy( stsd, box );
875 int ret = isom_add_print_func( file, stsd, level );
876 if( ret < 0 )
877 return ret;
878 uint64_t stsd_pos = lsmash_bs_count( bs );
879 for( uint32_t i = 0; i < stsd->entry_count || (stsd_pos + ISOM_BASEBOX_COMMON_SIZE) <= stsd->size; i++ )
881 if( (ret = isom_read_box( file, box, (isom_box_t *)stsd, stsd_pos, level )) != 0 )
882 break;
883 stsd_pos += box->size;
884 if( stsd->size <= stsd_pos || bs->eob || bs->error )
885 break;
887 if( stsd->size < stsd_pos )
889 printf( "[stsd] box has extra bytes: %"PRId64"\n", stsd_pos - stsd->size );
890 stsd->size = stsd_pos;
892 box->size = stsd->size;
893 return ret;
896 static int isom_read_codec_specific( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
898 lsmash_bs_t *bs = file->bs;
899 uint64_t opaque_pos = lsmash_bs_count( bs );
900 uint64_t exdata_length = box->size - opaque_pos;
901 if( exdata_length > UINT32_MAX )
902 return LSMASH_ERR_MEMORY_ALLOC;
903 uint8_t *exdata = lsmash_malloc( box->size );
904 if( !exdata )
905 return LSMASH_ERR_MEMORY_ALLOC;
906 int ret = lsmash_bs_get_bytes_ex( bs, exdata_length, exdata + (uintptr_t)opaque_pos );
907 if( ret < 0 )
908 goto fail;
909 LSMASH_SET_BE32( &exdata[0], box->size );
910 LSMASH_SET_BE32( &exdata[4], box->type.fourcc );
911 uintptr_t i = 8;
912 if( box->type.fourcc == ISOM_BOX_TYPE_UUID.fourcc )
914 LSMASH_SET_BE32( &exdata[8], box->type.user.fourcc );
915 memcpy( &exdata[12], box->type.user.id, 12 );
916 i += 16;
918 if( box->manager & LSMASH_FULLBOX )
920 LSMASH_SET_BYTE( &exdata[i], box->version );
921 i += 1;
922 LSMASH_SET_BE24( &exdata[i], box->flags );
923 i += 3;
925 if( i != opaque_pos )
927 ret = LSMASH_ERR_INVALID_DATA;
928 goto fail;
930 if( (ret = isom_add_extension_binary( parent, box->type, LSMASH_BOX_PRECEDENCE_N, exdata, box->size )) < 0 )
931 goto fail;
932 isom_box_t *ext = (isom_box_t *)parent->extensions.tail->data;
933 box->manager |= ext->manager;
934 isom_check_box_size( file->bs, box );
935 isom_basebox_common_copy( ext, box );
936 return isom_add_print_func( file, ext, level );
937 fail:
938 lsmash_free( exdata );
939 return ret;
942 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type )
944 if( lsmash_check_codec_type_identical( sample_type, LSMASH_CODEC_TYPE_RAW ) )
945 return lsmash_malloc_zero( LSMASH_MAX( sizeof(isom_visual_entry_t), sizeof(isom_audio_entry_t) ) );
946 static struct description_alloc_table_tag
948 lsmash_codec_type_t type;
949 size_t alloc_size;
950 } description_alloc_table[160] = { { LSMASH_CODEC_TYPE_INITIALIZER, 0 } };
951 if( description_alloc_table[0].alloc_size == 0 )
953 /* Initialize the table. */
954 int i = 0;
955 #define ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( type, alloc_size ) \
956 description_alloc_table[i++] = (struct description_alloc_table_tag){ type, alloc_size }
957 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, sizeof(isom_visual_entry_t) );
958 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, sizeof(isom_visual_entry_t) );
959 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, sizeof(isom_visual_entry_t) );
960 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, sizeof(isom_visual_entry_t) );
961 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, sizeof(isom_visual_entry_t) );
962 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, sizeof(isom_visual_entry_t) );
963 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, sizeof(isom_visual_entry_t) );
964 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, sizeof(isom_visual_entry_t) );
965 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, sizeof(isom_visual_entry_t) );
966 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, sizeof(isom_visual_entry_t) );
967 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, sizeof(isom_visual_entry_t) );
968 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, sizeof(isom_visual_entry_t) );
969 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, sizeof(isom_visual_entry_t) );
970 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, sizeof(isom_visual_entry_t) );
971 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, sizeof(isom_visual_entry_t) );
972 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, sizeof(isom_visual_entry_t) );
973 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, sizeof(isom_visual_entry_t) );
974 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, sizeof(isom_visual_entry_t) );
975 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, sizeof(isom_visual_entry_t) );
976 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, sizeof(isom_visual_entry_t) );
977 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, sizeof(isom_visual_entry_t) );
978 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, sizeof(isom_visual_entry_t) );
979 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, sizeof(isom_visual_entry_t) );
980 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, sizeof(isom_visual_entry_t) );
981 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, sizeof(isom_visual_entry_t) );
982 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, sizeof(isom_visual_entry_t) );
983 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, sizeof(isom_visual_entry_t) );
984 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, sizeof(isom_visual_entry_t) );
985 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, sizeof(isom_visual_entry_t) );
986 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, sizeof(isom_visual_entry_t) );
987 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, sizeof(isom_visual_entry_t) );
988 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, sizeof(isom_visual_entry_t) );
989 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, sizeof(isom_visual_entry_t) );
990 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, sizeof(isom_visual_entry_t) );
991 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, sizeof(isom_visual_entry_t) );
992 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, sizeof(isom_visual_entry_t) );
993 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, sizeof(isom_visual_entry_t) );
994 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, sizeof(isom_visual_entry_t) );
995 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, sizeof(isom_visual_entry_t) );
996 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, sizeof(isom_visual_entry_t) );
997 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, sizeof(isom_visual_entry_t) );
998 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, sizeof(isom_visual_entry_t) );
999 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, sizeof(isom_visual_entry_t) );
1000 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, sizeof(isom_visual_entry_t) );
1001 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, sizeof(isom_visual_entry_t) );
1002 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, sizeof(isom_visual_entry_t) );
1003 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, sizeof(isom_visual_entry_t) );
1004 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, sizeof(isom_visual_entry_t) );
1005 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, sizeof(isom_visual_entry_t) );
1006 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, sizeof(isom_visual_entry_t) );
1007 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, sizeof(isom_visual_entry_t) );
1008 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, sizeof(isom_visual_entry_t) );
1009 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, sizeof(isom_visual_entry_t) );
1010 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, sizeof(isom_visual_entry_t) );
1011 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, sizeof(isom_visual_entry_t) );
1012 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, sizeof(isom_visual_entry_t) );
1013 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, sizeof(isom_visual_entry_t) );
1014 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, sizeof(isom_visual_entry_t) );
1015 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, sizeof(isom_visual_entry_t) );
1016 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, sizeof(isom_visual_entry_t) );
1017 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, sizeof(isom_visual_entry_t) );
1018 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, sizeof(isom_visual_entry_t) );
1019 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, sizeof(isom_visual_entry_t) );
1020 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, sizeof(isom_visual_entry_t) );
1021 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, sizeof(isom_visual_entry_t) );
1022 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, sizeof(isom_visual_entry_t) );
1023 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, sizeof(isom_visual_entry_t) );
1024 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, sizeof(isom_visual_entry_t) );
1025 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, sizeof(isom_visual_entry_t) );
1026 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, sizeof(isom_visual_entry_t) );
1027 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, sizeof(isom_visual_entry_t) );
1028 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, sizeof(isom_visual_entry_t) );
1029 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, sizeof(isom_visual_entry_t) );
1030 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, sizeof(isom_visual_entry_t) );
1031 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, sizeof(isom_visual_entry_t) );
1032 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, sizeof(isom_visual_entry_t) );
1033 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, sizeof(isom_audio_entry_t) );
1034 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, sizeof(isom_audio_entry_t) );
1035 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, sizeof(isom_audio_entry_t) );
1036 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, sizeof(isom_audio_entry_t) );
1037 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, sizeof(isom_audio_entry_t) );
1038 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, sizeof(isom_audio_entry_t) );
1039 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, sizeof(isom_audio_entry_t) );
1040 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, sizeof(isom_audio_entry_t) );
1041 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, sizeof(isom_audio_entry_t) );
1042 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, sizeof(isom_audio_entry_t) );
1043 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, sizeof(isom_audio_entry_t) );
1044 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, sizeof(isom_audio_entry_t) );
1045 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, sizeof(isom_audio_entry_t) );
1046 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, sizeof(isom_audio_entry_t) );
1047 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_RAW_AUDIO, sizeof(isom_audio_entry_t) );
1048 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, sizeof(isom_audio_entry_t) );
1049 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, sizeof(isom_audio_entry_t) );
1050 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, sizeof(isom_audio_entry_t) );
1051 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, sizeof(isom_audio_entry_t) );
1052 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, sizeof(isom_audio_entry_t) );
1053 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, sizeof(isom_audio_entry_t) );
1054 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, sizeof(isom_audio_entry_t) );
1055 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, sizeof(isom_audio_entry_t) );
1056 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MP4A_AUDIO, sizeof(isom_audio_entry_t) );
1057 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, sizeof(isom_audio_entry_t) );
1058 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, sizeof(isom_audio_entry_t) );
1059 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, sizeof(isom_audio_entry_t) );
1060 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, sizeof(isom_audio_entry_t) );
1061 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, sizeof(isom_audio_entry_t) );
1062 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, sizeof(isom_audio_entry_t) );
1063 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, sizeof(isom_audio_entry_t) );
1064 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, sizeof(isom_audio_entry_t) );
1065 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, sizeof(isom_audio_entry_t) );
1066 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, sizeof(isom_audio_entry_t) );
1067 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, sizeof(isom_audio_entry_t) );
1068 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, sizeof(isom_audio_entry_t) );
1069 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, sizeof(isom_audio_entry_t) );
1070 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, sizeof(isom_audio_entry_t) );
1071 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, sizeof(isom_audio_entry_t) );
1072 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, sizeof(isom_audio_entry_t) );
1073 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, sizeof(isom_audio_entry_t) );
1074 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, sizeof(isom_audio_entry_t) );
1075 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, sizeof(isom_audio_entry_t) );
1076 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, sizeof(isom_audio_entry_t) );
1077 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, sizeof(isom_audio_entry_t) );
1078 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, sizeof(isom_audio_entry_t) );
1079 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, sizeof(isom_audio_entry_t) );
1080 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, sizeof(isom_audio_entry_t) );
1081 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, sizeof(isom_audio_entry_t) );
1082 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, sizeof(isom_audio_entry_t) );
1083 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, sizeof(isom_audio_entry_t) );
1084 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, sizeof(isom_audio_entry_t) );
1085 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, sizeof(isom_audio_entry_t) );
1086 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, sizeof(isom_tx3g_entry_t) );
1087 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, sizeof(isom_qt_text_entry_t) );
1088 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, sizeof(isom_mp4s_entry_t) );
1089 ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, 0 );
1090 #undef ADD_DESCRIPTION_ALLOC_TABLE_ELEMENT
1092 for( int i = 0; description_alloc_table[i].alloc_size; i++ )
1093 if( lsmash_check_codec_type_identical( sample_type, description_alloc_table[i].type ) )
1094 return lsmash_malloc_zero( description_alloc_table[i].alloc_size );
1095 return NULL;
1098 static void *isom_add_description( lsmash_codec_type_t sample_type, isom_stsd_t *stsd )
1100 void *sample = isom_sample_description_alloc( sample_type );
1101 if( !sample )
1102 return NULL;
1103 if( lsmash_add_entry( &stsd->list, sample ) < 0 )
1105 lsmash_free( sample );
1106 return NULL;
1108 if( lsmash_add_entry( &stsd->extensions, sample ) < 0 )
1110 lsmash_remove_entry_tail( &stsd->list, lsmash_free );
1111 return NULL;
1113 ((isom_box_t *)sample)->destruct = (isom_extension_destructor_t)isom_remove_sample_description;
1114 return sample;
1117 static int isom_read_visual_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1119 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1120 return isom_read_unknown_box( file, box, parent, level );
1121 isom_visual_entry_t *visual = (isom_visual_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1122 if( !visual )
1123 return LSMASH_ERR_MEMORY_ALLOC;
1124 lsmash_bs_t *bs = file->bs;
1125 for( int i = 0; i < 6; i++ )
1126 visual->reserved[i] = lsmash_bs_get_byte( bs );
1127 visual->data_reference_index = lsmash_bs_get_be16( bs );
1128 visual->version = lsmash_bs_get_be16( bs );
1129 visual->revision_level = lsmash_bs_get_be16( bs );
1130 visual->vendor = lsmash_bs_get_be32( bs );
1131 visual->temporalQuality = lsmash_bs_get_be32( bs );
1132 visual->spatialQuality = lsmash_bs_get_be32( bs );
1133 visual->width = lsmash_bs_get_be16( bs );
1134 visual->height = lsmash_bs_get_be16( bs );
1135 visual->horizresolution = lsmash_bs_get_be32( bs );
1136 visual->vertresolution = lsmash_bs_get_be32( bs );
1137 visual->dataSize = lsmash_bs_get_be32( bs );
1138 visual->frame_count = lsmash_bs_get_be16( bs );
1139 for( int i = 0; i < 32; i++ )
1140 visual->compressorname[i] = lsmash_bs_get_byte( bs );
1141 visual->depth = lsmash_bs_get_be16( bs );
1142 visual->color_table_ID = lsmash_bs_get_be16( bs );
1143 int ret;
1144 if( visual->color_table_ID == 0
1145 && lsmash_bs_get_pos( bs ) < box->size
1146 && (ret = isom_read_qt_color_table( bs, &visual->color_table )) < 0 )
1147 return ret;
1148 box->parent = parent;
1149 box->manager |= LSMASH_VIDEO_DESCRIPTION;
1150 isom_box_common_copy( visual, box );
1151 if( (ret = isom_add_print_func( file, visual, level )) < 0 )
1152 return ret;
1153 return isom_read_children( file, box, visual, level );
1156 static int isom_read_esds( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1158 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4V_VIDEO )
1159 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO )
1160 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_M4AE_AUDIO )
1161 && !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_MP4S_SYSTEM )
1162 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1163 return isom_read_unknown_box( file, box, parent, level );
1164 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1166 box->type = QT_BOX_TYPE_ESDS;
1167 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_CODEC_TYPE_MP4A_AUDIO ) )
1168 parent->parent->type = QT_CODEC_TYPE_MP4A_AUDIO;
1170 else
1171 box->type = ISOM_BOX_TYPE_ESDS;
1172 ADD_BOX( esds, void );
1173 lsmash_bs_t *bs = file->bs;
1174 esds->ES = mp4sys_get_descriptor( bs, NULL );
1175 if( !esds->ES )
1176 return LSMASH_ERR_INVALID_DATA;
1177 return isom_read_leaf_box_common_last_process( file, box, level, esds );
1180 static int isom_read_btrt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1182 ADD_BOX( btrt, isom_visual_entry_t );
1183 lsmash_bs_t *bs = file->bs;
1184 btrt->bufferSizeDB = lsmash_bs_get_be32( bs );
1185 btrt->maxBitrate = lsmash_bs_get_be32( bs );
1186 btrt->avgBitrate = lsmash_bs_get_be32( bs );
1187 return isom_read_leaf_box_common_last_process( file, box, level, btrt );
1190 static int isom_read_glbl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1192 ADD_BOX( glbl, isom_visual_entry_t );
1193 lsmash_bs_t *bs = file->bs;
1194 uint32_t header_size = box->size - ISOM_BASEBOX_COMMON_SIZE;
1195 if( header_size )
1197 glbl->header_data = lsmash_malloc( header_size );
1198 if( !glbl->header_data )
1199 return LSMASH_ERR_MEMORY_ALLOC;
1200 for( uint32_t i = 0; i < header_size; i++ )
1201 glbl->header_data[i] = lsmash_bs_get_byte( bs );
1203 glbl->header_size = header_size;
1204 return isom_read_leaf_box_common_last_process( file, box, level, glbl );
1207 static int isom_read_clap( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1209 ADD_BOX( clap, isom_visual_entry_t );
1210 lsmash_bs_t *bs = file->bs;
1211 clap->cleanApertureWidthN = lsmash_bs_get_be32( bs );
1212 clap->cleanApertureWidthD = lsmash_bs_get_be32( bs );
1213 clap->cleanApertureHeightN = lsmash_bs_get_be32( bs );
1214 clap->cleanApertureHeightD = lsmash_bs_get_be32( bs );
1215 clap->horizOffN = lsmash_bs_get_be32( bs );
1216 clap->horizOffD = lsmash_bs_get_be32( bs );
1217 clap->vertOffN = lsmash_bs_get_be32( bs );
1218 clap->vertOffD = lsmash_bs_get_be32( bs );
1219 return isom_read_leaf_box_common_last_process( file, box, level, clap );
1222 static int isom_read_pasp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1224 ADD_BOX( pasp, isom_visual_entry_t );
1225 lsmash_bs_t *bs = file->bs;
1226 pasp->hSpacing = lsmash_bs_get_be32( bs );
1227 pasp->vSpacing = lsmash_bs_get_be32( bs );
1228 return isom_read_leaf_box_common_last_process( file, box, level, pasp );
1231 static int isom_read_colr( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1233 ADD_BOX( colr, isom_visual_entry_t );
1234 lsmash_bs_t *bs = file->bs;
1235 colr->color_parameter_type = lsmash_bs_get_be32( bs );
1236 if( colr->color_parameter_type == QT_COLOR_PARAMETER_TYPE_NCLC
1237 || colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1239 colr->primaries_index = lsmash_bs_get_be16( bs );
1240 colr->transfer_function_index = lsmash_bs_get_be16( bs );
1241 colr->matrix_index = lsmash_bs_get_be16( bs );
1242 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
1244 if( lsmash_bs_count( bs ) < box->size )
1246 uint8_t temp8 = lsmash_bs_get_byte( bs );
1247 colr->full_range_flag = (temp8 >> 7) & 0x01;
1248 colr->reserved = temp8 & 0x7f;
1250 else
1252 /* It seems this box is broken or incomplete. */
1253 box->manager |= LSMASH_INCOMPLETE_BOX;
1254 colr->full_range_flag = 0;
1255 colr->reserved = 0;
1258 else
1259 box->manager |= LSMASH_QTFF_BASE;
1261 box->type = (box->manager & LSMASH_QTFF_BASE) ? QT_BOX_TYPE_COLR : ISOM_BOX_TYPE_COLR;
1262 return isom_read_leaf_box_common_last_process( file, box, level, colr );
1265 static int isom_read_gama( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1267 ADD_BOX( gama, isom_visual_entry_t );
1268 lsmash_bs_t *bs = file->bs;
1269 gama->level = lsmash_bs_get_be32( bs );
1270 return isom_read_leaf_box_common_last_process( file, box, level, gama );
1273 static int isom_read_fiel( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1275 ADD_BOX( fiel, isom_visual_entry_t );
1276 lsmash_bs_t *bs = file->bs;
1277 fiel->fields = lsmash_bs_get_byte( bs );
1278 fiel->detail = lsmash_bs_get_byte( bs );
1279 return isom_read_leaf_box_common_last_process( file, box, level, fiel );
1282 static int isom_read_cspc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1284 ADD_BOX( cspc, isom_visual_entry_t );
1285 lsmash_bs_t *bs = file->bs;
1286 cspc->pixel_format = lsmash_bs_get_be32( bs );
1287 return isom_read_leaf_box_common_last_process( file, box, level, cspc );
1290 static int isom_read_sgbt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1292 ADD_BOX( sgbt, isom_visual_entry_t );
1293 lsmash_bs_t *bs = file->bs;
1294 sgbt->significantBits = lsmash_bs_get_byte( bs );
1295 return isom_read_leaf_box_common_last_process( file, box, level, sgbt );
1298 static int isom_read_stsl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1300 ADD_BOX( stsl, isom_visual_entry_t );
1301 lsmash_bs_t *bs = file->bs;
1302 stsl->constraint_flag = lsmash_bs_get_byte( bs );
1303 stsl->scale_method = lsmash_bs_get_byte( bs );
1304 stsl->display_center_x = lsmash_bs_get_be16( bs );
1305 stsl->display_center_y = lsmash_bs_get_be16( bs );
1306 return isom_read_leaf_box_common_last_process( file, box, level, stsl );
1309 static int isom_read_audio_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1311 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1312 return isom_read_unknown_box( file, box, parent, level );
1313 isom_audio_entry_t *audio = (isom_audio_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1314 if( !audio )
1315 return LSMASH_ERR_MEMORY_ALLOC;
1316 lsmash_bs_t *bs = file->bs;
1317 for( int i = 0; i < 6; i++ )
1318 audio->reserved[i] = lsmash_bs_get_byte( bs );
1319 audio->data_reference_index = lsmash_bs_get_be16( bs );
1320 audio->version = lsmash_bs_get_be16( bs );
1321 audio->revision_level = lsmash_bs_get_be16( bs );
1322 audio->vendor = lsmash_bs_get_be32( bs );
1323 audio->channelcount = lsmash_bs_get_be16( bs );
1324 audio->samplesize = lsmash_bs_get_be16( bs );
1325 audio->compression_ID = lsmash_bs_get_be16( bs );
1326 audio->packet_size = lsmash_bs_get_be16( bs );
1327 audio->samplerate = lsmash_bs_get_be32( bs );
1328 if( audio->version == 0 && isom_is_qt_audio( box->type ) )
1330 /* Skip weird extra bytes.
1331 * About QTFF, extensions were first added with Sound Sample Description v1. */
1332 while( lsmash_bs_count( bs ) + ISOM_BASEBOX_COMMON_SIZE <= box->size )
1334 uint32_t size = lsmash_bs_show_be32( bs, 0 );
1335 if( size == 0 || lsmash_bs_count( bs ) + size > box->size )
1336 lsmash_bs_skip_bytes( bs, 1 );
1337 else
1338 break;
1341 else if( audio->version == 1 )
1343 if( ((isom_stsd_t *)parent)->version == 0 )
1345 audio->samplesPerPacket = lsmash_bs_get_be32( bs );
1346 audio->bytesPerPacket = lsmash_bs_get_be32( bs );
1347 audio->bytesPerFrame = lsmash_bs_get_be32( bs );
1348 audio->bytesPerSample = lsmash_bs_get_be32( bs );
1349 box->manager |= LSMASH_QTFF_BASE;
1351 else
1352 /* AudioSampleEntryV1 has no additional fields. */
1353 box->manager &= ~LSMASH_QTFF_BASE;
1355 else if( audio->version == 2 )
1357 audio->sizeOfStructOnly = lsmash_bs_get_be32( bs );
1358 audio->audioSampleRate = lsmash_bs_get_be64( bs );
1359 audio->numAudioChannels = lsmash_bs_get_be32( bs );
1360 audio->always7F000000 = lsmash_bs_get_be32( bs );
1361 audio->constBitsPerChannel = lsmash_bs_get_be32( bs );
1362 audio->formatSpecificFlags = lsmash_bs_get_be32( bs );
1363 audio->constBytesPerAudioPacket = lsmash_bs_get_be32( bs );
1364 audio->constLPCMFramesPerAudioPacket = lsmash_bs_get_be32( bs );
1365 box->manager |= LSMASH_QTFF_BASE;
1367 box->parent = parent;
1368 box->manager |= LSMASH_AUDIO_DESCRIPTION;
1369 isom_box_common_copy( audio, box );
1370 int ret = isom_add_print_func( file, audio, level );
1371 if( ret < 0 )
1372 return ret;
1373 return isom_read_children( file, box, audio, level );
1376 static int isom_read_wave( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1378 ADD_BOX( wave, isom_audio_entry_t );
1379 isom_box_common_copy( wave, box );
1380 int ret = isom_add_print_func( file, wave, level );
1381 if( ret < 0 )
1382 return ret;
1383 return isom_read_children( file, box, wave, level );
1386 static int isom_read_frma( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1388 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->frma )
1389 return isom_read_unknown_box( file, box, parent, level );
1390 ADD_BOX( frma, isom_wave_t );
1391 lsmash_bs_t *bs = file->bs;
1392 frma->data_format = lsmash_bs_get_be32( bs );
1393 return isom_read_leaf_box_common_last_process( file, box, level, frma );
1396 static int isom_read_enda( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1398 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->enda )
1399 return isom_read_unknown_box( file, box, parent, level );
1400 ADD_BOX( enda, isom_wave_t );
1401 lsmash_bs_t *bs = file->bs;
1402 enda->littleEndian = lsmash_bs_get_be16( bs );
1403 return isom_read_leaf_box_common_last_process( file, box, level, enda );
1406 static int isom_read_terminator( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1408 if( !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) || ((isom_wave_t *)parent)->terminator )
1409 return isom_read_unknown_box( file, box, parent, level );
1410 ADD_BOX( terminator, isom_wave_t );
1411 return isom_read_leaf_box_common_last_process( file, box, level, terminator );
1414 static int isom_read_chan( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1416 ADD_BOX( chan, isom_audio_entry_t );
1417 lsmash_bs_t *bs = file->bs;
1418 chan->channelLayoutTag = lsmash_bs_get_be32( bs );
1419 chan->channelBitmap = lsmash_bs_get_be32( bs );
1420 chan->numberChannelDescriptions = lsmash_bs_get_be32( bs );
1421 if( chan->numberChannelDescriptions )
1423 isom_channel_description_t *desc = lsmash_malloc( chan->numberChannelDescriptions * sizeof(isom_channel_description_t) );
1424 if( !desc )
1425 return LSMASH_ERR_MEMORY_ALLOC;
1426 chan->channelDescriptions = desc;
1427 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
1429 desc->channelLabel = lsmash_bs_get_be32( bs );
1430 desc->channelFlags = lsmash_bs_get_be32( bs );
1431 for( int j = 0; j < 3; j++ )
1432 desc->coordinates[j] = lsmash_bs_get_be32( bs );
1435 /* A 'chan' box often contains extra 20 bytes (= the number of bytes of one channel description). */
1436 isom_skip_box_rest( bs, box );
1437 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1440 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1442 ADD_BOX( srat, isom_audio_entry_t );
1443 lsmash_bs_t *bs = file->bs;
1444 srat->sampling_rate = lsmash_bs_get_be32( bs );
1445 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1448 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1450 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1451 return isom_read_unknown_box( file, box, parent, level );
1452 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1453 if( !text )
1454 return LSMASH_ERR_MEMORY_ALLOC;
1455 lsmash_bs_t *bs = file->bs;
1456 for( int i = 0; i < 6; i++ )
1457 text->reserved[i] = lsmash_bs_get_byte( bs );
1458 text->data_reference_index = lsmash_bs_get_be16( bs );
1459 text->displayFlags = lsmash_bs_get_be32( bs );
1460 text->textJustification = lsmash_bs_get_be32( bs );
1461 for( int i = 0; i < 3; i++ )
1462 text->bgColor[i] = lsmash_bs_get_be16( bs );
1463 text->top = lsmash_bs_get_be16( bs );
1464 text->left = lsmash_bs_get_be16( bs );
1465 text->bottom = lsmash_bs_get_be16( bs );
1466 text->right = lsmash_bs_get_be16( bs );
1467 text->scrpStartChar = lsmash_bs_get_be32( bs );
1468 text->scrpHeight = lsmash_bs_get_be16( bs );
1469 text->scrpAscent = lsmash_bs_get_be16( bs );
1470 text->scrpFont = lsmash_bs_get_be16( bs );
1471 text->scrpFace = lsmash_bs_get_be16( bs );
1472 text->scrpSize = lsmash_bs_get_be16( bs );
1473 for( int i = 0; i < 3; i++ )
1474 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1475 text->font_name_length = lsmash_bs_get_byte( bs );
1476 if( text->font_name_length )
1478 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1479 if( !text->font_name )
1480 return LSMASH_ERR_MEMORY_ALLOC;
1481 for( uint8_t i = 0; i < text->font_name_length; i++ )
1482 text->font_name[i] = lsmash_bs_get_byte( bs );
1483 text->font_name[text->font_name_length] = '\0';
1485 box->parent = parent;
1486 isom_box_common_copy( text, box );
1487 int ret = isom_add_print_func( file, text, level );
1488 if( ret < 0 )
1489 return ret;
1490 return isom_read_children( file, box, text, level );
1493 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1495 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1496 return isom_read_unknown_box( file, box, parent, level );
1497 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1498 if( !tx3g )
1499 return LSMASH_ERR_MEMORY_ALLOC;
1500 lsmash_bs_t *bs = file->bs;
1501 for( int i = 0; i < 6; i++ )
1502 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1503 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1504 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1505 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1506 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1507 for( int i = 0; i < 4; i++ )
1508 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1509 tx3g->top = lsmash_bs_get_be16( bs );
1510 tx3g->left = lsmash_bs_get_be16( bs );
1511 tx3g->bottom = lsmash_bs_get_be16( bs );
1512 tx3g->right = lsmash_bs_get_be16( bs );
1513 tx3g->startChar = lsmash_bs_get_be16( bs );
1514 tx3g->endChar = lsmash_bs_get_be16( bs );
1515 tx3g->font_ID = lsmash_bs_get_be16( bs );
1516 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1517 tx3g->font_size = lsmash_bs_get_byte( bs );
1518 for( int i = 0; i < 4; i++ )
1519 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1520 box->parent = parent;
1521 isom_box_common_copy( tx3g, box );
1522 int ret = isom_add_print_func( file, tx3g, level );
1523 if( ret < 0 )
1524 return ret;
1525 return isom_read_children( file, box, tx3g, level );
1528 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1530 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1531 || ((isom_tx3g_entry_t *)parent)->ftab )
1532 return isom_read_unknown_box( file, box, parent, level );
1533 ADD_BOX( ftab, isom_tx3g_entry_t );
1534 lsmash_bs_t *bs = file->bs;
1535 uint32_t entry_count = lsmash_bs_get_be16( bs );
1536 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1538 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1539 if( !data )
1540 return LSMASH_ERR_MEMORY_ALLOC;
1541 if( lsmash_add_entry( ftab->list, data ) < 0 )
1543 lsmash_free( data );
1544 return LSMASH_ERR_MEMORY_ALLOC;
1546 data->font_ID = lsmash_bs_get_be16( bs );
1547 data->font_name_length = lsmash_bs_get_byte( bs );
1548 if( data->font_name_length )
1550 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1551 if( !data->font_name )
1552 return LSMASH_ERR_MEMORY_ALLOC;
1553 for( uint8_t i = 0; i < data->font_name_length; i++ )
1554 data->font_name[i] = lsmash_bs_get_byte( bs );
1555 data->font_name[data->font_name_length] = '\0';
1558 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1561 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1563 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1564 return isom_read_unknown_box( file, box, parent, level );
1565 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1566 if( !mp4s )
1567 return LSMASH_ERR_MEMORY_ALLOC;
1568 lsmash_bs_t *bs = file->bs;
1569 for( int i = 0; i < 6; i++ )
1570 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1571 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1572 box->parent = parent;
1573 isom_box_common_copy( mp4s, box );
1574 int ret = isom_add_print_func( file, mp4s, level );
1575 if( ret < 0 )
1576 return ret;
1577 return isom_read_children( file, box, mp4s, level );
1580 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1582 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stts )
1583 return isom_read_unknown_box( file, box, parent, level );
1584 ADD_BOX( stts, isom_stbl_t );
1585 lsmash_bs_t *bs = file->bs;
1586 uint32_t entry_count = lsmash_bs_get_be32( bs );
1587 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1589 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1590 if( !data )
1591 return LSMASH_ERR_MEMORY_ALLOC;
1592 if( lsmash_add_entry( stts->list, data ) < 0 )
1594 lsmash_free( data );
1595 return LSMASH_ERR_MEMORY_ALLOC;
1597 data->sample_count = lsmash_bs_get_be32( bs );
1598 data->sample_delta = lsmash_bs_get_be32( bs );
1600 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1603 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1605 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->ctts )
1606 return isom_read_unknown_box( file, box, parent, level );
1607 ADD_BOX( ctts, isom_stbl_t );
1608 lsmash_bs_t *bs = file->bs;
1609 uint32_t entry_count = lsmash_bs_get_be32( bs );
1610 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1612 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1613 if( !data )
1614 return LSMASH_ERR_MEMORY_ALLOC;
1615 if( lsmash_add_entry( ctts->list, data ) < 0 )
1617 lsmash_free( data );
1618 return LSMASH_ERR_MEMORY_ALLOC;
1620 data->sample_count = lsmash_bs_get_be32( bs );
1621 data->sample_offset = lsmash_bs_get_be32( bs );
1623 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1626 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1628 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->cslg )
1629 return isom_read_unknown_box( file, box, parent, level );
1630 ADD_BOX( cslg, isom_stbl_t );
1631 lsmash_bs_t *bs = file->bs;
1632 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1633 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1634 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1635 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1636 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1637 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1640 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1642 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stss )
1643 return isom_read_unknown_box( file, box, parent, level );
1644 ADD_BOX( stss, isom_stbl_t );
1645 lsmash_bs_t *bs = file->bs;
1646 uint32_t entry_count = lsmash_bs_get_be32( bs );
1647 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1649 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1650 if( !data )
1651 return LSMASH_ERR_MEMORY_ALLOC;
1652 if( lsmash_add_entry( stss->list, data ) < 0 )
1654 lsmash_free( data );
1655 return LSMASH_ERR_MEMORY_ALLOC;
1657 data->sample_number = lsmash_bs_get_be32( bs );
1659 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1662 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1664 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stps )
1665 return isom_read_unknown_box( file, box, parent, level );
1666 ADD_BOX( stps, isom_stbl_t );
1667 lsmash_bs_t *bs = file->bs;
1668 uint32_t entry_count = lsmash_bs_get_be32( bs );
1669 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1671 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1672 if( !data )
1673 return LSMASH_ERR_MEMORY_ALLOC;
1674 if( lsmash_add_entry( stps->list, data ) < 0 )
1676 lsmash_free( data );
1677 return LSMASH_ERR_MEMORY_ALLOC;
1679 data->sample_number = lsmash_bs_get_be32( bs );
1681 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1684 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1686 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1687 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1688 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && ((isom_stbl_t *)parent)->sdtp)
1689 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && ((isom_traf_t *)parent)->sdtp))
1690 return isom_read_unknown_box( file, box, parent, level );
1691 ADD_BOX( sdtp, isom_box_t );
1692 lsmash_bs_t *bs = file->bs;
1693 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1695 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1696 if( !data )
1697 return LSMASH_ERR_MEMORY_ALLOC;
1698 if( lsmash_add_entry( sdtp->list, data ) < 0 )
1700 lsmash_free( data );
1701 return LSMASH_ERR_MEMORY_ALLOC;
1703 uint8_t temp = lsmash_bs_get_byte( bs );
1704 data->is_leading = (temp >> 6) & 0x3;
1705 data->sample_depends_on = (temp >> 4) & 0x3;
1706 data->sample_is_depended_on = (temp >> 2) & 0x3;
1707 data->sample_has_redundancy = temp & 0x3;
1709 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1712 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1714 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsc )
1715 return isom_read_unknown_box( file, box, parent, level );
1716 ADD_BOX( stsc, isom_stbl_t );
1717 lsmash_bs_t *bs = file->bs;
1718 uint32_t entry_count = lsmash_bs_get_be32( bs );
1719 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1721 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1722 if( !data )
1723 return LSMASH_ERR_MEMORY_ALLOC;
1724 if( lsmash_add_entry( stsc->list, data ) < 0 )
1726 lsmash_free( data );
1727 return LSMASH_ERR_MEMORY_ALLOC;
1729 data->first_chunk = lsmash_bs_get_be32( bs );
1730 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1731 data->sample_description_index = lsmash_bs_get_be32( bs );
1733 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1736 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1738 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsz )
1739 return isom_read_unknown_box( file, box, parent, level );
1740 ADD_BOX( stsz, isom_stbl_t );
1741 lsmash_bs_t *bs = file->bs;
1742 stsz->sample_size = lsmash_bs_get_be32( bs );
1743 stsz->sample_count = lsmash_bs_get_be32( bs );
1744 uint64_t pos = lsmash_bs_count( bs );
1745 if( pos < box->size )
1747 stsz->list = lsmash_create_entry_list();
1748 if( !stsz->list )
1749 return LSMASH_ERR_MEMORY_ALLOC;
1750 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1752 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1753 if( !data )
1754 return LSMASH_ERR_MEMORY_ALLOC;
1755 if( lsmash_add_entry( stsz->list, data ) < 0 )
1757 lsmash_free( data );
1758 return LSMASH_ERR_MEMORY_ALLOC;
1760 data->entry_size = lsmash_bs_get_be32( bs );
1763 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1766 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1768 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stco )
1769 return isom_read_unknown_box( file, box, parent, level );
1770 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1771 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1772 isom_stco_t *stco = is_stco
1773 ? isom_add_stco( (isom_stbl_t *)parent )
1774 : isom_add_co64( (isom_stbl_t *)parent );
1775 if( !stco )
1776 return LSMASH_ERR_NAMELESS;
1777 lsmash_bs_t *bs = file->bs;
1778 uint32_t entry_count = lsmash_bs_get_be32( bs );
1779 if( is_stco )
1780 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1782 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1783 if( !data )
1784 return LSMASH_ERR_MEMORY_ALLOC;
1785 if( lsmash_add_entry( stco->list, data ) < 0 )
1787 lsmash_free( data );
1788 return LSMASH_ERR_MEMORY_ALLOC;
1790 data->chunk_offset = lsmash_bs_get_be32( bs );
1792 else
1794 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1796 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1797 if( !data )
1798 return LSMASH_ERR_MEMORY_ALLOC;
1799 if( lsmash_add_entry( stco->list, data ) < 0 )
1801 lsmash_free( data );
1802 return LSMASH_ERR_MEMORY_ALLOC;
1804 data->chunk_offset = lsmash_bs_get_be64( bs );
1807 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1810 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1812 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1813 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1814 return isom_read_unknown_box( file, box, parent, level );
1815 ADD_BOX( sgpd, void );
1816 lsmash_bs_t *bs = file->bs;
1817 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1818 if( box->version == 1 )
1819 sgpd->default_length = lsmash_bs_get_be32( bs );
1820 uint32_t entry_count = lsmash_bs_get_be32( bs );
1821 switch( sgpd->grouping_type )
1823 case ISOM_GROUP_TYPE_RAP :
1825 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1827 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1828 if( !data )
1829 return LSMASH_ERR_MEMORY_ALLOC;
1830 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1832 lsmash_free( data );
1833 return LSMASH_ERR_MEMORY_ALLOC;
1835 memset( data, 0, sizeof(isom_rap_entry_t) );
1836 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1837 if( box->version == 1 && !sgpd->default_length )
1838 data->description_length = lsmash_bs_get_be32( bs );
1839 else
1841 uint8_t temp = lsmash_bs_get_byte( bs );
1842 data->num_leading_samples_known = (temp >> 7) & 0x01;
1843 data->num_leading_samples = temp & 0x7f;
1846 break;
1848 case ISOM_GROUP_TYPE_ROLL :
1849 case ISOM_GROUP_TYPE_PROL :
1851 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1853 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1854 if( !data )
1855 return LSMASH_ERR_MEMORY_ALLOC;
1856 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1858 lsmash_free( data );
1859 return LSMASH_ERR_MEMORY_ALLOC;
1861 memset( data, 0, sizeof(isom_roll_entry_t) );
1862 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1863 if( box->version == 1 && !sgpd->default_length )
1864 data->description_length = lsmash_bs_get_be32( bs );
1865 else
1866 data->roll_distance = lsmash_bs_get_be16( bs );
1868 break;
1870 default :
1871 break;
1873 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1876 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1878 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1879 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1880 return isom_read_unknown_box( file, box, parent, level );
1881 ADD_BOX( sbgp, void );
1882 lsmash_bs_t *bs = file->bs;
1883 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1884 if( box->version == 1 )
1885 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1886 uint32_t entry_count = lsmash_bs_get_be32( bs );
1887 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1889 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1890 if( !data )
1891 return LSMASH_ERR_MEMORY_ALLOC;
1892 if( lsmash_add_entry( sbgp->list, data ) < 0 )
1894 lsmash_free( data );
1895 return LSMASH_ERR_MEMORY_ALLOC;
1897 data->sample_count = lsmash_bs_get_be32( bs );
1898 data->group_description_index = lsmash_bs_get_be32( bs );
1900 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1903 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1905 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1906 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1907 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->udta)
1908 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->udta) )
1909 return isom_read_unknown_box( file, box, parent, level );
1910 ADD_BOX( udta, void );
1911 isom_box_common_copy( udta, box );
1912 int ret = isom_add_print_func( file, udta, level );
1913 if( ret < 0 )
1914 return ret;
1915 return isom_read_children( file, box, udta, level );
1918 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1920 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->chpl )
1921 return isom_read_unknown_box( file, box, parent, level );
1922 ADD_BOX( chpl, isom_udta_t );
1923 lsmash_bs_t *bs = file->bs;
1924 uint32_t entry_count;
1925 if( box->version == 1 )
1927 chpl->unknown = lsmash_bs_get_byte( bs );
1928 entry_count = lsmash_bs_get_be32( bs );
1930 else
1931 entry_count = lsmash_bs_get_byte( bs );
1932 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1934 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1935 if( !data )
1936 return LSMASH_ERR_MEMORY_ALLOC;
1937 if( lsmash_add_entry( chpl->list, data ) < 0 )
1939 lsmash_free( data );
1940 return LSMASH_ERR_MEMORY_ALLOC;
1942 data->start_time = lsmash_bs_get_be64( bs );
1943 data->chapter_name_length = lsmash_bs_get_byte( bs );
1944 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1945 if( !data->chapter_name )
1947 lsmash_free( data );
1948 return LSMASH_ERR_MEMORY_ALLOC;
1950 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1951 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1952 data->chapter_name[data->chapter_name_length] = '\0';
1954 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1957 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1959 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvex )
1960 return isom_read_unknown_box( file, box, parent, level );
1961 ADD_BOX( mvex, isom_moov_t );
1962 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1963 isom_box_common_copy( mvex, box );
1964 int ret = isom_add_print_func( file, mvex, level );
1965 if( ret < 0 )
1966 return ret;
1967 return isom_read_children( file, box, mvex, level );
1970 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1972 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) || ((isom_mvex_t *)parent)->mehd )
1973 return isom_read_unknown_box( file, box, parent, level );
1974 ADD_BOX( mehd, isom_mvex_t );
1975 lsmash_bs_t *bs = file->bs;
1976 if( box->version == 1 )
1977 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1978 else
1979 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1980 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1983 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1985 uint32_t temp = lsmash_bs_get_be32( bs );
1986 isom_sample_flags_t flags;
1987 flags.reserved = (temp >> 28) & 0xf;
1988 flags.is_leading = (temp >> 26) & 0x3;
1989 flags.sample_depends_on = (temp >> 24) & 0x3;
1990 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1991 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1992 flags.sample_padding_value = (temp >> 17) & 0x7;
1993 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1994 flags.sample_degradation_priority = temp & 0xffff;
1995 return flags;
1998 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2000 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
2001 return isom_read_unknown_box( file, box, parent, level );
2002 ADD_BOX( trex, isom_mvex_t );
2003 box->parent = parent;
2004 lsmash_bs_t *bs = file->bs;
2005 trex->track_ID = lsmash_bs_get_be32( bs );
2006 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
2007 trex->default_sample_duration = lsmash_bs_get_be32( bs );
2008 trex->default_sample_size = lsmash_bs_get_be32( bs );
2009 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
2010 return isom_read_leaf_box_common_last_process( file, box, level, trex );
2013 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2015 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2016 return isom_read_unknown_box( file, box, parent, level );
2017 ADD_BOX( moof, lsmash_file_t );
2018 box->parent = parent;
2019 isom_box_common_copy( moof, box );
2020 int ret = isom_add_print_func( file, moof, level );
2021 if( ret < 0 )
2022 return ret;
2023 return isom_read_children( file, box, moof, level );
2026 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2028 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) || ((isom_moof_t *)parent)->mfhd )
2029 return isom_read_unknown_box( file, box, parent, level );
2030 ADD_BOX( mfhd, isom_moof_t );
2031 lsmash_bs_t *bs = file->bs;
2032 mfhd->sequence_number = lsmash_bs_get_be32( bs );
2033 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
2036 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2038 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
2039 return isom_read_unknown_box( file, box, parent, level );
2040 ADD_BOX( traf, isom_moof_t );
2041 box->parent = parent;
2042 isom_box_common_copy( traf, box );
2043 int ret = isom_add_print_func( file, traf, level );
2044 if( ret < 0 )
2045 return ret;
2046 return isom_read_children( file, box, traf, level );
2049 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2051 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfhd )
2052 return isom_read_unknown_box( file, box, parent, level );
2053 ADD_BOX( tfhd, isom_traf_t );
2054 lsmash_bs_t *bs = file->bs;
2055 tfhd->track_ID = lsmash_bs_get_be32( bs );
2056 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2057 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2058 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2059 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2060 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2061 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2064 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2066 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfdt )
2067 return isom_read_unknown_box( file, box, parent, level );
2068 ADD_BOX( tfdt, isom_traf_t );
2069 lsmash_bs_t *bs = file->bs;
2070 if( box->version == 1 )
2071 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2072 else
2073 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2074 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2077 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2079 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2080 return isom_read_unknown_box( file, box, parent, level );
2081 ADD_BOX( trun, isom_traf_t );
2082 box->parent = parent;
2083 lsmash_bs_t *bs = file->bs;
2084 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2085 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2086 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2087 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2088 has_optional_rows &= box->flags;
2089 trun->sample_count = lsmash_bs_get_be32( bs );
2090 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2091 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2092 if( trun->sample_count && has_optional_rows )
2094 trun->optional = lsmash_create_entry_list();
2095 if( !trun->optional )
2096 return LSMASH_ERR_MEMORY_ALLOC;
2097 for( uint32_t i = 0; i < trun->sample_count; i++ )
2099 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2100 if( !data )
2101 return LSMASH_ERR_MEMORY_ALLOC;
2102 if( lsmash_add_entry( trun->optional, data ) < 0 )
2104 lsmash_free( data );
2105 return LSMASH_ERR_MEMORY_ALLOC;
2107 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2108 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2109 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2110 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2113 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2116 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2118 if( file->fake_file_mode )
2119 return isom_read_unknown_box( file, box, parent, level );
2120 isom_box_t *skip = lsmash_malloc_zero( sizeof(isom_box_t) );
2121 if( !skip )
2122 return LSMASH_ERR_MEMORY_ALLOC;
2123 isom_skip_box_rest( file->bs, box );
2124 box->manager |= LSMASH_ABSENT_IN_FILE;
2125 isom_box_common_copy( skip, box );
2126 int ret = isom_add_print_func( file, skip, level );
2127 if( ret < 0 )
2129 lsmash_free( skip );
2130 return ret;
2132 return 0;
2135 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2137 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2138 return isom_read_unknown_box( file, box, parent, level );
2139 isom_box_t *mdat = lsmash_malloc_zero( sizeof(isom_box_t) );
2140 if( !mdat )
2141 return LSMASH_ERR_MEMORY_ALLOC;
2142 isom_skip_box_rest( file->bs, box );
2143 box->manager |= LSMASH_ABSENT_IN_FILE;
2144 file->flags |= LSMASH_FILE_MODE_MEDIA;
2145 isom_box_common_copy( mdat, box );
2146 int ret = isom_add_print_func( file, mdat, level );
2147 if( ret < 0 )
2149 lsmash_free( mdat );
2150 return ret;
2152 return 0;
2155 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2157 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2158 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2159 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2160 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2161 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && ((lsmash_file_t *)parent)->meta)
2162 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->meta)
2163 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->meta)
2164 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && ((isom_udta_t *)parent)->meta) )
2165 return isom_read_unknown_box( file, box, parent, level );
2166 ADD_BOX( meta, void );
2167 isom_box_common_copy( meta, box );
2168 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2169 if( is_qtff )
2171 box->manager |= LSMASH_QTFF_BASE;
2172 meta->manager |= LSMASH_QTFF_BASE;
2174 int ret = isom_add_print_func( file, meta, level );
2175 if( ret < 0 )
2176 return ret;
2177 return isom_read_children( file, box, meta, level );
2180 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2182 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2183 || ((isom_meta_t *)parent)->keys )
2184 return isom_read_unknown_box( file, box, parent, level );
2185 ADD_BOX( keys, isom_meta_t );
2186 lsmash_bs_t *bs = file->bs;
2187 uint32_t entry_count = lsmash_bs_get_be32( bs );
2188 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2190 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2191 if( !data )
2192 return LSMASH_ERR_MEMORY_ALLOC;
2193 if( lsmash_add_entry( keys->list, data ) < 0 )
2195 lsmash_free( data );
2196 return LSMASH_ERR_MEMORY_ALLOC;
2198 data->key_size = lsmash_bs_get_be32( bs );
2199 data->key_namespace = lsmash_bs_get_be32( bs );
2200 if( data->key_size > 8 )
2202 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2203 if( !data->key_value )
2204 return LSMASH_ERR_NAMELESS;
2206 else
2207 data->key_value = NULL;
2209 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2212 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2214 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2215 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2216 || ((isom_meta_t *)parent)->ilst )
2217 return isom_read_unknown_box( file, box, parent, level );
2218 ADD_BOX( ilst, isom_meta_t );
2219 isom_box_common_copy( ilst, box );
2220 int ret = isom_add_print_func( file, ilst, level );
2221 if( ret < 0 )
2222 return ret;
2223 return isom_read_children( file, box, ilst, level );
2226 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2228 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2229 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2230 return isom_read_unknown_box( file, box, parent, level );
2231 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2232 if( !metaitem )
2233 return -1;
2234 box->parent = parent;
2235 isom_box_common_copy( metaitem, box );
2236 int ret = isom_add_print_func( file, metaitem, level );
2237 if( ret < 0 )
2238 return ret;
2239 return isom_read_children( file, box, metaitem, level );
2242 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2244 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->mean )
2245 return isom_read_unknown_box( file, box, parent, level );
2246 ADD_BOX( mean, isom_metaitem_t );
2247 lsmash_bs_t *bs = file->bs;
2248 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2249 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2250 if( !mean->meaning_string )
2251 return LSMASH_ERR_NAMELESS;
2252 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2255 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2257 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->name )
2258 return isom_read_unknown_box( file, box, parent, level );
2259 ADD_BOX( name, isom_metaitem_t );
2260 lsmash_bs_t *bs = file->bs;
2261 name->name_length = box->size - lsmash_bs_count( bs );
2262 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2263 if( !name->name )
2264 return LSMASH_ERR_NAMELESS;
2265 return isom_read_leaf_box_common_last_process( file, box, level, name );
2268 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2270 if( ((isom_metaitem_t *)parent)->data )
2271 return isom_read_unknown_box( file, box, parent, level );
2272 ADD_BOX( data, isom_metaitem_t );
2273 lsmash_bs_t *bs = file->bs;
2274 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2275 data->reserved = lsmash_bs_get_be16( bs );
2276 data->type_set_identifier = lsmash_bs_get_byte( bs );
2277 data->type_code = lsmash_bs_get_byte( bs );
2278 data->the_locale = lsmash_bs_get_be32( bs );
2279 if( data->value_length )
2281 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2282 if( !data->value )
2283 return LSMASH_ERR_NAMELESS;
2285 return isom_read_leaf_box_common_last_process( file, box, level, data );
2288 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2290 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->WLOC )
2291 return isom_read_unknown_box( file, box, parent, level );
2292 ADD_BOX( WLOC, isom_udta_t );
2293 lsmash_bs_t *bs = file->bs;
2294 WLOC->x = lsmash_bs_get_be16( bs );
2295 WLOC->y = lsmash_bs_get_be16( bs );
2296 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2299 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2301 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->LOOP )
2302 return isom_read_unknown_box( file, box, parent, level );
2303 ADD_BOX( LOOP, isom_udta_t );
2304 lsmash_bs_t *bs = file->bs;
2305 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2306 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2309 static int isom_read_SelO( 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_UDTA ) || ((isom_udta_t *)parent)->SelO )
2312 return isom_read_unknown_box( file, box, parent, level );
2313 ADD_BOX( SelO, isom_udta_t );
2314 lsmash_bs_t *bs = file->bs;
2315 SelO->selection_only = lsmash_bs_get_byte( bs );
2316 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2319 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2321 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->AllF )
2322 return isom_read_unknown_box( file, box, parent, level );
2323 ADD_BOX( AllF, isom_udta_t );
2324 lsmash_bs_t *bs = file->bs;
2325 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2326 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2329 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2331 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2332 return isom_read_unknown_box( file, box, parent, level );
2333 ADD_BOX( cprt, isom_udta_t );
2334 box->parent = parent;
2335 lsmash_bs_t *bs = file->bs;
2336 cprt->language = lsmash_bs_get_be16( bs );
2337 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2338 if( cprt->notice_length )
2340 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2341 if( !cprt->notice )
2343 cprt->notice_length = 0;
2344 return LSMASH_ERR_NAMELESS;
2347 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2350 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2352 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->mfra )
2353 return isom_read_unknown_box( file, box, parent, level );
2354 ADD_BOX( mfra, lsmash_file_t );
2355 isom_box_common_copy( mfra, box );
2356 int ret = isom_add_print_func( file, mfra, level );
2357 if( ret < 0 )
2358 return ret;
2359 return isom_read_children( file, box, mfra, level );
2362 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2364 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2365 return isom_read_unknown_box( file, box, parent, level );
2366 ADD_BOX( tfra, isom_mfra_t );
2367 box->parent = parent;
2368 lsmash_bs_t *bs = file->bs;
2369 tfra->track_ID = lsmash_bs_get_be32( bs );
2370 uint32_t temp = lsmash_bs_get_be32( bs );
2371 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2372 tfra->reserved = (temp >> 6) & 0x3ffffff;
2373 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2374 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2375 tfra->length_size_of_sample_num = temp & 0x3;
2376 if( tfra->number_of_entry )
2378 tfra->list = lsmash_create_entry_list();
2379 if( !tfra->list )
2380 return LSMASH_ERR_MEMORY_ALLOC;
2381 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2383 lsmash_bs_get_byte_to_64,
2384 lsmash_bs_get_be16_to_64,
2385 lsmash_bs_get_be24_to_64,
2386 lsmash_bs_get_be32_to_64,
2387 lsmash_bs_get_be64
2389 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2390 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2391 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2392 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2393 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2394 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2396 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2397 if( !data )
2398 return LSMASH_ERR_MEMORY_ALLOC;
2399 if( lsmash_add_entry( tfra->list, data ) < 0 )
2401 lsmash_free( data );
2402 return LSMASH_ERR_MEMORY_ALLOC;
2404 data->time = bs_put_time ( bs );
2405 data->moof_offset = bs_put_moof_offset ( bs );
2406 data->traf_number = bs_put_traf_number ( bs );
2407 data->trun_number = bs_put_trun_number ( bs );
2408 data->sample_number = bs_put_sample_number( bs );
2411 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2414 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2416 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) || ((isom_mfra_t *)parent)->mfro )
2417 return isom_read_unknown_box( file, box, parent, level );
2418 ADD_BOX( mfro, isom_mfra_t );
2419 lsmash_bs_t *bs = file->bs;
2420 mfro->length = lsmash_bs_get_be32( bs );
2421 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2424 static inline void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2426 if( !bs->unseekable )
2427 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2428 else
2429 lsmash_bs_skip_bytes_64( bs, size );
2432 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2434 lsmash_bs_t *bs = file->bs;
2435 /* Skip extra bytes of the parent box if any. */
2436 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2438 uint64_t extra_bytes = parent->size - parent_pos;
2439 isom_read_skip_extra_bytes( bs, extra_bytes );
2440 /* This is not the size of a box but makes sense in isom_read_children(). */
2441 box->size = extra_bytes;
2442 return 1;
2444 /* Check if the size is valid or not. */
2445 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2447 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2448 if( size > 1
2449 && size < ISOM_BASEBOX_COMMON_SIZE )
2451 /* It seems we are still within the box considered as previous.
2452 * Skip bytes up to the next box. */
2453 isom_read_skip_extra_bytes( bs, parent->size - parent_pos );
2454 box->size = 0;
2455 return 1;
2457 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2458 size = lsmash_bs_show_be64( bs, 8 );
2459 if( size == 0 && parent != (isom_box_t *)file )
2461 /* Check if this box is actually the last box or not. */
2462 size = parent->size - parent_pos;
2463 uint64_t extra_bytes;
2464 if( !bs->unseekable )
2465 extra_bytes = bs->written - lsmash_bs_get_stream_pos( bs );
2466 else
2468 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2469 while( size < extra_bytes )
2471 int ret = lsmash_bs_read( bs, 1 );
2472 if( bs->eof || ret < 0 )
2473 break;
2474 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2477 if( size != extra_bytes )
2479 /* This is not the size of the last box.
2480 * It seems we are still within the box considered as previous.
2481 * Skip bytes up to the next box. */
2482 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2483 box->size = 0;
2484 return 1;
2488 return 0;
2491 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2493 assert( parent && parent->root && parent->file );
2494 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2495 return 0;
2496 memset( box, 0, sizeof(isom_box_t) );
2497 box->root = parent->root;
2498 box->file = parent->file;
2499 box->parent = parent;
2500 lsmash_bs_t *bs = file->bs;
2501 int ret = isom_bs_read_box_common( bs, box );
2502 if( !!ret )
2503 return ret; /* return if reached EOF */
2504 ++level;
2505 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2506 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2507 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2509 /* Check whether CODEC is RAW Video/Audio encapsulated in QTFF. */
2510 if( box->type.fourcc == LSMASH_CODEC_TYPE_RAW.fourcc )
2512 if( ((isom_minf_t *)parent->parent->parent)->vmhd )
2514 form_box_type_func = lsmash_form_qtff_box_type;
2515 reader_func = isom_read_visual_description;
2517 else if( ((isom_minf_t *)parent->parent->parent)->smhd )
2519 form_box_type_func = lsmash_form_qtff_box_type;
2520 reader_func = isom_read_audio_description;
2522 goto read_box;
2524 static struct description_reader_table_tag
2526 lsmash_compact_box_type_t fourcc;
2527 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2528 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2529 } description_reader_table[160] = { { 0, NULL, NULL } };
2530 if( !description_reader_table[0].reader_func )
2532 /* Initialize the table. */
2533 int i = 0;
2534 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2535 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2549 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2551 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2576 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2632 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type, isom_read_audio_description );
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type, isom_read_qt_text_description );
2664 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type, isom_read_tx3g_description );
2665 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type, isom_read_mp4s_description );
2666 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL, NULL );
2667 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2669 for( int i = 0; description_reader_table[i].reader_func; i++ )
2670 if( box->type.fourcc == description_reader_table[i].fourcc )
2672 form_box_type_func = description_reader_table[i].form_box_type_func;
2673 reader_func = description_reader_table[i].reader_func;
2674 goto read_box;
2676 goto read_box;
2678 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2680 form_box_type_func = lsmash_form_qtff_box_type;
2681 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2682 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2683 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2684 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2685 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2686 else reader_func = isom_read_codec_specific;
2687 goto read_box;
2689 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2691 form_box_type_func = lsmash_form_iso_box_type;
2692 reader_func = isom_read_track_reference_type;
2693 goto read_box;
2695 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2697 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2698 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2699 form_box_type_func = lsmash_form_iso_box_type;
2700 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2701 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2702 form_box_type_func = lsmash_form_qtff_box_type;
2703 reader_func = isom_read_dref_entry;
2704 goto read_box;
2706 static struct box_reader_table_tag
2708 lsmash_compact_box_type_t fourcc;
2709 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2710 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2711 } box_reader_table[128] = { { 0, NULL, NULL } };
2712 if( !box_reader_table[0].reader_func )
2714 /* Initialize the table. */
2715 int i = 0;
2716 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2717 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2718 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2719 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2720 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2721 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2722 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2724 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2726 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2727 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2728 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2729 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2730 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2731 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2732 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2733 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2734 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2735 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2736 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2737 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2738 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2739 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2740 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2741 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2742 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2743 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2744 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2745 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2746 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2747 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2748 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2749 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2750 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2753 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2754 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2755 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2756 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2757 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2758 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2760 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2761 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2762 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2763 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2768 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2769 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2773 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2774 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2775 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2776 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2777 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2778 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2779 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2780 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2781 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2783 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2786 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2787 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2788 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2789 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2792 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2794 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2796 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2797 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2798 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2799 #undef ADD_BOX_READER_TABLE_ELEMENT
2801 for( int i = 0; box_reader_table[i].reader_func; i++ )
2802 if( box->type.fourcc == box_reader_table[i].fourcc )
2804 form_box_type_func = box_reader_table[i].form_box_type_func;
2805 reader_func = box_reader_table[i].reader_func;
2806 goto read_box;
2808 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2810 if( lsmash_bs_is_end ( bs, 3 ) == 0
2811 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2812 form_box_type_func = lsmash_form_iso_box_type;
2813 else
2814 form_box_type_func = lsmash_form_qtff_box_type;
2815 reader_func = isom_read_meta;
2816 goto read_box;
2818 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2820 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2821 form_box_type_func = lsmash_form_iso_box_type;
2822 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2823 form_box_type_func = lsmash_form_qtff_box_type;
2824 if( form_box_type_func )
2826 reader_func = isom_read_ilst;
2827 goto read_box;
2830 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2831 form_box_type_func = lsmash_form_iso_box_type;
2832 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2833 form_box_type_func = lsmash_form_qtff_box_type;
2834 if( form_box_type_func )
2836 reader_func = isom_read_metaitem;
2837 goto read_box;
2839 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2841 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2842 reader_func = isom_read_mean;
2843 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2844 reader_func = isom_read_name;
2845 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2846 reader_func = isom_read_data;
2847 if( reader_func )
2849 form_box_type_func = lsmash_form_iso_box_type;
2850 goto read_box;
2853 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2855 /* Avoid confusing udta.cprt with ilst.cprt. */
2856 form_box_type_func = lsmash_form_iso_box_type;
2857 reader_func = isom_read_cprt;
2858 goto read_box;
2860 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2862 static struct codec_specific_marker_table_tag
2864 lsmash_compact_box_type_t fourcc;
2865 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2866 } codec_specific_marker_table[16] = { { 0, NULL } };
2867 if( !codec_specific_marker_table[0].form_box_type_func )
2869 /* Initialize the table. */
2870 int i = 0;
2871 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2872 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2873 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type );
2874 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type );
2875 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type );
2876 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type );
2877 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type );
2878 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type );
2879 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type );
2880 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type );
2881 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type );
2882 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type );
2883 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2884 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2886 for( int i = 0; codec_specific_marker_table[i].form_box_type_func; i++ )
2887 if( box->type.fourcc == codec_specific_marker_table[i].fourcc )
2889 form_box_type_func = codec_specific_marker_table[i].form_box_type_func;
2890 break;
2892 reader_func = isom_read_codec_specific;
2894 read_box:
2895 if( form_box_type_func )
2896 box->type = form_box_type_func( box->type.fourcc );
2897 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2898 return ret;
2899 return reader_func
2900 ? reader_func( file, box, parent, level )
2901 : isom_read_unknown_box( file, box, parent, level );
2904 int isom_read_file( lsmash_file_t *file )
2906 lsmash_bs_t *bs = file->bs;
2907 if( !bs )
2908 return LSMASH_ERR_NAMELESS;
2909 /* Reset the counter so that we can use it to get position within the box. */
2910 lsmash_bs_reset_counter( bs );
2911 if( file->flags & LSMASH_FILE_MODE_DUMP )
2913 file->print = lsmash_create_entry_list();
2914 if( !file->print )
2915 return LSMASH_ERR_MEMORY_ALLOC;
2917 file->size = UINT64_MAX;
2918 isom_box_t box;
2919 int ret = isom_read_children( file, &box, file, 0 );
2920 file->size = box.size;
2921 lsmash_bs_empty( bs );
2922 bs->error = 0; /* Clear error flag. */
2923 if( ret < 0 )
2924 return ret;
2925 return isom_check_compatibility( file );