1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2015 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
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
);
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. */
55 box
->size
= lsmash_bs_get_be64( bs
);
58 /* This box is the last box in the stream. */
59 box
->manager
|= LSMASH_LAST_BOX
;
61 box
->size
= bs
->written
- (lsmash_bs_get_stream_pos( bs
) - lsmash_bs_count( bs
));
63 /* We haven't known the box size yet.
64 * To get the box size, read the stream until the end of the stream. */
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
);
73 /* This box may end incompletely at the end of the stream. */
74 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
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 )
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
);
94 static int isom_read_fullbox_common_extension( lsmash_bs_t
*bs
, isom_box_t
*box
)
96 if( !isom_is_fullbox( box
) )
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
;
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
;
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
;
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
);
137 if( isom_is_fullbox( src
) )
138 isom_fullbox_common_copy( (isom_box_t
*)dst
, (isom_box_t
*)src
);
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
);
153 lsmash_bs_skip_bytes( bs
, UINT32_MAX
);
154 uint64_t end
= lsmash_bs_get_stream_pos( bs
);
155 box
->size
+= end
- start
;
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
)
167 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
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
)
184 if( box
->size
< pos
)
186 printf( "[%s] box has more bytes: %"PRId64
"\n", isom_4cc2str( box
->type
.fourcc
), pos
- box
->size
);
191 static int isom_read_children( lsmash_file_t
*file
, isom_box_t
*box
, void *parent
, int level
)
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
)
203 box
->size
= parent_pos
; /* for file size */
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
) );
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
);
234 unknown
->unknown_field
= lsmash_bs_get_bytes( bs
, read_size
);
235 if( unknown
->unknown_field
)
236 unknown
->unknown_size
= read_size
;
238 unknown
->manager
|= LSMASH_INCOMPLETE_BOX
;
240 if( !(file
->flags
& LSMASH_FILE_MODE_DUMP
) )
242 /* Create a dummy for dump. */
243 isom_box_t
*dummy
= lsmash_malloc_zero( sizeof(isom_box_t
) );
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
);
251 lsmash_free( dummy
);
257 #define ADD_BOX( box_name, parent_type ) \
258 isom_##box_name##_t *box_name = isom_add_##box_name( (parent_type *)parent ); \
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
);
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
) );
341 return LSMASH_ERR_MEMORY_ALLOC
;
342 if( lsmash_add_entry( sidx
->list
, data
) < 0 )
345 return LSMASH_ERR_MEMORY_ALLOC
;
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
);
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
;
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
);
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
);
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
);
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
) );
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;
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
);
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
;
465 isom_box_common_copy( trak
, box
);
466 int ret
= isom_add_print_func( file
, trak
, level
);
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
;
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
);
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
);
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 )
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
) );
574 return LSMASH_ERR_MEMORY_ALLOC
;
575 if( lsmash_add_entry( elst
->list
, data
) < 0 )
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
);
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
);
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
);
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);
618 ref
->track_ID
= lsmash_malloc( ref
->ref_count
* sizeof(uint32_t) );
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
);
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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 )
883 stsd_pos
+= box
->size
;
884 if( stsd
->size
<= stsd_pos
|| bs
->eob
|| bs
->error
)
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
;
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
);
905 return LSMASH_ERR_MEMORY_ALLOC
;
906 int ret
= lsmash_bs_get_bytes_ex( bs
, exdata_length
, exdata
+ (uintptr_t)opaque_pos
);
909 LSMASH_SET_BE32( &exdata
[0], box
->size
);
910 LSMASH_SET_BE32( &exdata
[4], box
->type
.fourcc
);
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 );
918 if( box
->manager
& LSMASH_FULLBOX
)
920 LSMASH_SET_BYTE( &exdata
[i
], box
->version
);
922 LSMASH_SET_BE24( &exdata
[i
], box
->flags
);
925 if( i
!= opaque_pos
)
927 ret
= LSMASH_ERR_INVALID_DATA
;
930 if( (ret
= isom_add_extension_binary( parent
, box
->type
, LSMASH_BOX_PRECEDENCE_N
, exdata
, box
->size
)) < 0 )
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
);
938 lsmash_free( exdata
);
942 static void *isom_sample_description_alloc( lsmash_codec_type_t sample_type
, isom_stsd_t
*stsd
)
944 assert( isom_check_media_hdlr_from_stsd( stsd
) );
945 /* Determine suitable allocation size. */
946 size_t alloc_size
= 0;
947 lsmash_media_type media_type
= ((isom_mdia_t
*)stsd
->parent
->parent
->parent
)->hdlr
->componentSubtype
;
948 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
949 alloc_size
= sizeof(isom_visual_entry_t
);
950 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
951 alloc_size
= sizeof(isom_audio_entry_t
);
952 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
954 if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
955 alloc_size
= sizeof(isom_tx3g_entry_t
);
956 else if( lsmash_check_codec_type_identical( sample_type
, QT_CODEC_TYPE_TEXT_TEXT
) )
957 alloc_size
= sizeof(isom_qt_text_entry_t
);
959 else if( lsmash_check_codec_type_identical( sample_type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
) )
960 alloc_size
= sizeof(isom_mp4s_entry_t
);
961 /* Return allocated memory block if the allocation size is non-zero. */
962 if( alloc_size
== 0 )
964 return lsmash_malloc_zero( alloc_size
);
967 static void *isom_add_description( lsmash_codec_type_t sample_type
, isom_stsd_t
*stsd
)
969 void *sample
= isom_sample_description_alloc( sample_type
, stsd
);
972 if( lsmash_add_entry( &stsd
->list
, sample
) < 0 )
974 lsmash_free( sample
);
977 if( lsmash_add_entry( &stsd
->extensions
, sample
) < 0 )
979 lsmash_remove_entry_tail( &stsd
->list
, lsmash_free
);
982 ((isom_box_t
*)sample
)->destruct
= (isom_extension_destructor_t
)isom_remove_sample_description
;
986 static int isom_read_visual_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
988 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
989 return isom_read_unknown_box( file
, box
, parent
, level
);
990 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
992 return LSMASH_ERR_MEMORY_ALLOC
;
993 lsmash_bs_t
*bs
= file
->bs
;
994 for( int i
= 0; i
< 6; i
++ )
995 visual
->reserved
[i
] = lsmash_bs_get_byte( bs
);
996 visual
->data_reference_index
= lsmash_bs_get_be16( bs
);
997 visual
->version
= lsmash_bs_get_be16( bs
);
998 visual
->revision_level
= lsmash_bs_get_be16( bs
);
999 visual
->vendor
= lsmash_bs_get_be32( bs
);
1000 visual
->temporalQuality
= lsmash_bs_get_be32( bs
);
1001 visual
->spatialQuality
= lsmash_bs_get_be32( bs
);
1002 visual
->width
= lsmash_bs_get_be16( bs
);
1003 visual
->height
= lsmash_bs_get_be16( bs
);
1004 visual
->horizresolution
= lsmash_bs_get_be32( bs
);
1005 visual
->vertresolution
= lsmash_bs_get_be32( bs
);
1006 visual
->dataSize
= lsmash_bs_get_be32( bs
);
1007 visual
->frame_count
= lsmash_bs_get_be16( bs
);
1008 for( int i
= 0; i
< 32; i
++ )
1009 visual
->compressorname
[i
] = lsmash_bs_get_byte( bs
);
1010 visual
->depth
= lsmash_bs_get_be16( bs
);
1011 visual
->color_table_ID
= lsmash_bs_get_be16( bs
);
1013 if( visual
->color_table_ID
== 0
1014 && lsmash_bs_get_pos( bs
) < box
->size
1015 && (ret
= isom_read_qt_color_table( bs
, &visual
->color_table
)) < 0 )
1017 box
->parent
= parent
;
1018 box
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1019 isom_box_common_copy( visual
, box
);
1020 if( (ret
= isom_add_print_func( file
, visual
, level
)) < 0 )
1022 return isom_read_children( file
, box
, visual
, level
);
1025 static int isom_read_esds( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1027 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4V_VIDEO
)
1028 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4A_AUDIO
)
1029 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_M4AE_AUDIO
)
1030 && !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
)
1031 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1032 return isom_read_unknown_box( file
, box
, parent
, level
);
1033 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1035 box
->type
= QT_BOX_TYPE_ESDS
;
1036 if( parent
->parent
&& lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_CODEC_TYPE_MP4A_AUDIO
) )
1037 parent
->parent
->type
= QT_CODEC_TYPE_MP4A_AUDIO
;
1040 box
->type
= ISOM_BOX_TYPE_ESDS
;
1041 ADD_BOX( esds
, void );
1042 lsmash_bs_t
*bs
= file
->bs
;
1043 esds
->ES
= mp4sys_get_descriptor( bs
, NULL
);
1045 return LSMASH_ERR_INVALID_DATA
;
1046 return isom_read_leaf_box_common_last_process( file
, box
, level
, esds
);
1049 static int isom_read_btrt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1051 ADD_BOX( btrt
, isom_visual_entry_t
);
1052 lsmash_bs_t
*bs
= file
->bs
;
1053 btrt
->bufferSizeDB
= lsmash_bs_get_be32( bs
);
1054 btrt
->maxBitrate
= lsmash_bs_get_be32( bs
);
1055 btrt
->avgBitrate
= lsmash_bs_get_be32( bs
);
1056 return isom_read_leaf_box_common_last_process( file
, box
, level
, btrt
);
1059 static int isom_read_glbl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1061 ADD_BOX( glbl
, isom_visual_entry_t
);
1062 lsmash_bs_t
*bs
= file
->bs
;
1063 uint32_t header_size
= box
->size
- ISOM_BASEBOX_COMMON_SIZE
;
1066 glbl
->header_data
= lsmash_malloc( header_size
);
1067 if( !glbl
->header_data
)
1068 return LSMASH_ERR_MEMORY_ALLOC
;
1069 for( uint32_t i
= 0; i
< header_size
; i
++ )
1070 glbl
->header_data
[i
] = lsmash_bs_get_byte( bs
);
1072 glbl
->header_size
= header_size
;
1073 return isom_read_leaf_box_common_last_process( file
, box
, level
, glbl
);
1076 static int isom_read_clap( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1078 ADD_BOX( clap
, isom_visual_entry_t
);
1079 lsmash_bs_t
*bs
= file
->bs
;
1080 clap
->cleanApertureWidthN
= lsmash_bs_get_be32( bs
);
1081 clap
->cleanApertureWidthD
= lsmash_bs_get_be32( bs
);
1082 clap
->cleanApertureHeightN
= lsmash_bs_get_be32( bs
);
1083 clap
->cleanApertureHeightD
= lsmash_bs_get_be32( bs
);
1084 clap
->horizOffN
= lsmash_bs_get_be32( bs
);
1085 clap
->horizOffD
= lsmash_bs_get_be32( bs
);
1086 clap
->vertOffN
= lsmash_bs_get_be32( bs
);
1087 clap
->vertOffD
= lsmash_bs_get_be32( bs
);
1088 return isom_read_leaf_box_common_last_process( file
, box
, level
, clap
);
1091 static int isom_read_pasp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1093 ADD_BOX( pasp
, isom_visual_entry_t
);
1094 lsmash_bs_t
*bs
= file
->bs
;
1095 pasp
->hSpacing
= lsmash_bs_get_be32( bs
);
1096 pasp
->vSpacing
= lsmash_bs_get_be32( bs
);
1097 return isom_read_leaf_box_common_last_process( file
, box
, level
, pasp
);
1100 static int isom_read_colr( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1102 ADD_BOX( colr
, isom_visual_entry_t
);
1103 lsmash_bs_t
*bs
= file
->bs
;
1104 colr
->color_parameter_type
= lsmash_bs_get_be32( bs
);
1105 if( colr
->color_parameter_type
== QT_COLOR_PARAMETER_TYPE_NCLC
1106 || colr
->color_parameter_type
== ISOM_COLOR_PARAMETER_TYPE_NCLX
)
1108 colr
->primaries_index
= lsmash_bs_get_be16( bs
);
1109 colr
->transfer_function_index
= lsmash_bs_get_be16( bs
);
1110 colr
->matrix_index
= lsmash_bs_get_be16( bs
);
1111 if( colr
->color_parameter_type
== ISOM_COLOR_PARAMETER_TYPE_NCLX
)
1113 if( lsmash_bs_count( bs
) < box
->size
)
1115 uint8_t temp8
= lsmash_bs_get_byte( bs
);
1116 colr
->full_range_flag
= (temp8
>> 7) & 0x01;
1117 colr
->reserved
= temp8
& 0x7f;
1121 /* It seems this box is broken or incomplete. */
1122 box
->manager
|= LSMASH_INCOMPLETE_BOX
;
1123 colr
->full_range_flag
= 0;
1128 box
->manager
|= LSMASH_QTFF_BASE
;
1130 box
->type
= (box
->manager
& LSMASH_QTFF_BASE
) ? QT_BOX_TYPE_COLR
: ISOM_BOX_TYPE_COLR
;
1131 return isom_read_leaf_box_common_last_process( file
, box
, level
, colr
);
1134 static int isom_read_gama( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1136 ADD_BOX( gama
, isom_visual_entry_t
);
1137 lsmash_bs_t
*bs
= file
->bs
;
1138 gama
->level
= lsmash_bs_get_be32( bs
);
1139 return isom_read_leaf_box_common_last_process( file
, box
, level
, gama
);
1142 static int isom_read_fiel( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1144 ADD_BOX( fiel
, isom_visual_entry_t
);
1145 lsmash_bs_t
*bs
= file
->bs
;
1146 fiel
->fields
= lsmash_bs_get_byte( bs
);
1147 fiel
->detail
= lsmash_bs_get_byte( bs
);
1148 return isom_read_leaf_box_common_last_process( file
, box
, level
, fiel
);
1151 static int isom_read_cspc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1153 ADD_BOX( cspc
, isom_visual_entry_t
);
1154 lsmash_bs_t
*bs
= file
->bs
;
1155 cspc
->pixel_format
= lsmash_bs_get_be32( bs
);
1156 return isom_read_leaf_box_common_last_process( file
, box
, level
, cspc
);
1159 static int isom_read_sgbt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1161 ADD_BOX( sgbt
, isom_visual_entry_t
);
1162 lsmash_bs_t
*bs
= file
->bs
;
1163 sgbt
->significantBits
= lsmash_bs_get_byte( bs
);
1164 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgbt
);
1167 static int isom_read_stsl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1169 ADD_BOX( stsl
, isom_visual_entry_t
);
1170 lsmash_bs_t
*bs
= file
->bs
;
1171 stsl
->constraint_flag
= lsmash_bs_get_byte( bs
);
1172 stsl
->scale_method
= lsmash_bs_get_byte( bs
);
1173 stsl
->display_center_x
= lsmash_bs_get_be16( bs
);
1174 stsl
->display_center_y
= lsmash_bs_get_be16( bs
);
1175 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsl
);
1178 static int isom_read_audio_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1180 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1181 return isom_read_unknown_box( file
, box
, parent
, level
);
1182 isom_audio_entry_t
*audio
= (isom_audio_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1184 return LSMASH_ERR_MEMORY_ALLOC
;
1185 lsmash_bs_t
*bs
= file
->bs
;
1186 for( int i
= 0; i
< 6; i
++ )
1187 audio
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1188 audio
->data_reference_index
= lsmash_bs_get_be16( bs
);
1189 audio
->version
= lsmash_bs_get_be16( bs
);
1190 audio
->revision_level
= lsmash_bs_get_be16( bs
);
1191 audio
->vendor
= lsmash_bs_get_be32( bs
);
1192 audio
->channelcount
= lsmash_bs_get_be16( bs
);
1193 audio
->samplesize
= lsmash_bs_get_be16( bs
);
1194 audio
->compression_ID
= lsmash_bs_get_be16( bs
);
1195 audio
->packet_size
= lsmash_bs_get_be16( bs
);
1196 audio
->samplerate
= lsmash_bs_get_be32( bs
);
1197 if( audio
->version
== 0 && isom_is_qt_audio( box
->type
) )
1199 /* Skip weird extra bytes.
1200 * About QTFF, extensions were first added with Sound Sample Description v1. */
1201 while( lsmash_bs_count( bs
) + ISOM_BASEBOX_COMMON_SIZE
<= box
->size
)
1203 uint32_t size
= lsmash_bs_show_be32( bs
, 0 );
1204 if( size
== 0 || lsmash_bs_count( bs
) + size
> box
->size
)
1205 lsmash_bs_skip_bytes( bs
, 1 );
1210 else if( audio
->version
== 1 )
1212 if( ((isom_stsd_t
*)parent
)->version
== 0 )
1214 audio
->samplesPerPacket
= lsmash_bs_get_be32( bs
);
1215 audio
->bytesPerPacket
= lsmash_bs_get_be32( bs
);
1216 audio
->bytesPerFrame
= lsmash_bs_get_be32( bs
);
1217 audio
->bytesPerSample
= lsmash_bs_get_be32( bs
);
1218 box
->manager
|= LSMASH_QTFF_BASE
;
1221 /* AudioSampleEntryV1 has no additional fields. */
1222 box
->manager
&= ~LSMASH_QTFF_BASE
;
1224 else if( audio
->version
== 2 )
1226 audio
->sizeOfStructOnly
= lsmash_bs_get_be32( bs
);
1227 audio
->audioSampleRate
= lsmash_bs_get_be64( bs
);
1228 audio
->numAudioChannels
= lsmash_bs_get_be32( bs
);
1229 audio
->always7F000000
= lsmash_bs_get_be32( bs
);
1230 audio
->constBitsPerChannel
= lsmash_bs_get_be32( bs
);
1231 audio
->formatSpecificFlags
= lsmash_bs_get_be32( bs
);
1232 audio
->constBytesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1233 audio
->constLPCMFramesPerAudioPacket
= lsmash_bs_get_be32( bs
);
1234 box
->manager
|= LSMASH_QTFF_BASE
;
1236 box
->parent
= parent
;
1237 box
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1238 isom_box_common_copy( audio
, box
);
1239 int ret
= isom_add_print_func( file
, audio
, level
);
1242 return isom_read_children( file
, box
, audio
, level
);
1245 static int isom_read_wave( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1247 ADD_BOX( wave
, isom_audio_entry_t
);
1248 isom_box_common_copy( wave
, box
);
1249 int ret
= isom_add_print_func( file
, wave
, level
);
1252 return isom_read_children( file
, box
, wave
, level
);
1255 static int isom_read_frma( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1257 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) || ((isom_wave_t
*)parent
)->frma
)
1258 return isom_read_unknown_box( file
, box
, parent
, level
);
1259 ADD_BOX( frma
, isom_wave_t
);
1260 lsmash_bs_t
*bs
= file
->bs
;
1261 frma
->data_format
= lsmash_bs_get_be32( bs
);
1262 return isom_read_leaf_box_common_last_process( file
, box
, level
, frma
);
1265 static int isom_read_enda( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1267 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) || ((isom_wave_t
*)parent
)->enda
)
1268 return isom_read_unknown_box( file
, box
, parent
, level
);
1269 ADD_BOX( enda
, isom_wave_t
);
1270 lsmash_bs_t
*bs
= file
->bs
;
1271 enda
->littleEndian
= lsmash_bs_get_be16( bs
);
1272 return isom_read_leaf_box_common_last_process( file
, box
, level
, enda
);
1275 static int isom_read_terminator( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1277 if( !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) || ((isom_wave_t
*)parent
)->terminator
)
1278 return isom_read_unknown_box( file
, box
, parent
, level
);
1279 ADD_BOX( terminator
, isom_wave_t
);
1280 return isom_read_leaf_box_common_last_process( file
, box
, level
, terminator
);
1283 static int isom_read_chan( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1285 ADD_BOX( chan
, isom_audio_entry_t
);
1286 lsmash_bs_t
*bs
= file
->bs
;
1287 chan
->channelLayoutTag
= lsmash_bs_get_be32( bs
);
1288 chan
->channelBitmap
= lsmash_bs_get_be32( bs
);
1289 chan
->numberChannelDescriptions
= lsmash_bs_get_be32( bs
);
1290 if( chan
->numberChannelDescriptions
)
1292 isom_channel_description_t
*desc
= lsmash_malloc( chan
->numberChannelDescriptions
* sizeof(isom_channel_description_t
) );
1294 return LSMASH_ERR_MEMORY_ALLOC
;
1295 chan
->channelDescriptions
= desc
;
1296 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
1298 desc
->channelLabel
= lsmash_bs_get_be32( bs
);
1299 desc
->channelFlags
= lsmash_bs_get_be32( bs
);
1300 for( int j
= 0; j
< 3; j
++ )
1301 desc
->coordinates
[j
] = lsmash_bs_get_be32( bs
);
1304 /* A 'chan' box often contains extra 20 bytes (= the number of bytes of one channel description). */
1305 isom_skip_box_rest( bs
, box
);
1306 return isom_read_leaf_box_common_last_process( file
, box
, level
, chan
);
1309 static int isom_read_srat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1311 ADD_BOX( srat
, isom_audio_entry_t
);
1312 lsmash_bs_t
*bs
= file
->bs
;
1313 srat
->sampling_rate
= lsmash_bs_get_be32( bs
);
1314 return isom_read_leaf_box_common_last_process( file
, box
, level
, srat
);
1317 static int isom_read_qt_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1319 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1320 return isom_read_unknown_box( file
, box
, parent
, level
);
1321 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1323 return LSMASH_ERR_MEMORY_ALLOC
;
1324 lsmash_bs_t
*bs
= file
->bs
;
1325 for( int i
= 0; i
< 6; i
++ )
1326 text
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1327 text
->data_reference_index
= lsmash_bs_get_be16( bs
);
1328 text
->displayFlags
= lsmash_bs_get_be32( bs
);
1329 text
->textJustification
= lsmash_bs_get_be32( bs
);
1330 for( int i
= 0; i
< 3; i
++ )
1331 text
->bgColor
[i
] = lsmash_bs_get_be16( bs
);
1332 text
->top
= lsmash_bs_get_be16( bs
);
1333 text
->left
= lsmash_bs_get_be16( bs
);
1334 text
->bottom
= lsmash_bs_get_be16( bs
);
1335 text
->right
= lsmash_bs_get_be16( bs
);
1336 text
->scrpStartChar
= lsmash_bs_get_be32( bs
);
1337 text
->scrpHeight
= lsmash_bs_get_be16( bs
);
1338 text
->scrpAscent
= lsmash_bs_get_be16( bs
);
1339 text
->scrpFont
= lsmash_bs_get_be16( bs
);
1340 text
->scrpFace
= lsmash_bs_get_be16( bs
);
1341 text
->scrpSize
= lsmash_bs_get_be16( bs
);
1342 for( int i
= 0; i
< 3; i
++ )
1343 text
->scrpColor
[i
] = lsmash_bs_get_be16( bs
);
1344 text
->font_name_length
= lsmash_bs_get_byte( bs
);
1345 if( text
->font_name_length
)
1347 text
->font_name
= lsmash_malloc( text
->font_name_length
+ 1 );
1348 if( !text
->font_name
)
1349 return LSMASH_ERR_MEMORY_ALLOC
;
1350 for( uint8_t i
= 0; i
< text
->font_name_length
; i
++ )
1351 text
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1352 text
->font_name
[text
->font_name_length
] = '\0';
1354 box
->parent
= parent
;
1355 isom_box_common_copy( text
, box
);
1356 int ret
= isom_add_print_func( file
, text
, level
);
1359 return isom_read_children( file
, box
, text
, level
);
1362 static int isom_read_tx3g_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1364 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1365 return isom_read_unknown_box( file
, box
, parent
, level
);
1366 isom_tx3g_entry_t
*tx3g
= (isom_tx3g_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1368 return LSMASH_ERR_MEMORY_ALLOC
;
1369 lsmash_bs_t
*bs
= file
->bs
;
1370 for( int i
= 0; i
< 6; i
++ )
1371 tx3g
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1372 tx3g
->data_reference_index
= lsmash_bs_get_be16( bs
);
1373 tx3g
->displayFlags
= lsmash_bs_get_be32( bs
);
1374 tx3g
->horizontal_justification
= lsmash_bs_get_byte( bs
);
1375 tx3g
->vertical_justification
= lsmash_bs_get_byte( bs
);
1376 for( int i
= 0; i
< 4; i
++ )
1377 tx3g
->background_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1378 tx3g
->top
= lsmash_bs_get_be16( bs
);
1379 tx3g
->left
= lsmash_bs_get_be16( bs
);
1380 tx3g
->bottom
= lsmash_bs_get_be16( bs
);
1381 tx3g
->right
= lsmash_bs_get_be16( bs
);
1382 tx3g
->startChar
= lsmash_bs_get_be16( bs
);
1383 tx3g
->endChar
= lsmash_bs_get_be16( bs
);
1384 tx3g
->font_ID
= lsmash_bs_get_be16( bs
);
1385 tx3g
->face_style_flags
= lsmash_bs_get_byte( bs
);
1386 tx3g
->font_size
= lsmash_bs_get_byte( bs
);
1387 for( int i
= 0; i
< 4; i
++ )
1388 tx3g
->text_color_rgba
[i
] = lsmash_bs_get_byte( bs
);
1389 box
->parent
= parent
;
1390 isom_box_common_copy( tx3g
, box
);
1391 int ret
= isom_add_print_func( file
, tx3g
, level
);
1394 return isom_read_children( file
, box
, tx3g
, level
);
1397 static int isom_read_text_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1399 if( lsmash_check_codec_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1400 return isom_read_qt_text_description( file
, box
, parent
, level
);
1401 else if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1402 return isom_read_tx3g_description( file
, box
, parent
, level
);
1404 return isom_read_unknown_box( file
, box
, parent
, level
);
1407 static int isom_read_ftab( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1409 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
)
1410 || ((isom_tx3g_entry_t
*)parent
)->ftab
)
1411 return isom_read_unknown_box( file
, box
, parent
, level
);
1412 ADD_BOX( ftab
, isom_tx3g_entry_t
);
1413 lsmash_bs_t
*bs
= file
->bs
;
1414 uint32_t entry_count
= lsmash_bs_get_be16( bs
);
1415 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ftab
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1417 isom_font_record_t
*data
= lsmash_malloc_zero( sizeof(isom_font_record_t
) );
1419 return LSMASH_ERR_MEMORY_ALLOC
;
1420 if( lsmash_add_entry( ftab
->list
, data
) < 0 )
1422 lsmash_free( data
);
1423 return LSMASH_ERR_MEMORY_ALLOC
;
1425 data
->font_ID
= lsmash_bs_get_be16( bs
);
1426 data
->font_name_length
= lsmash_bs_get_byte( bs
);
1427 if( data
->font_name_length
)
1429 data
->font_name
= lsmash_malloc( data
->font_name_length
+ 1 );
1430 if( !data
->font_name
)
1431 return LSMASH_ERR_MEMORY_ALLOC
;
1432 for( uint8_t i
= 0; i
< data
->font_name_length
; i
++ )
1433 data
->font_name
[i
] = lsmash_bs_get_byte( bs
);
1434 data
->font_name
[data
->font_name_length
] = '\0';
1437 return isom_read_leaf_box_common_last_process( file
, box
, level
, ftab
);
1440 static int isom_read_mp4s_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1442 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1443 return isom_read_unknown_box( file
, box
, parent
, level
);
1444 isom_mp4s_entry_t
*mp4s
= (isom_mp4s_entry_t
*)isom_add_description( box
->type
, (isom_stsd_t
*)parent
);
1446 return LSMASH_ERR_MEMORY_ALLOC
;
1447 lsmash_bs_t
*bs
= file
->bs
;
1448 for( int i
= 0; i
< 6; i
++ )
1449 mp4s
->reserved
[i
] = lsmash_bs_get_byte( bs
);
1450 mp4s
->data_reference_index
= lsmash_bs_get_be16( bs
);
1451 box
->parent
= parent
;
1452 isom_box_common_copy( mp4s
, box
);
1453 int ret
= isom_add_print_func( file
, mp4s
, level
);
1456 return isom_read_children( file
, box
, mp4s
, level
);
1459 static int isom_read_other_description( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1461 if( lsmash_check_codec_type_identical( box
->type
, ISOM_CODEC_TYPE_MP4S_SYSTEM
) )
1462 return isom_read_mp4s_description( file
, box
, parent
, level
);
1463 return isom_read_unknown_box( file
, box
, parent
, level
);
1466 static int isom_read_stts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1468 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stts
)
1469 return isom_read_unknown_box( file
, box
, parent
, level
);
1470 ADD_BOX( stts
, isom_stbl_t
);
1471 lsmash_bs_t
*bs
= file
->bs
;
1472 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1473 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1475 isom_stts_entry_t
*data
= lsmash_malloc( sizeof(isom_stts_entry_t
) );
1477 return LSMASH_ERR_MEMORY_ALLOC
;
1478 if( lsmash_add_entry( stts
->list
, data
) < 0 )
1480 lsmash_free( data
);
1481 return LSMASH_ERR_MEMORY_ALLOC
;
1483 data
->sample_count
= lsmash_bs_get_be32( bs
);
1484 data
->sample_delta
= lsmash_bs_get_be32( bs
);
1486 return isom_read_leaf_box_common_last_process( file
, box
, level
, stts
);
1489 static int isom_read_ctts( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1491 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->ctts
)
1492 return isom_read_unknown_box( file
, box
, parent
, level
);
1493 ADD_BOX( ctts
, isom_stbl_t
);
1494 lsmash_bs_t
*bs
= file
->bs
;
1495 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1496 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& ctts
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1498 isom_ctts_entry_t
*data
= lsmash_malloc( sizeof(isom_ctts_entry_t
) );
1500 return LSMASH_ERR_MEMORY_ALLOC
;
1501 if( lsmash_add_entry( ctts
->list
, data
) < 0 )
1503 lsmash_free( data
);
1504 return LSMASH_ERR_MEMORY_ALLOC
;
1506 data
->sample_count
= lsmash_bs_get_be32( bs
);
1507 data
->sample_offset
= lsmash_bs_get_be32( bs
);
1509 return isom_read_leaf_box_common_last_process( file
, box
, level
, ctts
);
1512 static int isom_read_cslg( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1514 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->cslg
)
1515 return isom_read_unknown_box( file
, box
, parent
, level
);
1516 ADD_BOX( cslg
, isom_stbl_t
);
1517 lsmash_bs_t
*bs
= file
->bs
;
1518 cslg
->compositionToDTSShift
= lsmash_bs_get_be32( bs
);
1519 cslg
->leastDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1520 cslg
->greatestDecodeToDisplayDelta
= lsmash_bs_get_be32( bs
);
1521 cslg
->compositionStartTime
= lsmash_bs_get_be32( bs
);
1522 cslg
->compositionEndTime
= lsmash_bs_get_be32( bs
);
1523 return isom_read_leaf_box_common_last_process( file
, box
, level
, cslg
);
1526 static int isom_read_stss( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1528 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stss
)
1529 return isom_read_unknown_box( file
, box
, parent
, level
);
1530 ADD_BOX( stss
, isom_stbl_t
);
1531 lsmash_bs_t
*bs
= file
->bs
;
1532 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1533 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stss
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1535 isom_stss_entry_t
*data
= lsmash_malloc( sizeof(isom_stss_entry_t
) );
1537 return LSMASH_ERR_MEMORY_ALLOC
;
1538 if( lsmash_add_entry( stss
->list
, data
) < 0 )
1540 lsmash_free( data
);
1541 return LSMASH_ERR_MEMORY_ALLOC
;
1543 data
->sample_number
= lsmash_bs_get_be32( bs
);
1545 return isom_read_leaf_box_common_last_process( file
, box
, level
, stss
);
1548 static int isom_read_stps( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1550 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stps
)
1551 return isom_read_unknown_box( file
, box
, parent
, level
);
1552 ADD_BOX( stps
, isom_stbl_t
);
1553 lsmash_bs_t
*bs
= file
->bs
;
1554 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1555 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stps
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1557 isom_stps_entry_t
*data
= lsmash_malloc( sizeof(isom_stps_entry_t
) );
1559 return LSMASH_ERR_MEMORY_ALLOC
;
1560 if( lsmash_add_entry( stps
->list
, data
) < 0 )
1562 lsmash_free( data
);
1563 return LSMASH_ERR_MEMORY_ALLOC
;
1565 data
->sample_number
= lsmash_bs_get_be32( bs
);
1567 return isom_read_leaf_box_common_last_process( file
, box
, level
, stps
);
1570 static int isom_read_sdtp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1572 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1573 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
))
1574 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) && ((isom_stbl_t
*)parent
)->sdtp
)
1575 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) && ((isom_traf_t
*)parent
)->sdtp
))
1576 return isom_read_unknown_box( file
, box
, parent
, level
);
1577 ADD_BOX( sdtp
, isom_box_t
);
1578 lsmash_bs_t
*bs
= file
->bs
;
1579 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
; pos
= lsmash_bs_count( bs
) )
1581 isom_sdtp_entry_t
*data
= lsmash_malloc( sizeof(isom_sdtp_entry_t
) );
1583 return LSMASH_ERR_MEMORY_ALLOC
;
1584 if( lsmash_add_entry( sdtp
->list
, data
) < 0 )
1586 lsmash_free( data
);
1587 return LSMASH_ERR_MEMORY_ALLOC
;
1589 uint8_t temp
= lsmash_bs_get_byte( bs
);
1590 data
->is_leading
= (temp
>> 6) & 0x3;
1591 data
->sample_depends_on
= (temp
>> 4) & 0x3;
1592 data
->sample_is_depended_on
= (temp
>> 2) & 0x3;
1593 data
->sample_has_redundancy
= temp
& 0x3;
1595 return isom_read_leaf_box_common_last_process( file
, box
, level
, sdtp
);
1598 static int isom_read_stsc( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1600 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stsc
)
1601 return isom_read_unknown_box( file
, box
, parent
, level
);
1602 ADD_BOX( stsc
, isom_stbl_t
);
1603 lsmash_bs_t
*bs
= file
->bs
;
1604 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1605 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stsc
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1607 isom_stsc_entry_t
*data
= lsmash_malloc( sizeof(isom_stsc_entry_t
) );
1609 return LSMASH_ERR_MEMORY_ALLOC
;
1610 if( lsmash_add_entry( stsc
->list
, data
) < 0 )
1612 lsmash_free( data
);
1613 return LSMASH_ERR_MEMORY_ALLOC
;
1615 data
->first_chunk
= lsmash_bs_get_be32( bs
);
1616 data
->samples_per_chunk
= lsmash_bs_get_be32( bs
);
1617 data
->sample_description_index
= lsmash_bs_get_be32( bs
);
1619 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsc
);
1622 static int isom_read_stsz( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1624 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stsz
)
1625 return isom_read_unknown_box( file
, box
, parent
, level
);
1626 ADD_BOX( stsz
, isom_stbl_t
);
1627 lsmash_bs_t
*bs
= file
->bs
;
1628 stsz
->sample_size
= lsmash_bs_get_be32( bs
);
1629 stsz
->sample_count
= lsmash_bs_get_be32( bs
);
1630 uint64_t pos
= lsmash_bs_count( bs
);
1631 if( pos
< box
->size
)
1633 stsz
->list
= lsmash_create_entry_list();
1635 return LSMASH_ERR_MEMORY_ALLOC
;
1636 for( ; pos
< box
->size
&& stsz
->list
->entry_count
< stsz
->sample_count
; pos
= lsmash_bs_count( bs
) )
1638 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1640 return LSMASH_ERR_MEMORY_ALLOC
;
1641 if( lsmash_add_entry( stsz
->list
, data
) < 0 )
1643 lsmash_free( data
);
1644 return LSMASH_ERR_MEMORY_ALLOC
;
1646 data
->entry_size
= lsmash_bs_get_be32( bs
);
1649 return isom_read_leaf_box_common_last_process( file
, box
, level
, stsz
);
1652 static int isom_read_stz2( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1654 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stz2
)
1655 return isom_read_unknown_box( file
, box
, parent
, level
);
1656 ADD_BOX( stz2
, isom_stbl_t
);
1657 lsmash_bs_t
*bs
= file
->bs
;
1658 uint32_t temp32
= lsmash_bs_get_be32( bs
);
1659 stz2
->reserved
= temp32
>> 24;
1660 stz2
->field_size
= temp32
& 0xff;
1661 stz2
->sample_count
= lsmash_bs_get_be32( bs
);
1662 uint64_t pos
= lsmash_bs_count( bs
);
1663 if( pos
< box
->size
)
1665 if( stz2
->field_size
== 16 || stz2
->field_size
== 8 )
1667 uint64_t (*bs_get_funcs
[2])( lsmash_bs_t
* ) =
1669 lsmash_bs_get_byte_to_64
,
1670 lsmash_bs_get_be16_to_64
1672 uint64_t (*bs_get_entry_size
)( lsmash_bs_t
* ) = bs_get_funcs
[ stz2
->field_size
== 16 ? 1 : 0 ];
1673 for( ; pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
; pos
= lsmash_bs_count( bs
) )
1675 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1677 return LSMASH_ERR_MEMORY_ALLOC
;
1678 if( lsmash_add_entry( stz2
->list
, data
) < 0 )
1680 lsmash_free( data
);
1681 return LSMASH_ERR_MEMORY_ALLOC
;
1683 data
->entry_size
= bs_get_entry_size( bs
);
1686 else if( stz2
->field_size
== 4 )
1690 while( pos
< box
->size
&& stz2
->list
->entry_count
< stz2
->sample_count
)
1692 isom_stsz_entry_t
*data
= lsmash_malloc( sizeof(isom_stsz_entry_t
) );
1694 return LSMASH_ERR_MEMORY_ALLOC
;
1695 if( lsmash_add_entry( stz2
->list
, data
) < 0 )
1697 lsmash_free( data
);
1698 return LSMASH_ERR_MEMORY_ALLOC
;
1700 /* Read a byte by two entries. */
1703 temp8
= lsmash_bs_get_byte( bs
);
1704 data
->entry_size
= (temp8
>> 4) & 0xf;
1708 pos
= lsmash_bs_count( bs
);
1709 data
->entry_size
= temp8
& 0xf;
1715 return LSMASH_ERR_INVALID_DATA
;
1717 return isom_read_leaf_box_common_last_process( file
, box
, level
, stz2
);
1720 static int isom_read_stco( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1722 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) || ((isom_stbl_t
*)parent
)->stco
)
1723 return isom_read_unknown_box( file
, box
, parent
, level
);
1724 box
->type
= lsmash_form_iso_box_type( box
->type
.fourcc
);
1725 int is_stco
= lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_STCO
);
1726 isom_stco_t
*stco
= is_stco
1727 ? isom_add_stco( (isom_stbl_t
*)parent
)
1728 : isom_add_co64( (isom_stbl_t
*)parent
);
1730 return LSMASH_ERR_NAMELESS
;
1731 lsmash_bs_t
*bs
= file
->bs
;
1732 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1734 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1736 isom_stco_entry_t
*data
= lsmash_malloc( sizeof(isom_stco_entry_t
) );
1738 return LSMASH_ERR_MEMORY_ALLOC
;
1739 if( lsmash_add_entry( stco
->list
, data
) < 0 )
1741 lsmash_free( data
);
1742 return LSMASH_ERR_MEMORY_ALLOC
;
1744 data
->chunk_offset
= lsmash_bs_get_be32( bs
);
1748 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& stco
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1750 isom_co64_entry_t
*data
= lsmash_malloc( sizeof(isom_co64_entry_t
) );
1752 return LSMASH_ERR_MEMORY_ALLOC
;
1753 if( lsmash_add_entry( stco
->list
, data
) < 0 )
1755 lsmash_free( data
);
1756 return LSMASH_ERR_MEMORY_ALLOC
;
1758 data
->chunk_offset
= lsmash_bs_get_be64( bs
);
1761 return isom_read_leaf_box_common_last_process( file
, box
, level
, stco
);
1764 static int isom_read_sgpd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1766 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1767 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1768 return isom_read_unknown_box( file
, box
, parent
, level
);
1769 ADD_BOX( sgpd
, void );
1770 lsmash_bs_t
*bs
= file
->bs
;
1771 sgpd
->grouping_type
= lsmash_bs_get_be32( bs
);
1772 if( box
->version
== 1 )
1773 sgpd
->default_length
= lsmash_bs_get_be32( bs
);
1774 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1775 switch( sgpd
->grouping_type
)
1777 case ISOM_GROUP_TYPE_RAP
:
1779 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sgpd
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1781 isom_rap_entry_t
*data
= lsmash_malloc( sizeof(isom_rap_entry_t
) );
1783 return LSMASH_ERR_MEMORY_ALLOC
;
1784 if( lsmash_add_entry( sgpd
->list
, data
) < 0 )
1786 lsmash_free( data
);
1787 return LSMASH_ERR_MEMORY_ALLOC
;
1789 memset( data
, 0, sizeof(isom_rap_entry_t
) );
1790 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1791 if( box
->version
== 1 && !sgpd
->default_length
)
1792 data
->description_length
= lsmash_bs_get_be32( bs
);
1795 uint8_t temp
= lsmash_bs_get_byte( bs
);
1796 data
->num_leading_samples_known
= (temp
>> 7) & 0x01;
1797 data
->num_leading_samples
= temp
& 0x7f;
1802 case ISOM_GROUP_TYPE_ROLL
:
1803 case ISOM_GROUP_TYPE_PROL
:
1805 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sgpd
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1807 isom_roll_entry_t
*data
= lsmash_malloc( sizeof(isom_roll_entry_t
) );
1809 return LSMASH_ERR_MEMORY_ALLOC
;
1810 if( lsmash_add_entry( sgpd
->list
, data
) < 0 )
1812 lsmash_free( data
);
1813 return LSMASH_ERR_MEMORY_ALLOC
;
1815 memset( data
, 0, sizeof(isom_roll_entry_t
) );
1816 /* We don't know groups decided by variable description length. If encountering, skip getting of bytes of it. */
1817 if( box
->version
== 1 && !sgpd
->default_length
)
1818 data
->description_length
= lsmash_bs_get_be32( bs
);
1820 data
->roll_distance
= lsmash_bs_get_be16( bs
);
1827 return isom_read_leaf_box_common_last_process( file
, box
, level
, sgpd
);
1830 static int isom_read_sbgp( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1832 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
)
1833 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1834 return isom_read_unknown_box( file
, box
, parent
, level
);
1835 ADD_BOX( sbgp
, void );
1836 lsmash_bs_t
*bs
= file
->bs
;
1837 sbgp
->grouping_type
= lsmash_bs_get_be32( bs
);
1838 if( box
->version
== 1 )
1839 sbgp
->grouping_type_parameter
= lsmash_bs_get_be32( bs
);
1840 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
1841 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& sbgp
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1843 isom_group_assignment_entry_t
*data
= lsmash_malloc( sizeof(isom_group_assignment_entry_t
) );
1845 return LSMASH_ERR_MEMORY_ALLOC
;
1846 if( lsmash_add_entry( sbgp
->list
, data
) < 0 )
1848 lsmash_free( data
);
1849 return LSMASH_ERR_MEMORY_ALLOC
;
1851 data
->sample_count
= lsmash_bs_get_be32( bs
);
1852 data
->group_description_index
= lsmash_bs_get_be32( bs
);
1854 return isom_read_leaf_box_common_last_process( file
, box
, level
,sbgp
);
1857 static int isom_read_udta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1859 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
1860 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
))
1861 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && ((isom_moov_t
*)parent
)->udta
)
1862 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && ((isom_trak_t
*)parent
)->udta
) )
1863 return isom_read_unknown_box( file
, box
, parent
, level
);
1864 ADD_BOX( udta
, void );
1865 isom_box_common_copy( udta
, box
);
1866 int ret
= isom_add_print_func( file
, udta
, level
);
1869 return isom_read_children( file
, box
, udta
, level
);
1872 static int isom_read_chpl( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1874 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) || ((isom_udta_t
*)parent
)->chpl
)
1875 return isom_read_unknown_box( file
, box
, parent
, level
);
1876 ADD_BOX( chpl
, isom_udta_t
);
1877 lsmash_bs_t
*bs
= file
->bs
;
1878 uint32_t entry_count
;
1879 if( box
->version
== 1 )
1881 chpl
->unknown
= lsmash_bs_get_byte( bs
);
1882 entry_count
= lsmash_bs_get_be32( bs
);
1885 entry_count
= lsmash_bs_get_byte( bs
);
1886 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& chpl
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
1888 isom_chpl_entry_t
*data
= lsmash_malloc( sizeof(isom_chpl_entry_t
) );
1890 return LSMASH_ERR_MEMORY_ALLOC
;
1891 if( lsmash_add_entry( chpl
->list
, data
) < 0 )
1893 lsmash_free( data
);
1894 return LSMASH_ERR_MEMORY_ALLOC
;
1896 data
->start_time
= lsmash_bs_get_be64( bs
);
1897 data
->chapter_name_length
= lsmash_bs_get_byte( bs
);
1898 data
->chapter_name
= lsmash_malloc( data
->chapter_name_length
+ 1 );
1899 if( !data
->chapter_name
)
1901 lsmash_free( data
);
1902 return LSMASH_ERR_MEMORY_ALLOC
;
1904 for( uint8_t i
= 0; i
< data
->chapter_name_length
; i
++ )
1905 data
->chapter_name
[i
] = lsmash_bs_get_byte( bs
);
1906 data
->chapter_name
[data
->chapter_name_length
] = '\0';
1908 return isom_read_leaf_box_common_last_process( file
, box
, level
, chpl
);
1911 static int isom_read_mvex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1913 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) || ((isom_moov_t
*)parent
)->mvex
)
1914 return isom_read_unknown_box( file
, box
, parent
, level
);
1915 ADD_BOX( mvex
, isom_moov_t
);
1916 file
->flags
|= LSMASH_FILE_MODE_FRAGMENTED
;
1917 isom_box_common_copy( mvex
, box
);
1918 int ret
= isom_add_print_func( file
, mvex
, level
);
1921 return isom_read_children( file
, box
, mvex
, level
);
1924 static int isom_read_mehd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1926 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
) || ((isom_mvex_t
*)parent
)->mehd
)
1927 return isom_read_unknown_box( file
, box
, parent
, level
);
1928 ADD_BOX( mehd
, isom_mvex_t
);
1929 lsmash_bs_t
*bs
= file
->bs
;
1930 if( box
->version
== 1 )
1931 mehd
->fragment_duration
= lsmash_bs_get_be64( bs
);
1933 mehd
->fragment_duration
= lsmash_bs_get_be32( bs
);
1934 return isom_read_leaf_box_common_last_process( file
, box
, level
, mehd
);
1937 static isom_sample_flags_t
isom_bs_get_sample_flags( lsmash_bs_t
*bs
)
1939 uint32_t temp
= lsmash_bs_get_be32( bs
);
1940 isom_sample_flags_t flags
;
1941 flags
.reserved
= (temp
>> 28) & 0xf;
1942 flags
.is_leading
= (temp
>> 26) & 0x3;
1943 flags
.sample_depends_on
= (temp
>> 24) & 0x3;
1944 flags
.sample_is_depended_on
= (temp
>> 22) & 0x3;
1945 flags
.sample_has_redundancy
= (temp
>> 20) & 0x3;
1946 flags
.sample_padding_value
= (temp
>> 17) & 0x7;
1947 flags
.sample_is_non_sync_sample
= (temp
>> 16) & 0x1;
1948 flags
.sample_degradation_priority
= temp
& 0xffff;
1952 static int isom_read_trex( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1954 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MVEX
) )
1955 return isom_read_unknown_box( file
, box
, parent
, level
);
1956 ADD_BOX( trex
, isom_mvex_t
);
1957 box
->parent
= parent
;
1958 lsmash_bs_t
*bs
= file
->bs
;
1959 trex
->track_ID
= lsmash_bs_get_be32( bs
);
1960 trex
->default_sample_description_index
= lsmash_bs_get_be32( bs
);
1961 trex
->default_sample_duration
= lsmash_bs_get_be32( bs
);
1962 trex
->default_sample_size
= lsmash_bs_get_be32( bs
);
1963 trex
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
1964 return isom_read_leaf_box_common_last_process( file
, box
, level
, trex
);
1967 static int isom_read_moof( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1969 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
1970 return isom_read_unknown_box( file
, box
, parent
, level
);
1971 ADD_BOX( moof
, lsmash_file_t
);
1972 box
->parent
= parent
;
1973 isom_box_common_copy( moof
, box
);
1974 int ret
= isom_add_print_func( file
, moof
, level
);
1977 return isom_read_children( file
, box
, moof
, level
);
1980 static int isom_read_mfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1982 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
) || ((isom_moof_t
*)parent
)->mfhd
)
1983 return isom_read_unknown_box( file
, box
, parent
, level
);
1984 ADD_BOX( mfhd
, isom_moof_t
);
1985 lsmash_bs_t
*bs
= file
->bs
;
1986 mfhd
->sequence_number
= lsmash_bs_get_be32( bs
);
1987 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfhd
);
1990 static int isom_read_traf( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
1992 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOF
) )
1993 return isom_read_unknown_box( file
, box
, parent
, level
);
1994 ADD_BOX( traf
, isom_moof_t
);
1995 box
->parent
= parent
;
1996 isom_box_common_copy( traf
, box
);
1997 int ret
= isom_add_print_func( file
, traf
, level
);
2000 return isom_read_children( file
, box
, traf
, level
);
2003 static int isom_read_tfhd( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2005 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) || ((isom_traf_t
*)parent
)->tfhd
)
2006 return isom_read_unknown_box( file
, box
, parent
, level
);
2007 ADD_BOX( tfhd
, isom_traf_t
);
2008 lsmash_bs_t
*bs
= file
->bs
;
2009 tfhd
->track_ID
= lsmash_bs_get_be32( bs
);
2010 if( box
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) tfhd
->base_data_offset
= lsmash_bs_get_be64( bs
);
2011 if( box
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) tfhd
->sample_description_index
= lsmash_bs_get_be32( bs
);
2012 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) tfhd
->default_sample_duration
= lsmash_bs_get_be32( bs
);
2013 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) tfhd
->default_sample_size
= lsmash_bs_get_be32( bs
);
2014 if( box
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) tfhd
->default_sample_flags
= isom_bs_get_sample_flags( bs
);
2015 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfhd
);
2018 static int isom_read_tfdt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2020 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) || ((isom_traf_t
*)parent
)->tfdt
)
2021 return isom_read_unknown_box( file
, box
, parent
, level
);
2022 ADD_BOX( tfdt
, isom_traf_t
);
2023 lsmash_bs_t
*bs
= file
->bs
;
2024 if( box
->version
== 1 )
2025 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be64( bs
);
2027 tfdt
->baseMediaDecodeTime
= lsmash_bs_get_be32( bs
);
2028 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfdt
);
2031 static int isom_read_trun( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2033 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
2034 return isom_read_unknown_box( file
, box
, parent
, level
);
2035 ADD_BOX( trun
, isom_traf_t
);
2036 box
->parent
= parent
;
2037 lsmash_bs_t
*bs
= file
->bs
;
2038 int has_optional_rows
= ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
2039 | ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
2040 | ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
2041 | ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
;
2042 has_optional_rows
&= box
->flags
;
2043 trun
->sample_count
= lsmash_bs_get_be32( bs
);
2044 if( box
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) trun
->data_offset
= lsmash_bs_get_be32( bs
);
2045 if( box
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) trun
->first_sample_flags
= isom_bs_get_sample_flags( bs
);
2046 if( trun
->sample_count
&& has_optional_rows
)
2048 trun
->optional
= lsmash_create_entry_list();
2049 if( !trun
->optional
)
2050 return LSMASH_ERR_MEMORY_ALLOC
;
2051 for( uint32_t i
= 0; i
< trun
->sample_count
; i
++ )
2053 isom_trun_optional_row_t
*data
= lsmash_malloc( sizeof(isom_trun_optional_row_t
) );
2055 return LSMASH_ERR_MEMORY_ALLOC
;
2056 if( lsmash_add_entry( trun
->optional
, data
) < 0 )
2058 lsmash_free( data
);
2059 return LSMASH_ERR_MEMORY_ALLOC
;
2061 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) data
->sample_duration
= lsmash_bs_get_be32( bs
);
2062 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) data
->sample_size
= lsmash_bs_get_be32( bs
);
2063 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) data
->sample_flags
= isom_bs_get_sample_flags( bs
);
2064 if( box
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) data
->sample_composition_time_offset
= lsmash_bs_get_be32( bs
);
2067 return isom_read_leaf_box_common_last_process( file
, box
, level
, trun
);
2070 static int isom_read_free( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2072 if( file
->fake_file_mode
)
2073 return isom_read_unknown_box( file
, box
, parent
, level
);
2074 isom_box_t
*skip
= lsmash_malloc_zero( sizeof(isom_box_t
) );
2076 return LSMASH_ERR_MEMORY_ALLOC
;
2077 isom_skip_box_rest( file
->bs
, box
);
2078 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2079 isom_box_common_copy( skip
, box
);
2080 int ret
= isom_add_print_func( file
, skip
, level
);
2083 lsmash_free( skip
);
2089 static int isom_read_mdat( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2091 if( file
->fake_file_mode
|| !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
2092 return isom_read_unknown_box( file
, box
, parent
, level
);
2093 isom_box_t
*mdat
= lsmash_malloc_zero( sizeof(isom_box_t
) );
2095 return LSMASH_ERR_MEMORY_ALLOC
;
2096 isom_skip_box_rest( file
->bs
, box
);
2097 box
->manager
|= LSMASH_ABSENT_IN_FILE
;
2098 file
->flags
|= LSMASH_FILE_MODE_MEDIA
;
2099 isom_box_common_copy( mdat
, box
);
2100 int ret
= isom_add_print_func( file
, mdat
, level
);
2103 lsmash_free( mdat
);
2109 static int isom_read_meta( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2111 if( (!lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
)
2112 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
)
2113 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
)
2114 && !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
))
2115 || (lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) && ((lsmash_file_t
*)parent
)->meta
)
2116 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) && ((isom_moov_t
*)parent
)->meta
)
2117 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) && ((isom_trak_t
*)parent
)->meta
)
2118 || (lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) && ((isom_udta_t
*)parent
)->meta
) )
2119 return isom_read_unknown_box( file
, box
, parent
, level
);
2120 ADD_BOX( meta
, void );
2121 isom_box_common_copy( meta
, box
);
2122 int is_qtff
= lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_META
);
2125 box
->manager
|= LSMASH_QTFF_BASE
;
2126 meta
->manager
|= LSMASH_QTFF_BASE
;
2128 int ret
= isom_add_print_func( file
, meta
, level
);
2131 return isom_read_children( file
, box
, meta
, level
);
2134 static int isom_read_keys( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2136 if( (!lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) && !(parent
->manager
& LSMASH_QTFF_BASE
))
2137 || ((isom_meta_t
*)parent
)->keys
)
2138 return isom_read_unknown_box( file
, box
, parent
, level
);
2139 ADD_BOX( keys
, isom_meta_t
);
2140 lsmash_bs_t
*bs
= file
->bs
;
2141 uint32_t entry_count
= lsmash_bs_get_be32( bs
);
2142 for( uint64_t pos
= lsmash_bs_count( bs
); pos
< box
->size
&& keys
->list
->entry_count
< entry_count
; pos
= lsmash_bs_count( bs
) )
2144 isom_keys_entry_t
*data
= lsmash_malloc( sizeof(isom_keys_entry_t
) );
2146 return LSMASH_ERR_MEMORY_ALLOC
;
2147 if( lsmash_add_entry( keys
->list
, data
) < 0 )
2149 lsmash_free( data
);
2150 return LSMASH_ERR_MEMORY_ALLOC
;
2152 data
->key_size
= lsmash_bs_get_be32( bs
);
2153 data
->key_namespace
= lsmash_bs_get_be32( bs
);
2154 if( data
->key_size
> 8 )
2156 data
->key_value
= lsmash_bs_get_bytes( bs
, data
->key_size
- 8 );
2157 if( !data
->key_value
)
2158 return LSMASH_ERR_NAMELESS
;
2161 data
->key_value
= NULL
;
2163 return isom_read_leaf_box_common_last_process( file
, box
, level
, keys
);
2166 static int isom_read_ilst( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2168 if( (!lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
2169 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
))
2170 || ((isom_meta_t
*)parent
)->ilst
)
2171 return isom_read_unknown_box( file
, box
, parent
, level
);
2172 ADD_BOX( ilst
, isom_meta_t
);
2173 isom_box_common_copy( ilst
, box
);
2174 int ret
= isom_add_print_func( file
, ilst
, level
);
2177 return isom_read_children( file
, box
, ilst
, level
);
2180 static int isom_read_metaitem( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2182 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
2183 && !lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2184 return isom_read_unknown_box( file
, box
, parent
, level
);
2185 isom_metaitem_t
*metaitem
= isom_add_metaitem( (isom_ilst_t
*)parent
, box
->type
.fourcc
);
2188 box
->parent
= parent
;
2189 isom_box_common_copy( metaitem
, box
);
2190 int ret
= isom_add_print_func( file
, metaitem
, level
);
2193 return isom_read_children( file
, box
, metaitem
, level
);
2196 static int isom_read_mean( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2198 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
|| ((isom_metaitem_t
*)parent
)->mean
)
2199 return isom_read_unknown_box( file
, box
, parent
, level
);
2200 ADD_BOX( mean
, isom_metaitem_t
);
2201 lsmash_bs_t
*bs
= file
->bs
;
2202 mean
->meaning_string_length
= box
->size
- lsmash_bs_count( bs
);
2203 mean
->meaning_string
= lsmash_bs_get_bytes( bs
, mean
->meaning_string_length
);
2204 if( !mean
->meaning_string
)
2205 return LSMASH_ERR_NAMELESS
;
2206 return isom_read_leaf_box_common_last_process( file
, box
, level
, mean
);
2209 static int isom_read_name( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2211 if( parent
->type
.fourcc
!= ITUNES_METADATA_ITEM_CUSTOM
|| ((isom_metaitem_t
*)parent
)->name
)
2212 return isom_read_unknown_box( file
, box
, parent
, level
);
2213 ADD_BOX( name
, isom_metaitem_t
);
2214 lsmash_bs_t
*bs
= file
->bs
;
2215 name
->name_length
= box
->size
- lsmash_bs_count( bs
);
2216 name
->name
= lsmash_bs_get_bytes( bs
, name
->name_length
);
2218 return LSMASH_ERR_NAMELESS
;
2219 return isom_read_leaf_box_common_last_process( file
, box
, level
, name
);
2222 static int isom_read_data( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2224 if( ((isom_metaitem_t
*)parent
)->data
)
2225 return isom_read_unknown_box( file
, box
, parent
, level
);
2226 ADD_BOX( data
, isom_metaitem_t
);
2227 lsmash_bs_t
*bs
= file
->bs
;
2228 data
->value_length
= box
->size
- lsmash_bs_count( bs
) - 8;
2229 data
->reserved
= lsmash_bs_get_be16( bs
);
2230 data
->type_set_identifier
= lsmash_bs_get_byte( bs
);
2231 data
->type_code
= lsmash_bs_get_byte( bs
);
2232 data
->the_locale
= lsmash_bs_get_be32( bs
);
2233 if( data
->value_length
)
2235 data
->value
= lsmash_bs_get_bytes( bs
, data
->value_length
);
2237 return LSMASH_ERR_NAMELESS
;
2239 return isom_read_leaf_box_common_last_process( file
, box
, level
, data
);
2242 static int isom_read_WLOC( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2244 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) || ((isom_udta_t
*)parent
)->WLOC
)
2245 return isom_read_unknown_box( file
, box
, parent
, level
);
2246 ADD_BOX( WLOC
, isom_udta_t
);
2247 lsmash_bs_t
*bs
= file
->bs
;
2248 WLOC
->x
= lsmash_bs_get_be16( bs
);
2249 WLOC
->y
= lsmash_bs_get_be16( bs
);
2250 return isom_read_leaf_box_common_last_process( file
, box
, level
, WLOC
);
2253 static int isom_read_LOOP( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2255 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) || ((isom_udta_t
*)parent
)->LOOP
)
2256 return isom_read_unknown_box( file
, box
, parent
, level
);
2257 ADD_BOX( LOOP
, isom_udta_t
);
2258 lsmash_bs_t
*bs
= file
->bs
;
2259 LOOP
->looping_mode
= lsmash_bs_get_be32( bs
);
2260 return isom_read_leaf_box_common_last_process( file
, box
, level
, LOOP
);
2263 static int isom_read_SelO( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2265 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) || ((isom_udta_t
*)parent
)->SelO
)
2266 return isom_read_unknown_box( file
, box
, parent
, level
);
2267 ADD_BOX( SelO
, isom_udta_t
);
2268 lsmash_bs_t
*bs
= file
->bs
;
2269 SelO
->selection_only
= lsmash_bs_get_byte( bs
);
2270 return isom_read_leaf_box_common_last_process( file
, box
, level
, SelO
);
2273 static int isom_read_AllF( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2275 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) || ((isom_udta_t
*)parent
)->AllF
)
2276 return isom_read_unknown_box( file
, box
, parent
, level
);
2277 ADD_BOX( AllF
, isom_udta_t
);
2278 lsmash_bs_t
*bs
= file
->bs
;
2279 AllF
->play_all_frames
= lsmash_bs_get_byte( bs
);
2280 return isom_read_leaf_box_common_last_process( file
, box
, level
, AllF
);
2283 static int isom_read_cprt( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2285 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
2286 return isom_read_unknown_box( file
, box
, parent
, level
);
2287 ADD_BOX( cprt
, isom_udta_t
);
2288 box
->parent
= parent
;
2289 lsmash_bs_t
*bs
= file
->bs
;
2290 cprt
->language
= lsmash_bs_get_be16( bs
);
2291 cprt
->notice_length
= box
->size
- (ISOM_FULLBOX_COMMON_SIZE
+ 2);
2292 if( cprt
->notice_length
)
2294 cprt
->notice
= lsmash_bs_get_bytes( bs
, cprt
->notice_length
);
2297 cprt
->notice_length
= 0;
2298 return LSMASH_ERR_NAMELESS
;
2301 return isom_read_leaf_box_common_last_process( file
, box
, level
, cprt
);
2304 static int isom_read_mfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2306 if( !lsmash_check_box_type_identical( parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) || ((lsmash_file_t
*)parent
)->mfra
)
2307 return isom_read_unknown_box( file
, box
, parent
, level
);
2308 ADD_BOX( mfra
, lsmash_file_t
);
2309 isom_box_common_copy( mfra
, box
);
2310 int ret
= isom_add_print_func( file
, mfra
, level
);
2313 return isom_read_children( file
, box
, mfra
, level
);
2316 static int isom_read_tfra( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2318 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
) )
2319 return isom_read_unknown_box( file
, box
, parent
, level
);
2320 ADD_BOX( tfra
, isom_mfra_t
);
2321 box
->parent
= parent
;
2322 lsmash_bs_t
*bs
= file
->bs
;
2323 tfra
->track_ID
= lsmash_bs_get_be32( bs
);
2324 uint32_t temp
= lsmash_bs_get_be32( bs
);
2325 tfra
->number_of_entry
= lsmash_bs_get_be32( bs
);
2326 tfra
->reserved
= (temp
>> 6) & 0x3ffffff;
2327 tfra
->length_size_of_traf_num
= (temp
>> 4) & 0x3;
2328 tfra
->length_size_of_trun_num
= (temp
>> 2) & 0x3;
2329 tfra
->length_size_of_sample_num
= temp
& 0x3;
2330 if( tfra
->number_of_entry
)
2332 tfra
->list
= lsmash_create_entry_list();
2334 return LSMASH_ERR_MEMORY_ALLOC
;
2335 uint64_t (*bs_get_funcs
[5])( lsmash_bs_t
* ) =
2337 lsmash_bs_get_byte_to_64
,
2338 lsmash_bs_get_be16_to_64
,
2339 lsmash_bs_get_be24_to_64
,
2340 lsmash_bs_get_be32_to_64
,
2343 uint64_t (*bs_put_time
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2344 uint64_t (*bs_put_moof_offset
) ( lsmash_bs_t
* ) = bs_get_funcs
[ 3 + (box
->version
== 1) ];
2345 uint64_t (*bs_put_traf_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_traf_num
];
2346 uint64_t (*bs_put_trun_number
) ( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_trun_num
];
2347 uint64_t (*bs_put_sample_number
)( lsmash_bs_t
* ) = bs_get_funcs
[ tfra
->length_size_of_sample_num
];
2348 for( uint32_t i
= 0; i
< tfra
->number_of_entry
; i
++ )
2350 isom_tfra_location_time_entry_t
*data
= lsmash_malloc( sizeof(isom_tfra_location_time_entry_t
) );
2352 return LSMASH_ERR_MEMORY_ALLOC
;
2353 if( lsmash_add_entry( tfra
->list
, data
) < 0 )
2355 lsmash_free( data
);
2356 return LSMASH_ERR_MEMORY_ALLOC
;
2358 data
->time
= bs_put_time ( bs
);
2359 data
->moof_offset
= bs_put_moof_offset ( bs
);
2360 data
->traf_number
= bs_put_traf_number ( bs
);
2361 data
->trun_number
= bs_put_trun_number ( bs
);
2362 data
->sample_number
= bs_put_sample_number( bs
);
2365 return isom_read_leaf_box_common_last_process( file
, box
, level
, tfra
);
2368 static int isom_read_mfro( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, int level
)
2370 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MFRA
) || ((isom_mfra_t
*)parent
)->mfro
)
2371 return isom_read_unknown_box( file
, box
, parent
, level
);
2372 ADD_BOX( mfro
, isom_mfra_t
);
2373 lsmash_bs_t
*bs
= file
->bs
;
2374 mfro
->length
= lsmash_bs_get_be32( bs
);
2375 return isom_read_leaf_box_common_last_process( file
, box
, level
, mfro
);
2378 static void isom_read_skip_extra_bytes( lsmash_bs_t
*bs
, uint64_t size
)
2380 if( !bs
->unseekable
)
2382 /* lsmash_bs_read_seek() could fail on offset=INT64_MAX, so use (INT64_MAX >> 1) instead. */
2383 while( size
> (INT64_MAX
>> 1) )
2385 lsmash_bs_read_seek( bs
, INT64_MAX
>> 1, SEEK_CUR
);
2386 if( lsmash_bs_is_end( bs
, 0 ) )
2388 size
-= (INT64_MAX
>> 1);
2390 lsmash_bs_read_seek( bs
, size
, SEEK_CUR
);
2393 lsmash_bs_skip_bytes_64( bs
, size
);
2396 static int isom_read_skip_box_extra_bytes( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
)
2398 lsmash_bs_t
*bs
= file
->bs
;
2399 /* Skip extra bytes of the parent box if any. */
2400 if( parent
->size
< parent_pos
+ ISOM_BASEBOX_COMMON_SIZE
)
2402 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2403 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2404 /* This is not the size of a box but makes sense in isom_read_children(). */
2405 box
->size
= extra_bytes
;
2408 /* Check if the size is valid or not. */
2409 if( lsmash_bs_is_end( bs
, 3 ) == 0 )
2411 uint64_t size
= (uint64_t)lsmash_bs_show_be32( bs
, 0 );
2413 && size
< ISOM_BASEBOX_COMMON_SIZE
)
2415 /* It's not a valid size of any box, therefore, it seems we are still within the box considered as the previous.
2416 * Skip bytes up to the next box of the parent box. */
2417 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2418 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2419 box
->size
= extra_bytes
;
2422 if( size
== 1 && lsmash_bs_is_end( bs
, 15 ) == 0 )
2423 size
= lsmash_bs_show_be64( bs
, 8 ); /* large size */
2424 if( size
== 0 && parent
!= (isom_box_t
*)file
)
2426 /* Check if this box is actually the last box or not. */
2427 uint64_t extra_bytes
= parent
->size
- parent_pos
;
2428 if( !bs
->unseekable
)
2429 size
= bs
->written
- lsmash_bs_get_stream_pos( bs
);
2432 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2433 while( size
<= extra_bytes
)
2435 int ret
= lsmash_bs_read( bs
, 1 );
2436 if( bs
->eof
|| ret
< 0 )
2438 size
= lsmash_bs_get_remaining_buffer_size( bs
);
2441 if( size
!= extra_bytes
)
2443 /* This is not the size of the last box.
2444 * It seems we are still within the box considered as the previous or the parent box.
2445 * Skip bytes up to the next box. */
2446 if( box
->size
> lsmash_bs_count( bs
) )
2448 /* within the previous */
2449 isom_read_skip_extra_bytes( bs
, box
->size
- lsmash_bs_count( bs
) );
2450 box
->size
= 0; /* already added to the size of the parent box */
2454 /* within the parent */
2455 isom_read_skip_extra_bytes( bs
, extra_bytes
);
2456 box
->size
= extra_bytes
;
2465 int isom_read_box( lsmash_file_t
*file
, isom_box_t
*box
, isom_box_t
*parent
, uint64_t parent_pos
, int level
)
2467 assert( parent
&& parent
->root
&& parent
->file
);
2468 if( isom_read_skip_box_extra_bytes( file
, box
, parent
, parent_pos
) != 0 )
2470 memset( box
, 0, sizeof(isom_box_t
) );
2471 box
->root
= parent
->root
;
2472 box
->file
= parent
->file
;
2473 box
->parent
= parent
;
2474 lsmash_bs_t
*bs
= file
->bs
;
2475 int ret
= isom_bs_read_box_common( bs
, box
);
2477 return ret
; /* return if reached EOF */
2479 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
) = NULL
;
2480 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int ) = NULL
;
2481 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
2483 /* OK, this box is a sample entry.
2484 * Here, determine the suitable sample entry reader by media type if possible. */
2485 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
2487 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
2488 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
2489 reader_func
= isom_read_visual_description
;
2490 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
2491 reader_func
= isom_read_audio_description
;
2492 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
2493 reader_func
= isom_read_text_description
;
2495 reader_func
= isom_read_other_description
;
2496 /* Determine either of file formats the sample type is defined in; ISOBMFF or QTFF. */
2497 static struct description_reader_table_tag
2499 lsmash_compact_box_type_t fourcc
;
2500 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2501 } description_reader_table
[160] = { { 0, NULL
} };
2502 if( !description_reader_table
[0].form_box_type_func
)
2504 /* Initialize the table. */
2506 #define ADD_DESCRIPTION_READER_TABLE_ELEMENT( type, form_box_type_func ) \
2507 description_reader_table[i++] = (struct description_reader_table_tag){ type.fourcc, form_box_type_func }
2508 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, lsmash_form_iso_box_type
);
2509 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, lsmash_form_iso_box_type
);
2510 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, lsmash_form_iso_box_type
);
2511 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, lsmash_form_iso_box_type
);
2512 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, lsmash_form_iso_box_type
);
2513 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, lsmash_form_iso_box_type
);
2514 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, lsmash_form_iso_box_type
);
2515 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, lsmash_form_iso_box_type
);
2516 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, lsmash_form_iso_box_type
);
2517 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, lsmash_form_iso_box_type
);
2518 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, lsmash_form_iso_box_type
);
2519 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, lsmash_form_iso_box_type
);
2520 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, lsmash_form_iso_box_type
);
2521 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, lsmash_form_iso_box_type
);
2522 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, lsmash_form_iso_box_type
);
2523 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, lsmash_form_iso_box_type
);
2524 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, lsmash_form_qtff_box_type
);
2525 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, lsmash_form_qtff_box_type
);
2526 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, lsmash_form_qtff_box_type
);
2527 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, lsmash_form_qtff_box_type
);
2528 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, lsmash_form_qtff_box_type
);
2529 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, lsmash_form_qtff_box_type
);
2530 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, lsmash_form_qtff_box_type
);
2531 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, lsmash_form_qtff_box_type
);
2532 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, lsmash_form_qtff_box_type
);
2533 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, lsmash_form_qtff_box_type
);
2534 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, lsmash_form_qtff_box_type
);
2535 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, lsmash_form_qtff_box_type
);
2536 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, lsmash_form_qtff_box_type
);
2537 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, lsmash_form_qtff_box_type
);
2538 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, lsmash_form_qtff_box_type
);
2539 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, lsmash_form_qtff_box_type
);
2540 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, lsmash_form_qtff_box_type
);
2541 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, lsmash_form_qtff_box_type
);
2542 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, lsmash_form_qtff_box_type
);
2543 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, lsmash_form_qtff_box_type
);
2544 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, lsmash_form_qtff_box_type
);
2545 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, lsmash_form_qtff_box_type
);
2546 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, lsmash_form_qtff_box_type
);
2547 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO
, lsmash_form_qtff_box_type
);
2548 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, lsmash_form_qtff_box_type
);
2549 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO, lsmash_form_qtff_box_type );
2550 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, lsmash_form_qtff_box_type
);
2551 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, lsmash_form_qtff_box_type
);
2552 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, lsmash_form_qtff_box_type
);
2553 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, lsmash_form_qtff_box_type
);
2554 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, lsmash_form_qtff_box_type
);
2555 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, lsmash_form_qtff_box_type
);
2556 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, lsmash_form_qtff_box_type
);
2557 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, lsmash_form_qtff_box_type
);
2558 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, lsmash_form_qtff_box_type
);
2559 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, lsmash_form_qtff_box_type
);
2560 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, lsmash_form_qtff_box_type
);
2561 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, lsmash_form_qtff_box_type
);
2562 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, lsmash_form_qtff_box_type
);
2563 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, lsmash_form_qtff_box_type
);
2564 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, lsmash_form_qtff_box_type
);
2565 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, lsmash_form_qtff_box_type
);
2566 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, lsmash_form_qtff_box_type
);
2567 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, lsmash_form_qtff_box_type
);
2568 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, lsmash_form_qtff_box_type
);
2569 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, lsmash_form_qtff_box_type
);
2570 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, lsmash_form_qtff_box_type
);
2571 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, lsmash_form_qtff_box_type
);
2572 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, lsmash_form_qtff_box_type
);
2573 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, lsmash_form_qtff_box_type
);
2574 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, lsmash_form_qtff_box_type
);
2575 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, lsmash_form_qtff_box_type
);
2576 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, lsmash_form_qtff_box_type
);
2577 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, lsmash_form_qtff_box_type
);
2578 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, lsmash_form_qtff_box_type
);
2579 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO
, lsmash_form_qtff_box_type
);
2580 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, lsmash_form_qtff_box_type
);
2581 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, lsmash_form_qtff_box_type
);
2582 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, lsmash_form_qtff_box_type
);
2583 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, lsmash_form_qtff_box_type
);
2584 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, lsmash_form_qtff_box_type
);
2585 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, lsmash_form_qtff_box_type
);
2586 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, lsmash_form_iso_box_type
);
2587 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, lsmash_form_iso_box_type
);
2588 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, lsmash_form_iso_box_type
);
2589 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, lsmash_form_iso_box_type
);
2590 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, lsmash_form_iso_box_type
);
2591 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, lsmash_form_iso_box_type
);
2592 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, lsmash_form_iso_box_type
);
2593 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, lsmash_form_iso_box_type
);
2594 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, lsmash_form_iso_box_type
);
2595 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, lsmash_form_iso_box_type
);
2596 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, lsmash_form_iso_box_type
);
2597 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, lsmash_form_iso_box_type
);
2598 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, lsmash_form_iso_box_type
);
2599 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, lsmash_form_iso_box_type
);
2600 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, lsmash_form_iso_box_type
);
2601 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, lsmash_form_iso_box_type
);
2602 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, lsmash_form_iso_box_type
);
2603 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, lsmash_form_iso_box_type
);
2604 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, lsmash_form_iso_box_type
);
2605 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, lsmash_form_iso_box_type
);
2606 //ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO, lsmash_form_iso_box_type );
2607 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_WMA_AUDIO
, lsmash_form_iso_box_type
);
2608 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, lsmash_form_qtff_box_type
);
2609 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC3_AUDIO
, lsmash_form_qtff_box_type
);
2610 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MAC6_AUDIO
, lsmash_form_qtff_box_type
);
2611 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, lsmash_form_qtff_box_type
);
2612 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDM2_AUDIO
, lsmash_form_qtff_box_type
);
2613 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QDMC_AUDIO
, lsmash_form_qtff_box_type
);
2614 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_QCLP_AUDIO
, lsmash_form_qtff_box_type
);
2615 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_AGSM_AUDIO
, lsmash_form_qtff_box_type
);
2616 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ALAW_AUDIO
, lsmash_form_qtff_box_type
);
2617 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX2_AUDIO
, lsmash_form_qtff_box_type
);
2618 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_CDX4_AUDIO
, lsmash_form_qtff_box_type
);
2619 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCA_AUDIO
, lsmash_form_qtff_box_type
);
2620 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_DVI_AUDIO
, lsmash_form_qtff_box_type
);
2621 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, lsmash_form_qtff_box_type
);
2622 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, lsmash_form_qtff_box_type
);
2623 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IMA4_AUDIO
, lsmash_form_qtff_box_type
);
2624 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, lsmash_form_qtff_box_type
);
2625 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, lsmash_form_qtff_box_type
);
2626 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, lsmash_form_qtff_box_type
);
2627 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, lsmash_form_qtff_box_type
);
2628 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, lsmash_form_qtff_box_type
);
2629 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ULAW_AUDIO
, lsmash_form_qtff_box_type
);
2630 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_VDVA_AUDIO
, lsmash_form_qtff_box_type
);
2631 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_FULLMP3_AUDIO
, lsmash_form_qtff_box_type
);
2632 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_MP3_AUDIO
, lsmash_form_qtff_box_type
);
2633 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM2_AUDIO
, lsmash_form_qtff_box_type
);
2634 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_ADPCM17_AUDIO
, lsmash_form_qtff_box_type
);
2635 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_GSM49_AUDIO
, lsmash_form_qtff_box_type
);
2636 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, lsmash_form_qtff_box_type
);
2637 ADD_DESCRIPTION_READER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, lsmash_form_qtff_box_type
);
2638 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, lsmash_form_iso_box_type
);
2639 ADD_DESCRIPTION_READER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, lsmash_form_iso_box_type
);
2640 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_RAW
, lsmash_form_qtff_box_type
);
2641 ADD_DESCRIPTION_READER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
2642 #undef ADD_DESCRIPTION_READER_TABLE_ELEMENT
2644 for( int i
= 0; description_reader_table
[i
].form_box_type_func
; i
++ )
2645 if( box
->type
.fourcc
== description_reader_table
[i
].fourcc
)
2647 form_box_type_func
= description_reader_table
[i
].form_box_type_func
;
2652 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
2654 form_box_type_func
= lsmash_form_qtff_box_type
;
2655 if( box
->type
.fourcc
== QT_BOX_TYPE_FRMA
.fourcc
) reader_func
= isom_read_frma
;
2656 else if( box
->type
.fourcc
== QT_BOX_TYPE_ENDA
.fourcc
) reader_func
= isom_read_enda
;
2657 else if( box
->type
.fourcc
== QT_BOX_TYPE_ESDS
.fourcc
) reader_func
= isom_read_esds
;
2658 else if( box
->type
.fourcc
== QT_BOX_TYPE_CHAN
.fourcc
) reader_func
= isom_read_chan
;
2659 else if( box
->type
.fourcc
== QT_BOX_TYPE_TERMINATOR
.fourcc
) reader_func
= isom_read_terminator
;
2660 else reader_func
= isom_read_codec_specific
;
2663 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
2665 form_box_type_func
= lsmash_form_iso_box_type
;
2666 reader_func
= isom_read_track_reference_type
;
2669 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_DREF
) )
2671 if( box
->type
.fourcc
== ISOM_BOX_TYPE_URL
.fourcc
2672 || box
->type
.fourcc
== ISOM_BOX_TYPE_URN
.fourcc
)
2673 form_box_type_func
= lsmash_form_iso_box_type
;
2674 else if( box
->type
.fourcc
== QT_BOX_TYPE_ALIS
.fourcc
2675 || box
->type
.fourcc
== QT_BOX_TYPE_RSRC
.fourcc
)
2676 form_box_type_func
= lsmash_form_qtff_box_type
;
2677 reader_func
= isom_read_dref_entry
;
2680 static struct box_reader_table_tag
2682 lsmash_compact_box_type_t fourcc
;
2683 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2684 int (*reader_func
)( lsmash_file_t
*, isom_box_t
*, isom_box_t
*, int );
2685 } box_reader_table
[128] = { { 0, NULL
, NULL
} };
2686 if( !box_reader_table
[0].reader_func
)
2688 /* Initialize the table. */
2690 #define ADD_BOX_READER_TABLE_ELEMENT( type, form_box_type_func, reader_func ) \
2691 box_reader_table[i++] = (struct box_reader_table_tag){ type.fourcc, form_box_type_func, reader_func }
2692 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, lsmash_form_iso_box_type
, isom_read_ftyp
);
2693 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, lsmash_form_iso_box_type
, isom_read_styp
);
2694 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, lsmash_form_iso_box_type
, isom_read_sidx
);
2695 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, lsmash_form_iso_box_type
, isom_read_moov
);
2696 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, lsmash_form_iso_box_type
, isom_read_mvhd
);
2697 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, lsmash_form_iso_box_type
, isom_read_iods
);
2698 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, lsmash_form_qtff_box_type
, isom_read_ctab
);
2699 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, lsmash_form_iso_box_type
, isom_read_esds
);
2700 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, lsmash_form_iso_box_type
, isom_read_trak
);
2701 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, lsmash_form_iso_box_type
, isom_read_tkhd
);
2702 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, lsmash_form_qtff_box_type
, isom_read_tapt
);
2703 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, lsmash_form_qtff_box_type
, isom_read_clef
);
2704 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, lsmash_form_qtff_box_type
, isom_read_prof
);
2705 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, lsmash_form_qtff_box_type
, isom_read_enof
);
2706 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, lsmash_form_iso_box_type
, isom_read_edts
);
2707 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, lsmash_form_iso_box_type
, isom_read_elst
);
2708 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, lsmash_form_iso_box_type
, isom_read_tref
);
2709 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, lsmash_form_iso_box_type
, isom_read_mdia
);
2710 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, lsmash_form_iso_box_type
, isom_read_mdhd
);
2711 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, lsmash_form_iso_box_type
, isom_read_hdlr
);
2712 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, lsmash_form_iso_box_type
, isom_read_minf
);
2713 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, lsmash_form_iso_box_type
, isom_read_vmhd
);
2714 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, lsmash_form_iso_box_type
, isom_read_smhd
);
2715 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, lsmash_form_iso_box_type
, isom_read_hmhd
);
2716 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, lsmash_form_iso_box_type
, isom_read_nmhd
);
2717 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, lsmash_form_qtff_box_type
, isom_read_gmhd
);
2718 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, lsmash_form_qtff_box_type
, isom_read_gmin
);
2719 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, lsmash_form_qtff_box_type
, isom_read_text
);
2720 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, lsmash_form_iso_box_type
, isom_read_dinf
);
2721 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, lsmash_form_iso_box_type
, isom_read_dref
);
2722 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, lsmash_form_iso_box_type
, isom_read_stbl
);
2723 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, lsmash_form_iso_box_type
, isom_read_stsd
);
2724 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, lsmash_form_iso_box_type
, isom_read_btrt
);
2725 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, lsmash_form_iso_box_type
, isom_read_colr
);
2726 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, lsmash_form_iso_box_type
, isom_read_clap
);
2727 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, lsmash_form_iso_box_type
, isom_read_pasp
);
2728 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, lsmash_form_qtff_box_type
, isom_read_glbl
);
2729 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, lsmash_form_qtff_box_type
, isom_read_gama
);
2730 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, lsmash_form_qtff_box_type
, isom_read_fiel
);
2731 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, lsmash_form_qtff_box_type
, isom_read_cspc
);
2732 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, lsmash_form_qtff_box_type
, isom_read_sgbt
);
2733 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, lsmash_form_iso_box_type
, isom_read_stsl
);
2734 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, lsmash_form_qtff_box_type
, isom_read_wave
);
2735 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, lsmash_form_qtff_box_type
, isom_read_chan
);
2736 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SRAT
, lsmash_form_iso_box_type
, isom_read_srat
);
2737 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, lsmash_form_iso_box_type
, isom_read_ftab
);
2738 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, lsmash_form_iso_box_type
, isom_read_stts
);
2739 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, lsmash_form_iso_box_type
, isom_read_ctts
);
2740 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, lsmash_form_iso_box_type
, isom_read_cslg
);
2741 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, lsmash_form_iso_box_type
, isom_read_stss
);
2742 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, lsmash_form_qtff_box_type
, isom_read_stps
);
2743 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, lsmash_form_iso_box_type
, isom_read_sdtp
);
2744 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, lsmash_form_iso_box_type
, isom_read_stsc
);
2745 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, lsmash_form_iso_box_type
, isom_read_stsz
);
2746 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, lsmash_form_iso_box_type
, isom_read_stz2
);
2747 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, lsmash_form_iso_box_type
, isom_read_stco
);
2748 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, lsmash_form_iso_box_type
, isom_read_stco
);
2749 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, lsmash_form_iso_box_type
, isom_read_sgpd
);
2750 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, lsmash_form_iso_box_type
, isom_read_sbgp
);
2751 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, lsmash_form_iso_box_type
, isom_read_udta
);
2752 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, lsmash_form_iso_box_type
, isom_read_chpl
);
2753 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_WLOC
, lsmash_form_qtff_box_type
, isom_read_WLOC
);
2754 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_LOOP
, lsmash_form_qtff_box_type
, isom_read_LOOP
);
2755 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_SELO
, lsmash_form_qtff_box_type
, isom_read_SelO
);
2756 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_ALLF
, lsmash_form_qtff_box_type
, isom_read_AllF
);
2757 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, lsmash_form_iso_box_type
, isom_read_mvex
);
2758 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, lsmash_form_iso_box_type
, isom_read_mehd
);
2759 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, lsmash_form_iso_box_type
, isom_read_trex
);
2760 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, lsmash_form_iso_box_type
, isom_read_moof
);
2761 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, lsmash_form_iso_box_type
, isom_read_mfhd
);
2762 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, lsmash_form_iso_box_type
, isom_read_traf
);
2763 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, lsmash_form_iso_box_type
, isom_read_tfhd
);
2764 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, lsmash_form_iso_box_type
, isom_read_tfdt
);
2765 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, lsmash_form_iso_box_type
, isom_read_trun
);
2766 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, lsmash_form_iso_box_type
, isom_read_free
);
2767 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, lsmash_form_iso_box_type
, isom_read_free
);
2768 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, lsmash_form_iso_box_type
, isom_read_mdat
);
2769 ADD_BOX_READER_TABLE_ELEMENT( QT_BOX_TYPE_KEYS
, lsmash_form_qtff_box_type
, isom_read_keys
);
2770 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, lsmash_form_iso_box_type
, isom_read_mfra
);
2771 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, lsmash_form_iso_box_type
, isom_read_tfra
);
2772 ADD_BOX_READER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, lsmash_form_iso_box_type
, isom_read_mfro
);
2773 ADD_BOX_READER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
, NULL
);
2774 #undef ADD_BOX_READER_TABLE_ELEMENT
2776 for( int i
= 0; box_reader_table
[i
].reader_func
; i
++ )
2777 if( box
->type
.fourcc
== box_reader_table
[i
].fourcc
)
2779 form_box_type_func
= box_reader_table
[i
].form_box_type_func
;
2780 reader_func
= box_reader_table
[i
].reader_func
;
2783 if( box
->type
.fourcc
== ISOM_BOX_TYPE_META
.fourcc
)
2785 if( lsmash_bs_is_end ( bs
, 3 ) == 0
2786 && lsmash_bs_show_be32( bs
, 0 ) == 0 )
2787 form_box_type_func
= lsmash_form_iso_box_type
;
2789 form_box_type_func
= lsmash_form_qtff_box_type
;
2790 reader_func
= isom_read_meta
;
2793 if( box
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2795 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
) )
2796 form_box_type_func
= lsmash_form_iso_box_type
;
2797 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
2798 form_box_type_func
= lsmash_form_qtff_box_type
;
2799 if( form_box_type_func
)
2801 reader_func
= isom_read_ilst
;
2805 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
) )
2806 form_box_type_func
= lsmash_form_iso_box_type
;
2807 else if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
2808 form_box_type_func
= lsmash_form_qtff_box_type
;
2809 if( form_box_type_func
)
2811 reader_func
= isom_read_metaitem
;
2814 if( parent
->parent
&& parent
->parent
->type
.fourcc
== ISOM_BOX_TYPE_ILST
.fourcc
)
2816 if( box
->type
.fourcc
== ISOM_BOX_TYPE_MEAN
.fourcc
)
2817 reader_func
= isom_read_mean
;
2818 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_NAME
.fourcc
)
2819 reader_func
= isom_read_name
;
2820 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_DATA
.fourcc
)
2821 reader_func
= isom_read_data
;
2824 form_box_type_func
= lsmash_form_iso_box_type
;
2828 else if( box
->type
.fourcc
== ISOM_BOX_TYPE_CPRT
.fourcc
)
2830 /* Avoid confusing udta.cprt with ilst.cprt. */
2831 form_box_type_func
= lsmash_form_iso_box_type
;
2832 reader_func
= isom_read_cprt
;
2835 if( parent
->parent
&& lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_STSD
) )
2837 static struct codec_specific_marker_table_tag
2839 lsmash_compact_box_type_t fourcc
;
2840 lsmash_box_type_t (*form_box_type_func
)( lsmash_compact_box_type_t
);
2841 } codec_specific_marker_table
[16] = { { 0, NULL
} };
2842 if( !codec_specific_marker_table
[0].form_box_type_func
)
2844 /* Initialize the table. */
2846 #define ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( type, form_box_type_func ) \
2847 codec_specific_marker_table[i++] = (struct codec_specific_marker_table_tag){ type.fourcc, form_box_type_func }
2848 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_ALAC
, lsmash_form_iso_box_type
);
2849 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_AVCC
, lsmash_form_iso_box_type
);
2850 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAC3
, lsmash_form_iso_box_type
);
2851 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DAMR
, lsmash_form_iso_box_type
);
2852 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DDTS
, lsmash_form_iso_box_type
);
2853 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DEC3
, lsmash_form_iso_box_type
);
2854 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_DVC1
, lsmash_form_iso_box_type
);
2855 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_HVCC
, lsmash_form_iso_box_type
);
2856 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( ISOM_BOX_TYPE_WFEX
, lsmash_form_iso_box_type
);
2857 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, lsmash_form_qtff_box_type
);
2858 ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
);
2859 #undef ADD_CODEC_SPECIFIC_MARKER_TABLE_ELEMENT
2861 for( int i
= 0; codec_specific_marker_table
[i
].form_box_type_func
; i
++ )
2862 if( box
->type
.fourcc
== codec_specific_marker_table
[i
].fourcc
)
2864 form_box_type_func
= codec_specific_marker_table
[i
].form_box_type_func
;
2867 reader_func
= isom_read_codec_specific
;
2870 if( form_box_type_func
)
2871 box
->type
= form_box_type_func( box
->type
.fourcc
);
2872 if( (ret
= isom_read_fullbox_common_extension( bs
, box
)) < 0 )
2875 ? reader_func( file
, box
, parent
, level
)
2876 : isom_read_unknown_box( file
, box
, parent
, level
);
2879 int isom_read_file( lsmash_file_t
*file
)
2881 lsmash_bs_t
*bs
= file
->bs
;
2883 return LSMASH_ERR_NAMELESS
;
2884 /* Reset the counter so that we can use it to get position within the box. */
2885 lsmash_bs_reset_counter( bs
);
2886 if( file
->flags
& LSMASH_FILE_MODE_DUMP
)
2888 file
->print
= lsmash_create_entry_list();
2890 return LSMASH_ERR_MEMORY_ALLOC
;
2892 file
->size
= UINT64_MAX
;
2894 int ret
= isom_read_children( file
, &box
, file
, 0 );
2895 file
->size
= box
.size
;
2896 lsmash_bs_empty( bs
);
2897 bs
->error
= 0; /* Clear error flag. */
2900 return isom_check_compatibility( file
);