hevc: Fix infinite loop when series of byte stream end by
[L-SMASH.git] / core / read.c
blobe856338727f312bdb46a237abe3031156f1cf1f8
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 return isom_read_leaf_box_common_last_process( file, box, level, chan );
1438 static int isom_read_srat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1440 ADD_BOX( srat, isom_audio_entry_t );
1441 lsmash_bs_t *bs = file->bs;
1442 srat->sampling_rate = lsmash_bs_get_be32( bs );
1443 return isom_read_leaf_box_common_last_process( file, box, level, srat );
1446 static int isom_read_qt_text_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1448 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1449 return isom_read_unknown_box( file, box, parent, level );
1450 isom_qt_text_entry_t *text = (isom_qt_text_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1451 if( !text )
1452 return LSMASH_ERR_MEMORY_ALLOC;
1453 lsmash_bs_t *bs = file->bs;
1454 for( int i = 0; i < 6; i++ )
1455 text->reserved[i] = lsmash_bs_get_byte( bs );
1456 text->data_reference_index = lsmash_bs_get_be16( bs );
1457 text->displayFlags = lsmash_bs_get_be32( bs );
1458 text->textJustification = lsmash_bs_get_be32( bs );
1459 for( int i = 0; i < 3; i++ )
1460 text->bgColor[i] = lsmash_bs_get_be16( bs );
1461 text->top = lsmash_bs_get_be16( bs );
1462 text->left = lsmash_bs_get_be16( bs );
1463 text->bottom = lsmash_bs_get_be16( bs );
1464 text->right = lsmash_bs_get_be16( bs );
1465 text->scrpStartChar = lsmash_bs_get_be32( bs );
1466 text->scrpHeight = lsmash_bs_get_be16( bs );
1467 text->scrpAscent = lsmash_bs_get_be16( bs );
1468 text->scrpFont = lsmash_bs_get_be16( bs );
1469 text->scrpFace = lsmash_bs_get_be16( bs );
1470 text->scrpSize = lsmash_bs_get_be16( bs );
1471 for( int i = 0; i < 3; i++ )
1472 text->scrpColor[i] = lsmash_bs_get_be16( bs );
1473 text->font_name_length = lsmash_bs_get_byte( bs );
1474 if( text->font_name_length )
1476 text->font_name = lsmash_malloc( text->font_name_length + 1 );
1477 if( !text->font_name )
1478 return LSMASH_ERR_MEMORY_ALLOC;
1479 for( uint8_t i = 0; i < text->font_name_length; i++ )
1480 text->font_name[i] = lsmash_bs_get_byte( bs );
1481 text->font_name[text->font_name_length] = '\0';
1483 box->parent = parent;
1484 isom_box_common_copy( text, box );
1485 int ret = isom_add_print_func( file, text, level );
1486 if( ret < 0 )
1487 return ret;
1488 return isom_read_children( file, box, text, level );
1491 static int isom_read_tx3g_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1493 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1494 return isom_read_unknown_box( file, box, parent, level );
1495 isom_tx3g_entry_t *tx3g = (isom_tx3g_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1496 if( !tx3g )
1497 return LSMASH_ERR_MEMORY_ALLOC;
1498 lsmash_bs_t *bs = file->bs;
1499 for( int i = 0; i < 6; i++ )
1500 tx3g->reserved[i] = lsmash_bs_get_byte( bs );
1501 tx3g->data_reference_index = lsmash_bs_get_be16( bs );
1502 tx3g->displayFlags = lsmash_bs_get_be32( bs );
1503 tx3g->horizontal_justification = lsmash_bs_get_byte( bs );
1504 tx3g->vertical_justification = lsmash_bs_get_byte( bs );
1505 for( int i = 0; i < 4; i++ )
1506 tx3g->background_color_rgba[i] = lsmash_bs_get_byte( bs );
1507 tx3g->top = lsmash_bs_get_be16( bs );
1508 tx3g->left = lsmash_bs_get_be16( bs );
1509 tx3g->bottom = lsmash_bs_get_be16( bs );
1510 tx3g->right = lsmash_bs_get_be16( bs );
1511 tx3g->startChar = lsmash_bs_get_be16( bs );
1512 tx3g->endChar = lsmash_bs_get_be16( bs );
1513 tx3g->font_ID = lsmash_bs_get_be16( bs );
1514 tx3g->face_style_flags = lsmash_bs_get_byte( bs );
1515 tx3g->font_size = lsmash_bs_get_byte( bs );
1516 for( int i = 0; i < 4; i++ )
1517 tx3g->text_color_rgba[i] = lsmash_bs_get_byte( bs );
1518 box->parent = parent;
1519 isom_box_common_copy( tx3g, box );
1520 int ret = isom_add_print_func( file, tx3g, level );
1521 if( ret < 0 )
1522 return ret;
1523 return isom_read_children( file, box, tx3g, level );
1526 static int isom_read_ftab( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1528 if( !lsmash_check_box_type_identical( parent->type, ISOM_CODEC_TYPE_TX3G_TEXT )
1529 || ((isom_tx3g_entry_t *)parent)->ftab )
1530 return isom_read_unknown_box( file, box, parent, level );
1531 ADD_BOX( ftab, isom_tx3g_entry_t );
1532 lsmash_bs_t *bs = file->bs;
1533 uint32_t entry_count = lsmash_bs_get_be16( bs );
1534 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ftab->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1536 isom_font_record_t *data = lsmash_malloc_zero( sizeof(isom_font_record_t) );
1537 if( !data )
1538 return LSMASH_ERR_MEMORY_ALLOC;
1539 if( lsmash_add_entry( ftab->list, data ) < 0 )
1541 lsmash_free( data );
1542 return LSMASH_ERR_MEMORY_ALLOC;
1544 data->font_ID = lsmash_bs_get_be16( bs );
1545 data->font_name_length = lsmash_bs_get_byte( bs );
1546 if( data->font_name_length )
1548 data->font_name = lsmash_malloc( data->font_name_length + 1 );
1549 if( !data->font_name )
1550 return LSMASH_ERR_MEMORY_ALLOC;
1551 for( uint8_t i = 0; i < data->font_name_length; i++ )
1552 data->font_name[i] = lsmash_bs_get_byte( bs );
1553 data->font_name[data->font_name_length] = '\0';
1556 return isom_read_leaf_box_common_last_process( file, box, level, ftab );
1559 static int isom_read_mp4s_description( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1561 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1562 return isom_read_unknown_box( file, box, parent, level );
1563 isom_mp4s_entry_t *mp4s = (isom_mp4s_entry_t *)isom_add_description( box->type, (isom_stsd_t *)parent );
1564 if( !mp4s )
1565 return LSMASH_ERR_MEMORY_ALLOC;
1566 lsmash_bs_t *bs = file->bs;
1567 for( int i = 0; i < 6; i++ )
1568 mp4s->reserved[i] = lsmash_bs_get_byte( bs );
1569 mp4s->data_reference_index = lsmash_bs_get_be16( bs );
1570 box->parent = parent;
1571 isom_box_common_copy( mp4s, box );
1572 int ret = isom_add_print_func( file, mp4s, level );
1573 if( ret < 0 )
1574 return ret;
1575 return isom_read_children( file, box, mp4s, level );
1578 static int isom_read_stts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1580 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stts )
1581 return isom_read_unknown_box( file, box, parent, level );
1582 ADD_BOX( stts, isom_stbl_t );
1583 lsmash_bs_t *bs = file->bs;
1584 uint32_t entry_count = lsmash_bs_get_be32( bs );
1585 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1587 isom_stts_entry_t *data = lsmash_malloc( sizeof(isom_stts_entry_t) );
1588 if( !data )
1589 return LSMASH_ERR_MEMORY_ALLOC;
1590 if( lsmash_add_entry( stts->list, data ) < 0 )
1592 lsmash_free( data );
1593 return LSMASH_ERR_MEMORY_ALLOC;
1595 data->sample_count = lsmash_bs_get_be32( bs );
1596 data->sample_delta = lsmash_bs_get_be32( bs );
1598 return isom_read_leaf_box_common_last_process( file, box, level, stts );
1601 static int isom_read_ctts( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1603 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->ctts )
1604 return isom_read_unknown_box( file, box, parent, level );
1605 ADD_BOX( ctts, isom_stbl_t );
1606 lsmash_bs_t *bs = file->bs;
1607 uint32_t entry_count = lsmash_bs_get_be32( bs );
1608 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && ctts->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1610 isom_ctts_entry_t *data = lsmash_malloc( sizeof(isom_ctts_entry_t) );
1611 if( !data )
1612 return LSMASH_ERR_MEMORY_ALLOC;
1613 if( lsmash_add_entry( ctts->list, data ) < 0 )
1615 lsmash_free( data );
1616 return LSMASH_ERR_MEMORY_ALLOC;
1618 data->sample_count = lsmash_bs_get_be32( bs );
1619 data->sample_offset = lsmash_bs_get_be32( bs );
1621 return isom_read_leaf_box_common_last_process( file, box, level, ctts );
1624 static int isom_read_cslg( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1626 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->cslg )
1627 return isom_read_unknown_box( file, box, parent, level );
1628 ADD_BOX( cslg, isom_stbl_t );
1629 lsmash_bs_t *bs = file->bs;
1630 cslg->compositionToDTSShift = lsmash_bs_get_be32( bs );
1631 cslg->leastDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1632 cslg->greatestDecodeToDisplayDelta = lsmash_bs_get_be32( bs );
1633 cslg->compositionStartTime = lsmash_bs_get_be32( bs );
1634 cslg->compositionEndTime = lsmash_bs_get_be32( bs );
1635 return isom_read_leaf_box_common_last_process( file, box, level, cslg );
1638 static int isom_read_stss( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1640 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stss )
1641 return isom_read_unknown_box( file, box, parent, level );
1642 ADD_BOX( stss, isom_stbl_t );
1643 lsmash_bs_t *bs = file->bs;
1644 uint32_t entry_count = lsmash_bs_get_be32( bs );
1645 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stss->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1647 isom_stss_entry_t *data = lsmash_malloc( sizeof(isom_stss_entry_t) );
1648 if( !data )
1649 return LSMASH_ERR_MEMORY_ALLOC;
1650 if( lsmash_add_entry( stss->list, data ) < 0 )
1652 lsmash_free( data );
1653 return LSMASH_ERR_MEMORY_ALLOC;
1655 data->sample_number = lsmash_bs_get_be32( bs );
1657 return isom_read_leaf_box_common_last_process( file, box, level, stss );
1660 static int isom_read_stps( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1662 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stps )
1663 return isom_read_unknown_box( file, box, parent, level );
1664 ADD_BOX( stps, isom_stbl_t );
1665 lsmash_bs_t *bs = file->bs;
1666 uint32_t entry_count = lsmash_bs_get_be32( bs );
1667 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stps->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1669 isom_stps_entry_t *data = lsmash_malloc( sizeof(isom_stps_entry_t) );
1670 if( !data )
1671 return LSMASH_ERR_MEMORY_ALLOC;
1672 if( lsmash_add_entry( stps->list, data ) < 0 )
1674 lsmash_free( data );
1675 return LSMASH_ERR_MEMORY_ALLOC;
1677 data->sample_number = lsmash_bs_get_be32( bs );
1679 return isom_read_leaf_box_common_last_process( file, box, level, stps );
1682 static int isom_read_sdtp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1684 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1685 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ))
1686 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) && ((isom_stbl_t *)parent)->sdtp)
1687 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) && ((isom_traf_t *)parent)->sdtp))
1688 return isom_read_unknown_box( file, box, parent, level );
1689 ADD_BOX( sdtp, isom_box_t );
1690 lsmash_bs_t *bs = file->bs;
1691 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size; pos = lsmash_bs_count( bs ) )
1693 isom_sdtp_entry_t *data = lsmash_malloc( sizeof(isom_sdtp_entry_t) );
1694 if( !data )
1695 return LSMASH_ERR_MEMORY_ALLOC;
1696 if( lsmash_add_entry( sdtp->list, data ) < 0 )
1698 lsmash_free( data );
1699 return LSMASH_ERR_MEMORY_ALLOC;
1701 uint8_t temp = lsmash_bs_get_byte( bs );
1702 data->is_leading = (temp >> 6) & 0x3;
1703 data->sample_depends_on = (temp >> 4) & 0x3;
1704 data->sample_is_depended_on = (temp >> 2) & 0x3;
1705 data->sample_has_redundancy = temp & 0x3;
1707 return isom_read_leaf_box_common_last_process( file, box, level, sdtp );
1710 static int isom_read_stsc( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1712 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsc )
1713 return isom_read_unknown_box( file, box, parent, level );
1714 ADD_BOX( stsc, isom_stbl_t );
1715 lsmash_bs_t *bs = file->bs;
1716 uint32_t entry_count = lsmash_bs_get_be32( bs );
1717 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stsc->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1719 isom_stsc_entry_t *data = lsmash_malloc( sizeof(isom_stsc_entry_t) );
1720 if( !data )
1721 return LSMASH_ERR_MEMORY_ALLOC;
1722 if( lsmash_add_entry( stsc->list, data ) < 0 )
1724 lsmash_free( data );
1725 return LSMASH_ERR_MEMORY_ALLOC;
1727 data->first_chunk = lsmash_bs_get_be32( bs );
1728 data->samples_per_chunk = lsmash_bs_get_be32( bs );
1729 data->sample_description_index = lsmash_bs_get_be32( bs );
1731 return isom_read_leaf_box_common_last_process( file, box, level, stsc );
1734 static int isom_read_stsz( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1736 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stsz )
1737 return isom_read_unknown_box( file, box, parent, level );
1738 ADD_BOX( stsz, isom_stbl_t );
1739 lsmash_bs_t *bs = file->bs;
1740 stsz->sample_size = lsmash_bs_get_be32( bs );
1741 stsz->sample_count = lsmash_bs_get_be32( bs );
1742 uint64_t pos = lsmash_bs_count( bs );
1743 if( pos < box->size )
1745 stsz->list = lsmash_create_entry_list();
1746 if( !stsz->list )
1747 return LSMASH_ERR_MEMORY_ALLOC;
1748 for( ; pos < box->size && stsz->list->entry_count < stsz->sample_count; pos = lsmash_bs_count( bs ) )
1750 isom_stsz_entry_t *data = lsmash_malloc( sizeof(isom_stsz_entry_t) );
1751 if( !data )
1752 return LSMASH_ERR_MEMORY_ALLOC;
1753 if( lsmash_add_entry( stsz->list, data ) < 0 )
1755 lsmash_free( data );
1756 return LSMASH_ERR_MEMORY_ALLOC;
1758 data->entry_size = lsmash_bs_get_be32( bs );
1761 return isom_read_leaf_box_common_last_process( file, box, level, stsz );
1764 static int isom_read_stco( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1766 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL ) || ((isom_stbl_t *)parent)->stco )
1767 return isom_read_unknown_box( file, box, parent, level );
1768 box->type = lsmash_form_iso_box_type( box->type.fourcc );
1769 int is_stco = lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_STCO );
1770 isom_stco_t *stco = is_stco
1771 ? isom_add_stco( (isom_stbl_t *)parent )
1772 : isom_add_co64( (isom_stbl_t *)parent );
1773 if( !stco )
1774 return LSMASH_ERR_NAMELESS;
1775 lsmash_bs_t *bs = file->bs;
1776 uint32_t entry_count = lsmash_bs_get_be32( bs );
1777 if( is_stco )
1778 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1780 isom_stco_entry_t *data = lsmash_malloc( sizeof(isom_stco_entry_t) );
1781 if( !data )
1782 return LSMASH_ERR_MEMORY_ALLOC;
1783 if( lsmash_add_entry( stco->list, data ) < 0 )
1785 lsmash_free( data );
1786 return LSMASH_ERR_MEMORY_ALLOC;
1788 data->chunk_offset = lsmash_bs_get_be32( bs );
1790 else
1792 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && stco->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1794 isom_co64_entry_t *data = lsmash_malloc( sizeof(isom_co64_entry_t) );
1795 if( !data )
1796 return LSMASH_ERR_MEMORY_ALLOC;
1797 if( lsmash_add_entry( stco->list, data ) < 0 )
1799 lsmash_free( data );
1800 return LSMASH_ERR_MEMORY_ALLOC;
1802 data->chunk_offset = lsmash_bs_get_be64( bs );
1805 return isom_read_leaf_box_common_last_process( file, box, level, stco );
1808 static int isom_read_sgpd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1810 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1811 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1812 return isom_read_unknown_box( file, box, parent, level );
1813 ADD_BOX( sgpd, void );
1814 lsmash_bs_t *bs = file->bs;
1815 sgpd->grouping_type = lsmash_bs_get_be32( bs );
1816 if( box->version == 1 )
1817 sgpd->default_length = lsmash_bs_get_be32( bs );
1818 uint32_t entry_count = lsmash_bs_get_be32( bs );
1819 switch( sgpd->grouping_type )
1821 case ISOM_GROUP_TYPE_RAP :
1823 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1825 isom_rap_entry_t *data = lsmash_malloc( sizeof(isom_rap_entry_t) );
1826 if( !data )
1827 return LSMASH_ERR_MEMORY_ALLOC;
1828 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1830 lsmash_free( data );
1831 return LSMASH_ERR_MEMORY_ALLOC;
1833 memset( data, 0, sizeof(isom_rap_entry_t) );
1834 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1835 if( box->version == 1 && !sgpd->default_length )
1836 data->description_length = lsmash_bs_get_be32( bs );
1837 else
1839 uint8_t temp = lsmash_bs_get_byte( bs );
1840 data->num_leading_samples_known = (temp >> 7) & 0x01;
1841 data->num_leading_samples = temp & 0x7f;
1844 break;
1846 case ISOM_GROUP_TYPE_ROLL :
1847 case ISOM_GROUP_TYPE_PROL :
1849 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sgpd->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1851 isom_roll_entry_t *data = lsmash_malloc( sizeof(isom_roll_entry_t) );
1852 if( !data )
1853 return LSMASH_ERR_MEMORY_ALLOC;
1854 if( lsmash_add_entry( sgpd->list, data ) < 0 )
1856 lsmash_free( data );
1857 return LSMASH_ERR_MEMORY_ALLOC;
1859 memset( data, 0, sizeof(isom_roll_entry_t) );
1860 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1861 if( box->version == 1 && !sgpd->default_length )
1862 data->description_length = lsmash_bs_get_be32( bs );
1863 else
1864 data->roll_distance = lsmash_bs_get_be16( bs );
1866 break;
1868 default :
1869 break;
1871 return isom_read_leaf_box_common_last_process( file, box, level, sgpd );
1874 static int isom_read_sbgp( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1876 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STBL )
1877 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
1878 return isom_read_unknown_box( file, box, parent, level );
1879 ADD_BOX( sbgp, void );
1880 lsmash_bs_t *bs = file->bs;
1881 sbgp->grouping_type = lsmash_bs_get_be32( bs );
1882 if( box->version == 1 )
1883 sbgp->grouping_type_parameter = lsmash_bs_get_be32( bs );
1884 uint32_t entry_count = lsmash_bs_get_be32( bs );
1885 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && sbgp->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1887 isom_group_assignment_entry_t *data = lsmash_malloc( sizeof(isom_group_assignment_entry_t) );
1888 if( !data )
1889 return LSMASH_ERR_MEMORY_ALLOC;
1890 if( lsmash_add_entry( sbgp->list, data ) < 0 )
1892 lsmash_free( data );
1893 return LSMASH_ERR_MEMORY_ALLOC;
1895 data->sample_count = lsmash_bs_get_be32( bs );
1896 data->group_description_index = lsmash_bs_get_be32( bs );
1898 return isom_read_leaf_box_common_last_process( file, box, level,sbgp );
1901 static int isom_read_udta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1903 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
1904 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ))
1905 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->udta)
1906 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->udta) )
1907 return isom_read_unknown_box( file, box, parent, level );
1908 ADD_BOX( udta, void );
1909 isom_box_common_copy( udta, box );
1910 int ret = isom_add_print_func( file, udta, level );
1911 if( ret < 0 )
1912 return ret;
1913 return isom_read_children( file, box, udta, level );
1916 static int isom_read_chpl( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1918 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->chpl )
1919 return isom_read_unknown_box( file, box, parent, level );
1920 ADD_BOX( chpl, isom_udta_t );
1921 lsmash_bs_t *bs = file->bs;
1922 uint32_t entry_count;
1923 if( box->version == 1 )
1925 chpl->unknown = lsmash_bs_get_byte( bs );
1926 entry_count = lsmash_bs_get_be32( bs );
1928 else
1929 entry_count = lsmash_bs_get_byte( bs );
1930 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && chpl->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
1932 isom_chpl_entry_t *data = lsmash_malloc( sizeof(isom_chpl_entry_t) );
1933 if( !data )
1934 return LSMASH_ERR_MEMORY_ALLOC;
1935 if( lsmash_add_entry( chpl->list, data ) < 0 )
1937 lsmash_free( data );
1938 return LSMASH_ERR_MEMORY_ALLOC;
1940 data->start_time = lsmash_bs_get_be64( bs );
1941 data->chapter_name_length = lsmash_bs_get_byte( bs );
1942 data->chapter_name = lsmash_malloc( data->chapter_name_length + 1 );
1943 if( !data->chapter_name )
1945 lsmash_free( data );
1946 return LSMASH_ERR_MEMORY_ALLOC;
1948 for( uint8_t i = 0; i < data->chapter_name_length; i++ )
1949 data->chapter_name[i] = lsmash_bs_get_byte( bs );
1950 data->chapter_name[data->chapter_name_length] = '\0';
1952 return isom_read_leaf_box_common_last_process( file, box, level, chpl );
1955 static int isom_read_mvex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1957 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) || ((isom_moov_t *)parent)->mvex )
1958 return isom_read_unknown_box( file, box, parent, level );
1959 ADD_BOX( mvex, isom_moov_t );
1960 file->flags |= LSMASH_FILE_MODE_FRAGMENTED;
1961 isom_box_common_copy( mvex, box );
1962 int ret = isom_add_print_func( file, mvex, level );
1963 if( ret < 0 )
1964 return ret;
1965 return isom_read_children( file, box, mvex, level );
1968 static int isom_read_mehd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1970 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) || ((isom_mvex_t *)parent)->mehd )
1971 return isom_read_unknown_box( file, box, parent, level );
1972 ADD_BOX( mehd, isom_mvex_t );
1973 lsmash_bs_t *bs = file->bs;
1974 if( box->version == 1 )
1975 mehd->fragment_duration = lsmash_bs_get_be64( bs );
1976 else
1977 mehd->fragment_duration = lsmash_bs_get_be32( bs );
1978 return isom_read_leaf_box_common_last_process( file, box, level, mehd );
1981 static isom_sample_flags_t isom_bs_get_sample_flags( lsmash_bs_t *bs )
1983 uint32_t temp = lsmash_bs_get_be32( bs );
1984 isom_sample_flags_t flags;
1985 flags.reserved = (temp >> 28) & 0xf;
1986 flags.is_leading = (temp >> 26) & 0x3;
1987 flags.sample_depends_on = (temp >> 24) & 0x3;
1988 flags.sample_is_depended_on = (temp >> 22) & 0x3;
1989 flags.sample_has_redundancy = (temp >> 20) & 0x3;
1990 flags.sample_padding_value = (temp >> 17) & 0x7;
1991 flags.sample_is_non_sync_sample = (temp >> 16) & 0x1;
1992 flags.sample_degradation_priority = temp & 0xffff;
1993 return flags;
1996 static int isom_read_trex( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
1998 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MVEX ) )
1999 return isom_read_unknown_box( file, box, parent, level );
2000 ADD_BOX( trex, isom_mvex_t );
2001 box->parent = parent;
2002 lsmash_bs_t *bs = file->bs;
2003 trex->track_ID = lsmash_bs_get_be32( bs );
2004 trex->default_sample_description_index = lsmash_bs_get_be32( bs );
2005 trex->default_sample_duration = lsmash_bs_get_be32( bs );
2006 trex->default_sample_size = lsmash_bs_get_be32( bs );
2007 trex->default_sample_flags = isom_bs_get_sample_flags( bs );
2008 return isom_read_leaf_box_common_last_process( file, box, level, trex );
2011 static int isom_read_moof( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2013 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2014 return isom_read_unknown_box( file, box, parent, level );
2015 ADD_BOX( moof, lsmash_file_t );
2016 box->parent = parent;
2017 isom_box_common_copy( moof, box );
2018 int ret = isom_add_print_func( file, moof, level );
2019 if( ret < 0 )
2020 return ret;
2021 return isom_read_children( file, box, moof, level );
2024 static int isom_read_mfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2026 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) || ((isom_moof_t *)parent)->mfhd )
2027 return isom_read_unknown_box( file, box, parent, level );
2028 ADD_BOX( mfhd, isom_moof_t );
2029 lsmash_bs_t *bs = file->bs;
2030 mfhd->sequence_number = lsmash_bs_get_be32( bs );
2031 return isom_read_leaf_box_common_last_process( file, box, level, mfhd );
2034 static int isom_read_traf( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2036 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOF ) )
2037 return isom_read_unknown_box( file, box, parent, level );
2038 ADD_BOX( traf, isom_moof_t );
2039 box->parent = parent;
2040 isom_box_common_copy( traf, box );
2041 int ret = isom_add_print_func( file, traf, level );
2042 if( ret < 0 )
2043 return ret;
2044 return isom_read_children( file, box, traf, level );
2047 static int isom_read_tfhd( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2049 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfhd )
2050 return isom_read_unknown_box( file, box, parent, level );
2051 ADD_BOX( tfhd, isom_traf_t );
2052 lsmash_bs_t *bs = file->bs;
2053 tfhd->track_ID = lsmash_bs_get_be32( bs );
2054 if( box->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) tfhd->base_data_offset = lsmash_bs_get_be64( bs );
2055 if( box->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) tfhd->sample_description_index = lsmash_bs_get_be32( bs );
2056 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) tfhd->default_sample_duration = lsmash_bs_get_be32( bs );
2057 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) tfhd->default_sample_size = lsmash_bs_get_be32( bs );
2058 if( box->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) tfhd->default_sample_flags = isom_bs_get_sample_flags( bs );
2059 return isom_read_leaf_box_common_last_process( file, box, level, tfhd );
2062 static int isom_read_tfdt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2064 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) || ((isom_traf_t *)parent)->tfdt )
2065 return isom_read_unknown_box( file, box, parent, level );
2066 ADD_BOX( tfdt, isom_traf_t );
2067 lsmash_bs_t *bs = file->bs;
2068 if( box->version == 1 )
2069 tfdt->baseMediaDecodeTime = lsmash_bs_get_be64( bs );
2070 else
2071 tfdt->baseMediaDecodeTime = lsmash_bs_get_be32( bs );
2072 return isom_read_leaf_box_common_last_process( file, box, level, tfdt );
2075 static int isom_read_trun( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2077 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAF ) )
2078 return isom_read_unknown_box( file, box, parent, level );
2079 ADD_BOX( trun, isom_traf_t );
2080 box->parent = parent;
2081 lsmash_bs_t *bs = file->bs;
2082 int has_optional_rows = ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2083 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2084 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2085 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT;
2086 has_optional_rows &= box->flags;
2087 trun->sample_count = lsmash_bs_get_be32( bs );
2088 if( box->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) trun->data_offset = lsmash_bs_get_be32( bs );
2089 if( box->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) trun->first_sample_flags = isom_bs_get_sample_flags( bs );
2090 if( trun->sample_count && has_optional_rows )
2092 trun->optional = lsmash_create_entry_list();
2093 if( !trun->optional )
2094 return LSMASH_ERR_MEMORY_ALLOC;
2095 for( uint32_t i = 0; i < trun->sample_count; i++ )
2097 isom_trun_optional_row_t *data = lsmash_malloc( sizeof(isom_trun_optional_row_t) );
2098 if( !data )
2099 return LSMASH_ERR_MEMORY_ALLOC;
2100 if( lsmash_add_entry( trun->optional, data ) < 0 )
2102 lsmash_free( data );
2103 return LSMASH_ERR_MEMORY_ALLOC;
2105 if( box->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) data->sample_duration = lsmash_bs_get_be32( bs );
2106 if( box->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) data->sample_size = lsmash_bs_get_be32( bs );
2107 if( box->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) data->sample_flags = isom_bs_get_sample_flags( bs );
2108 if( box->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) data->sample_composition_time_offset = lsmash_bs_get_be32( bs );
2111 return isom_read_leaf_box_common_last_process( file, box, level, trun );
2114 static int isom_read_free( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2116 if( file->fake_file_mode )
2117 return isom_read_unknown_box( file, box, parent, level );
2118 isom_box_t *skip = lsmash_malloc_zero( sizeof(isom_box_t) );
2119 if( !skip )
2120 return LSMASH_ERR_MEMORY_ALLOC;
2121 isom_skip_box_rest( file->bs, box );
2122 box->manager |= LSMASH_ABSENT_IN_FILE;
2123 isom_box_common_copy( skip, box );
2124 int ret = isom_add_print_func( file, skip, level );
2125 if( ret < 0 )
2127 lsmash_free( skip );
2128 return ret;
2130 return 0;
2133 static int isom_read_mdat( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2135 if( file->fake_file_mode || !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) )
2136 return isom_read_unknown_box( file, box, parent, level );
2137 isom_box_t *mdat = lsmash_malloc_zero( sizeof(isom_box_t) );
2138 if( !mdat )
2139 return LSMASH_ERR_MEMORY_ALLOC;
2140 isom_skip_box_rest( file->bs, box );
2141 box->manager |= LSMASH_ABSENT_IN_FILE;
2142 file->flags |= LSMASH_FILE_MODE_MEDIA;
2143 isom_box_common_copy( mdat, box );
2144 int ret = isom_add_print_func( file, mdat, level );
2145 if( ret < 0 )
2147 lsmash_free( mdat );
2148 return ret;
2150 return 0;
2153 static int isom_read_meta( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2155 if( (!lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED )
2156 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV )
2157 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK )
2158 && !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ))
2159 || (lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) && ((lsmash_file_t *)parent)->meta)
2160 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MOOV ) && ((isom_moov_t *)parent)->meta)
2161 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TRAK ) && ((isom_trak_t *)parent)->meta)
2162 || (lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) && ((isom_udta_t *)parent)->meta) )
2163 return isom_read_unknown_box( file, box, parent, level );
2164 ADD_BOX( meta, void );
2165 isom_box_common_copy( meta, box );
2166 int is_qtff = lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_META );
2167 if( is_qtff )
2169 box->manager |= LSMASH_QTFF_BASE;
2170 meta->manager |= LSMASH_QTFF_BASE;
2172 int ret = isom_add_print_func( file, meta, level );
2173 if( ret < 0 )
2174 return ret;
2175 return isom_read_children( file, box, meta, level );
2178 static int isom_read_keys( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2180 if( (!lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) && !(parent->manager & LSMASH_QTFF_BASE))
2181 || ((isom_meta_t *)parent)->keys )
2182 return isom_read_unknown_box( file, box, parent, level );
2183 ADD_BOX( keys, isom_meta_t );
2184 lsmash_bs_t *bs = file->bs;
2185 uint32_t entry_count = lsmash_bs_get_be32( bs );
2186 for( uint64_t pos = lsmash_bs_count( bs ); pos < box->size && keys->list->entry_count < entry_count; pos = lsmash_bs_count( bs ) )
2188 isom_keys_entry_t *data = lsmash_malloc( sizeof(isom_keys_entry_t) );
2189 if( !data )
2190 return LSMASH_ERR_MEMORY_ALLOC;
2191 if( lsmash_add_entry( keys->list, data ) < 0 )
2193 lsmash_free( data );
2194 return LSMASH_ERR_MEMORY_ALLOC;
2196 data->key_size = lsmash_bs_get_be32( bs );
2197 data->key_namespace = lsmash_bs_get_be32( bs );
2198 if( data->key_size > 8 )
2200 data->key_value = lsmash_bs_get_bytes( bs, data->key_size - 8 );
2201 if( !data->key_value )
2202 return LSMASH_ERR_NAMELESS;
2204 else
2205 data->key_value = NULL;
2207 return isom_read_leaf_box_common_last_process( file, box, level, keys );
2210 static int isom_read_ilst( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2212 if( (!lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META )
2213 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ))
2214 || ((isom_meta_t *)parent)->ilst )
2215 return isom_read_unknown_box( file, box, parent, level );
2216 ADD_BOX( ilst, isom_meta_t );
2217 isom_box_common_copy( ilst, box );
2218 int ret = isom_add_print_func( file, ilst, level );
2219 if( ret < 0 )
2220 return ret;
2221 return isom_read_children( file, box, ilst, level );
2224 static int isom_read_metaitem( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2226 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
2227 && !lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2228 return isom_read_unknown_box( file, box, parent, level );
2229 isom_metaitem_t *metaitem = isom_add_metaitem( (isom_ilst_t *)parent, box->type.fourcc );
2230 if( !metaitem )
2231 return -1;
2232 box->parent = parent;
2233 isom_box_common_copy( metaitem, box );
2234 int ret = isom_add_print_func( file, metaitem, level );
2235 if( ret < 0 )
2236 return ret;
2237 return isom_read_children( file, box, metaitem, level );
2240 static int isom_read_mean( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2242 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->mean )
2243 return isom_read_unknown_box( file, box, parent, level );
2244 ADD_BOX( mean, isom_metaitem_t );
2245 lsmash_bs_t *bs = file->bs;
2246 mean->meaning_string_length = box->size - lsmash_bs_count( bs );
2247 mean->meaning_string = lsmash_bs_get_bytes( bs, mean->meaning_string_length );
2248 if( !mean->meaning_string )
2249 return LSMASH_ERR_NAMELESS;
2250 return isom_read_leaf_box_common_last_process( file, box, level, mean );
2253 static int isom_read_name( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2255 if( parent->type.fourcc != ITUNES_METADATA_ITEM_CUSTOM || ((isom_metaitem_t *)parent)->name )
2256 return isom_read_unknown_box( file, box, parent, level );
2257 ADD_BOX( name, isom_metaitem_t );
2258 lsmash_bs_t *bs = file->bs;
2259 name->name_length = box->size - lsmash_bs_count( bs );
2260 name->name = lsmash_bs_get_bytes( bs, name->name_length );
2261 if( !name->name )
2262 return LSMASH_ERR_NAMELESS;
2263 return isom_read_leaf_box_common_last_process( file, box, level, name );
2266 static int isom_read_data( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2268 if( ((isom_metaitem_t *)parent)->data )
2269 return isom_read_unknown_box( file, box, parent, level );
2270 ADD_BOX( data, isom_metaitem_t );
2271 lsmash_bs_t *bs = file->bs;
2272 data->value_length = box->size - lsmash_bs_count( bs ) - 8;
2273 data->reserved = lsmash_bs_get_be16( bs );
2274 data->type_set_identifier = lsmash_bs_get_byte( bs );
2275 data->type_code = lsmash_bs_get_byte( bs );
2276 data->the_locale = lsmash_bs_get_be32( bs );
2277 if( data->value_length )
2279 data->value = lsmash_bs_get_bytes( bs, data->value_length );
2280 if( !data->value )
2281 return LSMASH_ERR_NAMELESS;
2283 return isom_read_leaf_box_common_last_process( file, box, level, data );
2286 static int isom_read_WLOC( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2288 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->WLOC )
2289 return isom_read_unknown_box( file, box, parent, level );
2290 ADD_BOX( WLOC, isom_udta_t );
2291 lsmash_bs_t *bs = file->bs;
2292 WLOC->x = lsmash_bs_get_be16( bs );
2293 WLOC->y = lsmash_bs_get_be16( bs );
2294 return isom_read_leaf_box_common_last_process( file, box, level, WLOC );
2297 static int isom_read_LOOP( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2299 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->LOOP )
2300 return isom_read_unknown_box( file, box, parent, level );
2301 ADD_BOX( LOOP, isom_udta_t );
2302 lsmash_bs_t *bs = file->bs;
2303 LOOP->looping_mode = lsmash_bs_get_be32( bs );
2304 return isom_read_leaf_box_common_last_process( file, box, level, LOOP );
2307 static int isom_read_SelO( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2309 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->SelO )
2310 return isom_read_unknown_box( file, box, parent, level );
2311 ADD_BOX( SelO, isom_udta_t );
2312 lsmash_bs_t *bs = file->bs;
2313 SelO->selection_only = lsmash_bs_get_byte( bs );
2314 return isom_read_leaf_box_common_last_process( file, box, level, SelO );
2317 static int isom_read_AllF( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2319 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) || ((isom_udta_t *)parent)->AllF )
2320 return isom_read_unknown_box( file, box, parent, level );
2321 ADD_BOX( AllF, isom_udta_t );
2322 lsmash_bs_t *bs = file->bs;
2323 AllF->play_all_frames = lsmash_bs_get_byte( bs );
2324 return isom_read_leaf_box_common_last_process( file, box, level, AllF );
2327 static int isom_read_cprt( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2329 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_UDTA ) )
2330 return isom_read_unknown_box( file, box, parent, level );
2331 ADD_BOX( cprt, isom_udta_t );
2332 box->parent = parent;
2333 lsmash_bs_t *bs = file->bs;
2334 cprt->language = lsmash_bs_get_be16( bs );
2335 cprt->notice_length = box->size - (ISOM_FULLBOX_COMMON_SIZE + 2);
2336 if( cprt->notice_length )
2338 cprt->notice = lsmash_bs_get_bytes( bs, cprt->notice_length );
2339 if( !cprt->notice )
2341 cprt->notice_length = 0;
2342 return LSMASH_ERR_NAMELESS;
2345 return isom_read_leaf_box_common_last_process( file, box, level, cprt );
2348 static int isom_read_mfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2350 if( !lsmash_check_box_type_identical( parent->type, LSMASH_BOX_TYPE_UNSPECIFIED ) || ((lsmash_file_t *)parent)->mfra )
2351 return isom_read_unknown_box( file, box, parent, level );
2352 ADD_BOX( mfra, lsmash_file_t );
2353 isom_box_common_copy( mfra, box );
2354 int ret = isom_add_print_func( file, mfra, level );
2355 if( ret < 0 )
2356 return ret;
2357 return isom_read_children( file, box, mfra, level );
2360 static int isom_read_tfra( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2362 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) )
2363 return isom_read_unknown_box( file, box, parent, level );
2364 ADD_BOX( tfra, isom_mfra_t );
2365 box->parent = parent;
2366 lsmash_bs_t *bs = file->bs;
2367 tfra->track_ID = lsmash_bs_get_be32( bs );
2368 uint32_t temp = lsmash_bs_get_be32( bs );
2369 tfra->number_of_entry = lsmash_bs_get_be32( bs );
2370 tfra->reserved = (temp >> 6) & 0x3ffffff;
2371 tfra->length_size_of_traf_num = (temp >> 4) & 0x3;
2372 tfra->length_size_of_trun_num = (temp >> 2) & 0x3;
2373 tfra->length_size_of_sample_num = temp & 0x3;
2374 if( tfra->number_of_entry )
2376 tfra->list = lsmash_create_entry_list();
2377 if( !tfra->list )
2378 return LSMASH_ERR_MEMORY_ALLOC;
2379 uint64_t (*bs_get_funcs[5])( lsmash_bs_t * ) =
2381 lsmash_bs_get_byte_to_64,
2382 lsmash_bs_get_be16_to_64,
2383 lsmash_bs_get_be24_to_64,
2384 lsmash_bs_get_be32_to_64,
2385 lsmash_bs_get_be64
2387 uint64_t (*bs_put_time) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2388 uint64_t (*bs_put_moof_offset) ( lsmash_bs_t * ) = bs_get_funcs[ 3 + (box->version == 1) ];
2389 uint64_t (*bs_put_traf_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_traf_num ];
2390 uint64_t (*bs_put_trun_number) ( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_trun_num ];
2391 uint64_t (*bs_put_sample_number)( lsmash_bs_t * ) = bs_get_funcs[ tfra->length_size_of_sample_num ];
2392 for( uint32_t i = 0; i < tfra->number_of_entry; i++ )
2394 isom_tfra_location_time_entry_t *data = lsmash_malloc( sizeof(isom_tfra_location_time_entry_t) );
2395 if( !data )
2396 return LSMASH_ERR_MEMORY_ALLOC;
2397 if( lsmash_add_entry( tfra->list, data ) < 0 )
2399 lsmash_free( data );
2400 return LSMASH_ERR_MEMORY_ALLOC;
2402 data->time = bs_put_time ( bs );
2403 data->moof_offset = bs_put_moof_offset ( bs );
2404 data->traf_number = bs_put_traf_number ( bs );
2405 data->trun_number = bs_put_trun_number ( bs );
2406 data->sample_number = bs_put_sample_number( bs );
2409 return isom_read_leaf_box_common_last_process( file, box, level, tfra );
2412 static int isom_read_mfro( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, int level )
2414 if( !lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_MFRA ) || ((isom_mfra_t *)parent)->mfro )
2415 return isom_read_unknown_box( file, box, parent, level );
2416 ADD_BOX( mfro, isom_mfra_t );
2417 lsmash_bs_t *bs = file->bs;
2418 mfro->length = lsmash_bs_get_be32( bs );
2419 return isom_read_leaf_box_common_last_process( file, box, level, mfro );
2422 static inline void isom_read_skip_extra_bytes( lsmash_bs_t *bs, uint64_t size )
2424 if( !bs->unseekable )
2425 lsmash_bs_read_seek( bs, size, SEEK_CUR );
2426 else
2427 lsmash_bs_skip_bytes_64( bs, size );
2430 static int isom_read_skip_box_extra_bytes( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos )
2432 lsmash_bs_t *bs = file->bs;
2433 /* Skip extra bytes of the parent box if any. */
2434 if( parent->size < parent_pos + ISOM_BASEBOX_COMMON_SIZE )
2436 uint64_t extra_bytes = parent->size - parent_pos;
2437 isom_read_skip_extra_bytes( bs, extra_bytes );
2438 /* This is not the size of a box but makes sense in isom_read_children(). */
2439 box->size = extra_bytes;
2440 return 1;
2442 /* Check if the size is valid or not. */
2443 if( lsmash_bs_is_end( bs, 3 ) == 0 )
2445 uint64_t size = (uint64_t)lsmash_bs_show_be32( bs, 0 );
2446 if( size > 1
2447 && size < ISOM_BASEBOX_COMMON_SIZE )
2449 /* It seems we are still within the box considered as previous.
2450 * Skip bytes up to the next box. */
2451 isom_read_skip_extra_bytes( bs, parent->size - parent_pos );
2452 box->size = 0;
2453 return 1;
2455 if( size == 1 && lsmash_bs_is_end( bs, 15 ) == 0 )
2456 size = lsmash_bs_show_be64( bs, 8 );
2457 if( size == 0 && parent != (isom_box_t *)file )
2459 /* Check if this box is actually the last box or not. */
2460 size = parent->size - parent_pos;
2461 uint64_t extra_bytes;
2462 if( !bs->unseekable )
2463 extra_bytes = bs->written - lsmash_bs_get_stream_pos( bs );
2464 else
2466 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2467 while( size < extra_bytes )
2469 int ret = lsmash_bs_read( bs, 1 );
2470 if( bs->eof || ret < 0 )
2471 break;
2472 extra_bytes = lsmash_bs_get_remaining_buffer_size( bs );
2475 if( size != extra_bytes )
2477 /* This is not the size of the last box.
2478 * It seems we are still within the box considered as previous.
2479 * Skip bytes up to the next box. */
2480 isom_read_skip_extra_bytes( bs, box->size - lsmash_bs_count( bs ) );
2481 box->size = 0;
2482 return 1;
2486 return 0;
2489 int isom_read_box( lsmash_file_t *file, isom_box_t *box, isom_box_t *parent, uint64_t parent_pos, int level )
2491 assert( parent && parent->root && parent->file );
2492 if( isom_read_skip_box_extra_bytes( file, box, parent, parent_pos ) != 0 )
2493 return 0;
2494 memset( box, 0, sizeof(isom_box_t) );
2495 box->root = parent->root;
2496 box->file = parent->file;
2497 box->parent = parent;
2498 lsmash_bs_t *bs = file->bs;
2499 int ret = isom_bs_read_box_common( bs, box );
2500 if( !!ret )
2501 return ret; /* return if reached EOF */
2502 ++level;
2503 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t ) = NULL;
2504 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int ) = NULL;
2505 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
2507 /* Check whether CODEC is RAW Video/Audio encapsulated in QTFF. */
2508 if( box->type.fourcc == LSMASH_CODEC_TYPE_RAW.fourcc )
2510 if( ((isom_minf_t *)parent->parent->parent)->vmhd )
2512 form_box_type_func = lsmash_form_qtff_box_type;
2513 reader_func = isom_read_visual_description;
2515 else if( ((isom_minf_t *)parent->parent->parent)->smhd )
2517 form_box_type_func = lsmash_form_qtff_box_type;
2518 reader_func = isom_read_audio_description;
2520 goto read_box;
2522 static struct description_reader_table_tag
2524 lsmash_compact_box_type_t fourcc;
2525 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2526 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2527 } description_reader_table[160] = { { 0, NULL, NULL } };
2528 if( !description_reader_table[0].reader_func )
2530 /* Initialize the table. */
2531 int i = 0;
2532 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2533 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2534 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2535 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2549 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO, lsmash_form_iso_box_type, isom_read_visual_description );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2551 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2574 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2606 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO, lsmash_form_qtff_box_type, isom_read_visual_description );
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2630 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO, lsmash_form_iso_box_type, isom_read_audio_description );
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2642 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2643 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2644 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2645 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2646 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2647 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2648 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2649 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2650 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2651 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2652 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2653 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2654 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2655 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2656 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2657 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2658 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2659 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO, lsmash_form_qtff_box_type, isom_read_audio_description );
2660 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED, lsmash_form_qtff_box_type, isom_read_audio_description );
2661 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT, lsmash_form_qtff_box_type, isom_read_qt_text_description );
2662 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT, lsmash_form_iso_box_type, isom_read_tx3g_description );
2663 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM, lsmash_form_iso_box_type, isom_read_mp4s_description );
2664 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED, NULL, NULL );
2665 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2667 for( int i = 0; description_reader_table[i].reader_func; i++ )
2668 if( box->type.fourcc == description_reader_table[i].fourcc )
2670 form_box_type_func = description_reader_table[i].form_box_type_func;
2671 reader_func = description_reader_table[i].reader_func;
2672 goto read_box;
2674 goto read_box;
2676 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
2678 form_box_type_func = lsmash_form_qtff_box_type;
2679 if( box->type.fourcc == QT_BOX_TYPE_FRMA.fourcc ) reader_func = isom_read_frma;
2680 else if( box->type.fourcc == QT_BOX_TYPE_ENDA.fourcc ) reader_func = isom_read_enda;
2681 else if( box->type.fourcc == QT_BOX_TYPE_ESDS.fourcc ) reader_func = isom_read_esds;
2682 else if( box->type.fourcc == QT_BOX_TYPE_CHAN.fourcc ) reader_func = isom_read_chan;
2683 else if( box->type.fourcc == QT_BOX_TYPE_TERMINATOR.fourcc ) reader_func = isom_read_terminator;
2684 else reader_func = isom_read_codec_specific;
2685 goto read_box;
2687 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
2689 form_box_type_func = lsmash_form_iso_box_type;
2690 reader_func = isom_read_track_reference_type;
2691 goto read_box;
2693 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_DREF ) )
2695 if( box->type.fourcc == ISOM_BOX_TYPE_URL.fourcc
2696 || box->type.fourcc == ISOM_BOX_TYPE_URN.fourcc )
2697 form_box_type_func = lsmash_form_iso_box_type;
2698 else if( box->type.fourcc == QT_BOX_TYPE_ALIS.fourcc
2699 || box->type.fourcc == QT_BOX_TYPE_RSRC.fourcc )
2700 form_box_type_func = lsmash_form_qtff_box_type;
2701 reader_func = isom_read_dref_entry;
2702 goto read_box;
2704 static struct box_reader_table_tag
2706 lsmash_compact_box_type_t fourcc;
2707 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2708 int (*reader_func)( lsmash_file_t *, isom_box_t *, isom_box_t *, int );
2709 } box_reader_table[128] = { { 0, NULL, NULL } };
2710 if( !box_reader_table[0].reader_func )
2712 /* Initialize the table. */
2713 int i = 0;
2714 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2715 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2716 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, lsmash_form_iso_box_type, isom_read_ftyp );
2717 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, lsmash_form_iso_box_type, isom_read_styp );
2718 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, lsmash_form_iso_box_type, isom_read_sidx );
2719 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, lsmash_form_iso_box_type, isom_read_moov );
2720 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, lsmash_form_iso_box_type, isom_read_mvhd );
2721 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, lsmash_form_iso_box_type, isom_read_iods );
2722 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, lsmash_form_qtff_box_type, isom_read_ctab );
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, lsmash_form_iso_box_type, isom_read_esds );
2724 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, lsmash_form_iso_box_type, isom_read_trak );
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, lsmash_form_iso_box_type, isom_read_tkhd );
2726 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, lsmash_form_qtff_box_type, isom_read_tapt );
2727 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, lsmash_form_qtff_box_type, isom_read_clef );
2728 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, lsmash_form_qtff_box_type, isom_read_prof );
2729 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, lsmash_form_qtff_box_type, isom_read_enof );
2730 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, lsmash_form_iso_box_type, isom_read_edts );
2731 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, lsmash_form_iso_box_type, isom_read_elst );
2732 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, lsmash_form_iso_box_type, isom_read_tref );
2733 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, lsmash_form_iso_box_type, isom_read_mdia );
2734 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, lsmash_form_iso_box_type, isom_read_mdhd );
2735 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, lsmash_form_iso_box_type, isom_read_hdlr );
2736 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, lsmash_form_iso_box_type, isom_read_minf );
2737 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, lsmash_form_iso_box_type, isom_read_vmhd );
2738 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, lsmash_form_iso_box_type, isom_read_smhd );
2739 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, lsmash_form_iso_box_type, isom_read_hmhd );
2740 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, lsmash_form_iso_box_type, isom_read_nmhd );
2741 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, lsmash_form_qtff_box_type, isom_read_gmhd );
2742 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, lsmash_form_qtff_box_type, isom_read_gmin );
2743 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, lsmash_form_qtff_box_type, isom_read_text );
2744 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, lsmash_form_iso_box_type, isom_read_dinf );
2745 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, lsmash_form_iso_box_type, isom_read_dref );
2746 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, lsmash_form_iso_box_type, isom_read_stbl );
2747 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, lsmash_form_iso_box_type, isom_read_stsd );
2748 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, lsmash_form_iso_box_type, isom_read_btrt );
2749 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, lsmash_form_iso_box_type, isom_read_colr );
2750 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, lsmash_form_iso_box_type, isom_read_clap );
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, lsmash_form_iso_box_type, isom_read_pasp );
2752 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type, isom_read_glbl );
2753 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, lsmash_form_qtff_box_type, isom_read_gama );
2754 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, lsmash_form_qtff_box_type, isom_read_fiel );
2755 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, lsmash_form_qtff_box_type, isom_read_cspc );
2756 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, lsmash_form_qtff_box_type, isom_read_sgbt );
2757 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, lsmash_form_iso_box_type, isom_read_stsl );
2758 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, lsmash_form_qtff_box_type, isom_read_wave );
2759 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, lsmash_form_qtff_box_type, isom_read_chan );
2760 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT, lsmash_form_iso_box_type, isom_read_srat );
2761 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, lsmash_form_iso_box_type, isom_read_ftab );
2762 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, lsmash_form_iso_box_type, isom_read_stts );
2763 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, lsmash_form_iso_box_type, isom_read_ctts );
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, lsmash_form_iso_box_type, isom_read_cslg );
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, lsmash_form_iso_box_type, isom_read_stss );
2766 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, lsmash_form_qtff_box_type, isom_read_stps );
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, lsmash_form_iso_box_type, isom_read_sdtp );
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, lsmash_form_iso_box_type, isom_read_stsc );
2769 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, lsmash_form_iso_box_type, isom_read_stsz );
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, lsmash_form_iso_box_type, isom_read_stco );
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, lsmash_form_iso_box_type, isom_read_stco );
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, lsmash_form_iso_box_type, isom_read_sgpd );
2773 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, lsmash_form_iso_box_type, isom_read_sbgp );
2774 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, lsmash_form_iso_box_type, isom_read_udta );
2775 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, lsmash_form_iso_box_type, isom_read_chpl );
2776 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC, lsmash_form_qtff_box_type, isom_read_WLOC );
2777 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP, lsmash_form_qtff_box_type, isom_read_LOOP );
2778 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO, lsmash_form_qtff_box_type, isom_read_SelO );
2779 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF, lsmash_form_qtff_box_type, isom_read_AllF );
2780 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, lsmash_form_iso_box_type, isom_read_mvex );
2781 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, lsmash_form_iso_box_type, isom_read_mehd );
2782 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, lsmash_form_iso_box_type, isom_read_trex );
2783 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, lsmash_form_iso_box_type, isom_read_moof );
2784 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, lsmash_form_iso_box_type, isom_read_mfhd );
2785 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, lsmash_form_iso_box_type, isom_read_traf );
2786 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, lsmash_form_iso_box_type, isom_read_tfhd );
2787 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, lsmash_form_iso_box_type, isom_read_tfdt );
2788 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, lsmash_form_iso_box_type, isom_read_trun );
2789 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, lsmash_form_iso_box_type, isom_read_free );
2790 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, lsmash_form_iso_box_type, isom_read_free );
2791 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, lsmash_form_iso_box_type, isom_read_mdat );
2792 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS, lsmash_form_qtff_box_type, isom_read_keys );
2793 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, lsmash_form_iso_box_type, isom_read_mfra );
2794 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, lsmash_form_iso_box_type, isom_read_tfra );
2795 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, lsmash_form_iso_box_type, isom_read_mfro );
2796 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL, NULL );
2797 #undef ADD_BOX_READER_TABLE_ELEMENT
2799 for( int i = 0; box_reader_table[i].reader_func; i++ )
2800 if( box->type.fourcc == box_reader_table[i].fourcc )
2802 form_box_type_func = box_reader_table[i].form_box_type_func;
2803 reader_func = box_reader_table[i].reader_func;
2804 goto read_box;
2806 if( box->type.fourcc == ISOM_BOX_TYPE_META.fourcc )
2808 if( lsmash_bs_is_end ( bs, 3 ) == 0
2809 && lsmash_bs_show_be32( bs, 0 ) == 0 )
2810 form_box_type_func = lsmash_form_iso_box_type;
2811 else
2812 form_box_type_func = lsmash_form_qtff_box_type;
2813 reader_func = isom_read_meta;
2814 goto read_box;
2816 if( box->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2818 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_META ) )
2819 form_box_type_func = lsmash_form_iso_box_type;
2820 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_META ) )
2821 form_box_type_func = lsmash_form_qtff_box_type;
2822 if( form_box_type_func )
2824 reader_func = isom_read_ilst;
2825 goto read_box;
2828 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST ) )
2829 form_box_type_func = lsmash_form_iso_box_type;
2830 else if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
2831 form_box_type_func = lsmash_form_qtff_box_type;
2832 if( form_box_type_func )
2834 reader_func = isom_read_metaitem;
2835 goto read_box;
2837 if( parent->parent && parent->parent->type.fourcc == ISOM_BOX_TYPE_ILST.fourcc )
2839 if( box->type.fourcc == ISOM_BOX_TYPE_MEAN.fourcc )
2840 reader_func = isom_read_mean;
2841 else if( box->type.fourcc == ISOM_BOX_TYPE_NAME.fourcc )
2842 reader_func = isom_read_name;
2843 else if( box->type.fourcc == ISOM_BOX_TYPE_DATA.fourcc )
2844 reader_func = isom_read_data;
2845 if( reader_func )
2847 form_box_type_func = lsmash_form_iso_box_type;
2848 goto read_box;
2851 else if( box->type.fourcc == ISOM_BOX_TYPE_CPRT.fourcc )
2853 /* Avoid confusing udta.cprt with ilst.cprt. */
2854 form_box_type_func = lsmash_form_iso_box_type;
2855 reader_func = isom_read_cprt;
2856 goto read_box;
2858 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_STSD ) )
2860 static struct codec_specific_marker_table_tag
2862 lsmash_compact_box_type_t fourcc;
2863 lsmash_box_type_t (*form_box_type_func)( lsmash_compact_box_type_t );
2864 } codec_specific_marker_table[16] = { { 0, NULL } };
2865 if( !codec_specific_marker_table[0].form_box_type_func )
2867 /* Initialize the table. */
2868 int i = 0;
2869 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2870 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2871 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC, lsmash_form_iso_box_type );
2872 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC, lsmash_form_iso_box_type );
2873 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3, lsmash_form_iso_box_type );
2874 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR, lsmash_form_iso_box_type );
2875 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS, lsmash_form_iso_box_type );
2876 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3, lsmash_form_iso_box_type );
2877 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1, lsmash_form_iso_box_type );
2878 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC, lsmash_form_iso_box_type );
2879 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX, lsmash_form_iso_box_type );
2880 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, lsmash_form_qtff_box_type );
2881 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
2882 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2884 for( int i = 0; codec_specific_marker_table[i].form_box_type_func; i++ )
2885 if( box->type.fourcc == codec_specific_marker_table[i].fourcc )
2887 form_box_type_func = codec_specific_marker_table[i].form_box_type_func;
2888 break;
2890 reader_func = isom_read_codec_specific;
2892 read_box:
2893 if( form_box_type_func )
2894 box->type = form_box_type_func( box->type.fourcc );
2895 if( (ret = isom_read_fullbox_common_extension( bs, box )) < 0 )
2896 return ret;
2897 return reader_func
2898 ? reader_func( file, box, parent, level )
2899 : isom_read_unknown_box( file, box, parent, level );
2902 int isom_read_file( lsmash_file_t *file )
2904 lsmash_bs_t *bs = file->bs;
2905 if( !bs )
2906 return LSMASH_ERR_NAMELESS;
2907 /* Reset the counter so that we can use it to get position within the box. */
2908 lsmash_bs_reset_counter( bs );
2909 if( file->flags & LSMASH_FILE_MODE_DUMP )
2911 file->print = lsmash_create_entry_list();
2912 if( !file->print )
2913 return LSMASH_ERR_MEMORY_ALLOC;
2915 file->size = UINT64_MAX;
2916 isom_box_t box;
2917 int ret = isom_read_children( file, &box, file, 0 );
2918 file->size = box.size;
2919 lsmash_bs_empty( bs );
2920 bs->error = 0; /* Clear error flag. */
2921 if( ret < 0 )
2922 return ret;
2923 return isom_check_compatibility( file );