1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2014 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
31 #ifdef LSMASH_DEMUXER_ENABLED
36 #include "codecs/mp4a.h"
37 #include "codecs/mp4sys.h"
39 #include "importer/importer.h"
41 static const lsmash_class_t lsmash_box_class
=
46 const lsmash_box_type_t static_lsmash_box_type_unspecified
= LSMASH_BOX_TYPE_INITIALIZER
;
48 void isom_init_box_common_orig
52 lsmash_box_type_t box_type
,
54 isom_extension_destructor_t destructor
57 isom_box_t
*box
= (isom_box_t
*)_box
;
58 isom_box_t
*parent
= (isom_box_t
*)_parent
;
59 assert( box
&& parent
&& parent
->root
);
60 box
->class = &lsmash_box_class
;
61 box
->root
= parent
->root
;
62 box
->file
= parent
->file
;
64 box
->precedence
= precedence
;
65 box
->destruct
= destructor
;
68 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) && isom_is_fullbox( box
) )
73 isom_set_box_writer( box
);
76 static void isom_reorder_tail_box( isom_box_t
*parent
)
78 /* Reorder the appended box by 'precedence'. */
79 lsmash_entry_t
*x
= parent
->extensions
.tail
;
80 assert( x
&& x
->data
);
81 uint64_t precedence
= ((isom_box_t
*)x
->data
)->precedence
;
82 for( lsmash_entry_t
*y
= x
->prev
; y
; y
= y
->prev
)
84 isom_box_t
*box
= (isom_box_t
*)y
->data
;
85 if( !box
|| precedence
> box
->precedence
)
87 /* Exchange the entity data of adjacent two entries. */
97 int isom_add_box_to_extension_list( void *parent_box
, void *child_box
)
99 assert( parent_box
&& child_box
);
100 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
101 isom_box_t
*child
= (isom_box_t
*)child_box
;
102 /* Append at the end of the list. */
103 if( lsmash_add_entry( &parent
->extensions
, child
) < 0 )
104 return LSMASH_ERR_MEMORY_ALLOC
;
105 /* Don't reorder the appended box when the file is opened for reading. */
106 if( !parent
->file
|| (parent
->file
->flags
& LSMASH_FILE_MODE_READ
) || parent
->file
->fake_file_mode
)
108 isom_reorder_tail_box( parent
);
112 void isom_bs_put_basebox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
114 if( box
->size
> UINT32_MAX
)
116 lsmash_bs_put_be32( bs
, 1 );
117 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
118 lsmash_bs_put_be64( bs
, box
->size
); /* largesize */
122 lsmash_bs_put_be32( bs
, (uint32_t)box
->size
);
123 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
125 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
127 lsmash_bs_put_be32( bs
, box
->type
.user
.fourcc
);
128 lsmash_bs_put_bytes( bs
, 12, box
->type
.user
.id
);
132 void isom_bs_put_fullbox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
134 isom_bs_put_basebox_common( bs
, box
);
135 lsmash_bs_put_byte( bs
, box
->version
);
136 lsmash_bs_put_be24( bs
, box
->flags
);
139 void isom_bs_put_box_common( lsmash_bs_t
*bs
, void *box
)
146 isom_box_t
*parent
= ((isom_box_t
*)box
)->parent
;
147 if( parent
&& lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
149 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
152 if( isom_is_fullbox( box
) )
153 isom_bs_put_fullbox_common( bs
, (isom_box_t
*)box
);
155 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
158 /* Return 1 if the box is fullbox, Otherwise return 0. */
159 int isom_is_fullbox( void *box
)
161 isom_box_t
*current
= (isom_box_t
*)box
;
162 lsmash_box_type_t type
= current
->type
;
163 static lsmash_box_type_t fullbox_type_table
[50] = { LSMASH_BOX_TYPE_INITIALIZER
};
164 if( !lsmash_check_box_type_specified( &fullbox_type_table
[0] ) )
166 /* Initialize the table. */
168 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SIDX
;
169 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MVHD
;
170 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TKHD
;
171 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_IODS
;
172 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ESDS
;
173 fullbox_type_table
[i
++] = QT_BOX_TYPE_ESDS
;
174 fullbox_type_table
[i
++] = QT_BOX_TYPE_CLEF
;
175 fullbox_type_table
[i
++] = QT_BOX_TYPE_PROF
;
176 fullbox_type_table
[i
++] = QT_BOX_TYPE_ENOF
;
177 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ELST
;
178 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MDHD
;
179 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HDLR
;
180 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_VMHD
;
181 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SMHD
;
182 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HMHD
;
183 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NMHD
;
184 fullbox_type_table
[i
++] = QT_BOX_TYPE_GMIN
;
185 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_DREF
;
186 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSD
;
187 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSL
;
188 fullbox_type_table
[i
++] = QT_BOX_TYPE_CHAN
;
189 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SRAT
;
190 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STTS
;
191 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CTTS
;
192 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CSLG
;
193 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSS
;
194 fullbox_type_table
[i
++] = QT_BOX_TYPE_STPS
;
195 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SDTP
;
196 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSC
;
197 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSZ
;
198 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STCO
;
199 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CO64
;
200 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SGPD
;
201 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SBGP
;
202 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CHPL
;
203 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_META
;
204 fullbox_type_table
[i
++] = QT_BOX_TYPE_KEYS
;
205 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEAN
;
206 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NAME
;
207 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEHD
;
208 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TREX
;
209 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFHD
;
210 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFHD
;
211 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFDT
;
212 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TRUN
;
213 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFRA
;
214 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFRO
;
215 fullbox_type_table
[i
] = LSMASH_BOX_TYPE_UNSPECIFIED
;
217 for( int i
= 0; lsmash_check_box_type_specified( &fullbox_type_table
[i
] ); i
++ )
218 if( lsmash_check_box_type_identical( type
, fullbox_type_table
[i
] ) )
220 if( current
->parent
)
222 if( lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_DREF
)
223 || (lsmash_check_box_type_identical( type
, ISOM_BOX_TYPE_CPRT
)
224 && lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_UDTA
)) )
230 /* Return 1 if the sample type is LPCM audio, Otherwise return 0. */
231 int isom_is_lpcm_audio( void *box
)
233 isom_box_t
*current
= (isom_box_t
*)box
;
234 lsmash_box_type_t type
= current
->type
;
235 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
236 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
237 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
238 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
239 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
240 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
241 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
242 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
243 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
244 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
245 || (lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
) && (current
->manager
& LSMASH_AUDIO_DESCRIPTION
));
248 int isom_is_qt_audio( lsmash_codec_type_t type
)
250 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
251 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC3_AUDIO
)
252 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC6_AUDIO
)
253 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
254 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDM2_AUDIO
)
255 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDMC_AUDIO
)
256 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QCLP_AUDIO
)
257 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AC_3_AUDIO
)
258 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AGSM_AUDIO
)
259 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAC_AUDIO
)
260 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAW_AUDIO
)
261 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX2_AUDIO
)
262 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX4_AUDIO
)
263 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVCA_AUDIO
)
264 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVI_AUDIO
)
265 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
266 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
267 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IMA4_AUDIO
)
268 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
269 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
270 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
271 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP4A_AUDIO
)
272 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
)
273 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
274 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
275 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ULAW_AUDIO
)
276 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_VDVA_AUDIO
)
277 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
278 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
)
279 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
280 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
281 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
282 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
);
285 /* Return 1 if the sample type is uncompressed Y'CbCr video, Otherwise return 0. */
286 int isom_is_uncompressed_ycbcr( lsmash_codec_type_t type
)
288 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_2VUY_VIDEO
)
289 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V210_VIDEO
)
290 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V216_VIDEO
)
291 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V308_VIDEO
)
292 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V408_VIDEO
)
293 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V410_VIDEO
)
294 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_YUV2_VIDEO
);
297 int isom_is_waveform_audio( lsmash_box_type_t type
)
299 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
300 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
301 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
302 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
303 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
);
306 size_t isom_skip_box_common( uint8_t **p_data
)
308 uint8_t *orig
= *p_data
;
309 uint8_t *data
= *p_data
;
310 uint64_t size
= LSMASH_GET_BE32( data
);
311 data
+= ISOM_BASEBOX_COMMON_SIZE
;
314 size
= LSMASH_GET_BE64( data
);
321 static void isom_destruct_extension_binary( void *ext
)
325 isom_box_t
*box
= (isom_box_t
*)ext
;
326 lsmash_free( box
->binary
);
329 int isom_add_extension_binary
332 lsmash_box_type_t box_type
,
338 if( !parent_box
|| !box_data
|| box_size
< ISOM_BASEBOX_COMMON_SIZE
339 || !lsmash_check_box_type_specified( &box_type
) )
340 return LSMASH_ERR_FUNCTION_PARAM
;
341 isom_box_t
*ext
= lsmash_malloc_zero( sizeof(isom_box_t
) );
343 return LSMASH_ERR_MEMORY_ALLOC
;
344 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
345 ext
->class = &lsmash_box_class
;
346 ext
->root
= parent
->root
;
347 ext
->file
= parent
->file
;
348 ext
->parent
= parent
;
349 ext
->manager
= LSMASH_BINARY_CODED_BOX
;
350 ext
->precedence
= precedence
;
351 ext
->size
= box_size
;
352 ext
->type
= box_type
;
353 ext
->binary
= box_data
;
354 ext
->destruct
= isom_destruct_extension_binary
;
355 if( isom_add_box_to_extension_list( parent
, ext
) < 0 )
358 return LSMASH_ERR_MEMORY_ALLOC
;
360 isom_set_box_writer( ext
);
364 static void isom_remove_extension_box( isom_box_t
*ext
)
369 ext
->destruct( ext
);
370 isom_remove_all_extension_boxes( &ext
->extensions
);
374 void isom_remove_all_extension_boxes( lsmash_entry_list_t
*extensions
)
376 lsmash_remove_entries( extensions
, isom_remove_extension_box
);
379 isom_box_t
*isom_get_extension_box( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
381 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
383 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
386 if( lsmash_check_box_type_identical( ext
->type
, box_type
) )
392 void *isom_get_extension_box_format( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
394 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
396 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
397 if( !ext
|| (ext
->manager
& LSMASH_BINARY_CODED_BOX
) || !lsmash_check_box_type_identical( ext
->type
, box_type
) )
404 lsmash_entry_t
*isom_get_entry_of_box
406 lsmash_box_t
*parent
,
407 const lsmash_box_path_t box_path
[]
412 lsmash_entry_t
*entry
= NULL
;
413 const lsmash_box_path_t
*path
= &box_path
[0];
414 while( lsmash_check_box_type_specified( &path
->type
) )
416 entry
= parent
->extensions
.head
;
421 uint32_t number
= path
->number
? path
->number
: 1;
424 isom_box_t
*box
= entry
->data
;
425 if( box
&& lsmash_check_box_type_identical( path
->type
, box
->type
) )
429 /* Found a box. Move to a child box. */
444 /* box destructors */
445 #define REMOVE_BOX( box_name, parent_type ) \
446 isom_remove_predefined_box( box_name, offsetof( parent_type, box_name ) )
448 #define REMOVE_BOX_IN_LIST( box_name, parent_type ) \
449 isom_remove_box_in_predefined_list( box_name, offsetof( parent_type, box_name##_list ) )
451 #define REMOVE_LIST_BOX_TEMPLATE( REMOVER, box_name, parent_type, eliminator ) \
454 lsmash_remove_list( box_name->list, eliminator ); \
455 REMOVER( box_name, parent_type ); \
458 #define REMOVE_LIST_BOX( box_name, ... ) CALL_FUNC_DEFAULT_ARGS( REMOVE_LIST_BOX, box_name, __VA_ARGS__ )
459 #define REMOVE_LIST_BOX_3( box_name, parent_type, eliminator ) \
460 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX, box_name, parent_type, eliminator )
461 #define REMOVE_LIST_BOX_2( box_name, parent_type ) \
462 REMOVE_LIST_BOX_3( box_name, parent_type, NULL )
464 #define REMOVE_LIST_BOX_IN_LIST( box_name, parent_type ) \
465 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX_IN_LIST, box_name, parent_type, NULL )
467 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVER, box_name, ... ) \
468 static void isom_remove_##box_name( isom_##box_name##_t *box_name ) \
472 REMOVER( box_name, __VA_ARGS__ ); \
475 #define DEFINE_SIMPLE_BOX_REMOVER( func_name, box_name, ... ) \
476 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX, box_name, __VA_ARGS__ )
478 #define DEFINE_SIMPLE_LIST_BOX_REMOVER( func_name, box_name, ... ) \
479 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX, box_name, __VA_ARGS__ )
481 #define DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( func_name, box_name, ... ) \
482 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX_IN_LIST, box_name, __VA_ARGS__ )
484 #define DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( func_name, box_name, ... ) \
485 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX_IN_LIST, box_name, __VA_ARGS__ )
487 static void isom_remove_predefined_box( void *opaque_box
, size_t offset_of_box
)
489 assert( opaque_box
);
490 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
493 isom_box_t
**p
= (isom_box_t
**)(((int8_t *)box
->parent
) + offset_of_box
);
499 /* We always free boxes through the extension list of the parent box.
500 * Therefore, don't free boxes through any list other than the extension list. */
501 static void isom_remove_box_in_predefined_list( void *opaque_box
, size_t offset_of_list
)
503 assert( opaque_box
);
504 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
507 lsmash_entry_list_t
*list
= (lsmash_entry_list_t
*)(((int8_t *)box
->parent
) + offset_of_list
);
509 for( lsmash_entry_t
*entry
= list
->head
; entry
; entry
= entry
->next
)
510 if( box
== entry
->data
)
512 /* We don't free this box here.
513 * Because of freeing an entry of the list here, don't pass the list to free this box.
516 lsmash_remove_entry_direct( list
, entry
, NULL
);
522 /* Remove a box by the pointer containing its address.
523 * In addition, remove from the extension list of the parent box if possible.
524 * Don't call this function within a function freeing one or more entries of any extension list because of double free.
525 * Basically, don't use this function as a callback function. */
526 void isom_remove_box_by_itself( void *opaque_box
)
530 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
533 isom_box_t
*parent
= box
->parent
;
534 for( lsmash_entry_t
*entry
= parent
->extensions
.head
; entry
; entry
= entry
->next
)
535 if( box
== entry
->data
)
537 /* Free the corresponding entry here, therefore don't call this function as a callback function
538 * if a function frees the same entry later and calls this function. */
539 lsmash_remove_entry_direct( &parent
->extensions
, entry
, isom_remove_extension_box
);
543 isom_remove_extension_box( box
);
546 void isom_remove_unknown_box( isom_unknown_box_t
*unknown_box
)
550 lsmash_free( unknown_box
->unknown_field
);
553 static void isom_remove_file( lsmash_file_t
*file
)
557 #ifdef LSMASH_DEMUXER_ENABLED
558 isom_remove_print_funcs( file
);
559 isom_remove_timelines( file
);
561 lsmash_free( file
->compatible_brands
);
562 lsmash_bs_cleanup( file
->bs
);
563 lsmash_importer_destroy( file
->importer
);
566 lsmash_remove_list( file
->fragment
->pool
, isom_remove_sample_pool
);
567 lsmash_free( file
->fragment
);
569 REMOVE_BOX_IN_LIST( file
, lsmash_root_t
);
572 static void isom_remove_ftyp( isom_ftyp_t
*ftyp
)
576 lsmash_free( ftyp
->compatible_brands
);
577 REMOVE_BOX( ftyp
, lsmash_file_t
);
580 static void isom_remove_iods( isom_iods_t
*iods
)
584 mp4sys_remove_descriptor( iods
->OD
);
585 REMOVE_BOX( iods
, isom_moov_t
);
588 static void isom_remove_trak( isom_trak_t
*trak
)
594 isom_remove_sample_pool( trak
->cache
->chunk
.pool
);
595 lsmash_remove_list( trak
->cache
->roll
.pool
, NULL
);
596 lsmash_free( trak
->cache
->rap
);
597 lsmash_free( trak
->cache
->fragment
);
598 lsmash_free( trak
->cache
);
600 REMOVE_BOX_IN_LIST( trak
, isom_moov_t
);
603 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tkhd
, tkhd
, isom_trak_t
)
604 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_clef
, clef
, isom_tapt_t
)
605 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_prof
, prof
, isom_tapt_t
)
606 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enof
, enof
, isom_tapt_t
)
607 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tapt
, tapt
, isom_trak_t
)
608 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_edts
, edts
, isom_trak_t
)
609 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tref
, tref
, isom_trak_t
)
610 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_elst
, elst
, isom_edts_t
)
612 static void isom_remove_track_reference_type( isom_tref_type_t
*ref
)
616 lsmash_free( ref
->track_ID
);
617 isom_remove_box_in_predefined_list( ref
, offsetof( isom_tref_t
, ref_list
) );
620 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdhd
, mdhd
, isom_mdia_t
)
621 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_vmhd
, vmhd
, isom_minf_t
)
622 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_smhd
, smhd
, isom_minf_t
)
623 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_hmhd
, hmhd
, isom_minf_t
)
624 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_nmhd
, nmhd
, isom_minf_t
)
625 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmhd
, gmhd
, isom_minf_t
)
626 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmin
, gmin
, isom_gmhd_t
)
627 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_text
, text
, isom_gmhd_t
)
629 static void isom_remove_hdlr( isom_hdlr_t
*hdlr
)
633 lsmash_free( hdlr
->componentName
);
636 if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MDIA
) )
637 REMOVE_BOX( hdlr
, isom_mdia_t
);
638 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_META
)
639 || lsmash_check_box_type_identical( hdlr
->parent
->type
, QT_BOX_TYPE_META
) )
640 REMOVE_BOX( hdlr
, isom_meta_t
);
641 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MINF
) )
642 REMOVE_BOX( hdlr
, isom_minf_t
);
649 static void isom_remove_glbl( isom_glbl_t
*glbl
)
653 lsmash_free( glbl
->header_data
);
656 static void isom_remove_esds( isom_esds_t
*esds
)
660 mp4sys_remove_descriptor( esds
->ES
);
663 static void isom_remove_font_record( isom_font_record_t
*font_record
)
667 lsmash_free( font_record
->font_name
);
668 lsmash_free( font_record
);
670 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ftab
, ftab
, isom_tx3g_entry_t
, isom_remove_font_record
)
672 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_frma
, frma
, isom_wave_t
)
673 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enda
, enda
, isom_wave_t
)
674 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mp4a
, mp4a
, isom_wave_t
)
675 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_terminator
, terminator
, isom_wave_t
)
677 static void isom_remove_chan( isom_chan_t
*chan
)
681 lsmash_free( chan
->channelDescriptions
);
684 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stsd
, stsd
, isom_stbl_t
)
686 static void isom_remove_visual_description( isom_sample_entry_t
*description
)
688 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)description
;
689 lsmash_free( visual
->color_table
.array
);
690 isom_remove_box_in_predefined_list( visual
, offsetof( isom_stsd_t
, list
) );
693 static void isom_remove_audio_description( isom_sample_entry_t
*description
)
695 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
698 static void isom_remove_hint_description( isom_sample_entry_t
*description
)
700 isom_hint_entry_t
*hint
= (isom_hint_entry_t
*)description
;
701 lsmash_free( hint
->data
);
702 isom_remove_box_in_predefined_list( hint
, offsetof( isom_stsd_t
, list
) );
705 static void isom_remove_metadata_description( isom_sample_entry_t
*description
)
707 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
710 static void isom_remove_tx3g_description( isom_sample_entry_t
*description
)
712 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
715 static void isom_remove_qt_text_description( isom_sample_entry_t
*description
)
717 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)description
;
718 lsmash_free( text
->font_name
);
719 isom_remove_box_in_predefined_list( text
, offsetof( isom_stsd_t
, list
) );
722 static void isom_remove_mp4s_description( isom_sample_entry_t
*description
)
724 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
727 void isom_remove_sample_description( isom_sample_entry_t
*sample
)
731 lsmash_codec_type_t sample_type
= sample
->type
;
732 if( lsmash_check_box_type_identical( sample_type
, LSMASH_CODEC_TYPE_RAW
) )
734 if( sample
->manager
& LSMASH_VIDEO_DESCRIPTION
)
736 isom_remove_visual_description( sample
);
739 else if( sample
->manager
& LSMASH_AUDIO_DESCRIPTION
)
741 isom_remove_audio_description( sample
);
745 static struct description_remover_table_tag
747 lsmash_codec_type_t type
;
748 void (*func
)( isom_sample_entry_t
* );
749 } description_remover_table
[160] = { { LSMASH_CODEC_TYPE_INITIALIZER
, NULL
} };
750 if( !description_remover_table
[0].func
)
752 /* Initialize the table. */
754 #define ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( type, func ) \
755 description_remover_table[i++] = (struct description_remover_table_tag){ type, func }
756 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, isom_remove_visual_description
);
757 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, isom_remove_visual_description
);
758 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, isom_remove_visual_description
);
759 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, isom_remove_visual_description
);
760 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, isom_remove_visual_description
);
761 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, isom_remove_visual_description
);
762 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, isom_remove_visual_description
);
763 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, isom_remove_visual_description
);
764 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, isom_remove_visual_description
);
765 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, isom_remove_visual_description
);
766 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, isom_remove_visual_description
);
767 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
768 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, isom_remove_visual_description
);
769 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, isom_remove_visual_description
);
770 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, isom_remove_visual_description
);
771 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, isom_remove_visual_description
);
772 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, isom_remove_visual_description
);
773 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, isom_remove_visual_description
);
774 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, isom_remove_visual_description
);
775 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, isom_remove_visual_description
);
776 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, isom_remove_visual_description
);
777 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, isom_remove_visual_description
);
778 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, isom_remove_visual_description
);
779 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, isom_remove_visual_description
);
780 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, isom_remove_visual_description
);
781 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, isom_remove_visual_description
);
782 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, isom_remove_visual_description
);
783 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, isom_remove_visual_description
);
784 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, isom_remove_visual_description
);
785 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, isom_remove_visual_description
);
786 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, isom_remove_visual_description
);
787 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, isom_remove_visual_description
);
788 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, isom_remove_visual_description
);
789 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, isom_remove_visual_description
);
790 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, isom_remove_visual_description
);
791 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, isom_remove_visual_description
);
792 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, isom_remove_visual_description
);
793 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, isom_remove_visual_description
);
794 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, isom_remove_visual_description
);
795 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, isom_remove_visual_description
);
796 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
797 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, isom_remove_visual_description
);
798 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, isom_remove_visual_description
);
799 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, isom_remove_visual_description
);
800 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, isom_remove_visual_description
);
801 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, isom_remove_visual_description
);
802 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, isom_remove_visual_description
);
803 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, isom_remove_visual_description
);
804 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, isom_remove_visual_description
);
805 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, isom_remove_visual_description
);
806 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, isom_remove_visual_description
);
807 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, isom_remove_visual_description
);
808 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, isom_remove_visual_description
);
809 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, isom_remove_visual_description
);
810 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, isom_remove_visual_description
);
811 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, isom_remove_visual_description
);
812 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, isom_remove_visual_description
);
813 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, isom_remove_visual_description
);
814 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, isom_remove_visual_description
);
815 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, isom_remove_visual_description
);
816 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, isom_remove_visual_description
);
817 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, isom_remove_visual_description
);
818 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, isom_remove_visual_description
);
819 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, isom_remove_visual_description
);
820 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, isom_remove_visual_description
);
821 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, isom_remove_visual_description
);
822 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, isom_remove_visual_description
);
823 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, isom_remove_visual_description
);
824 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, isom_remove_visual_description
);
825 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, isom_remove_visual_description
);
826 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, isom_remove_visual_description
);
827 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, isom_remove_visual_description
);
828 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, isom_remove_visual_description
);
829 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, isom_remove_visual_description
);
830 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, isom_remove_visual_description
);
831 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, isom_remove_visual_description
);
832 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
833 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, isom_remove_audio_description
);
834 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, isom_remove_audio_description
);
835 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, isom_remove_audio_description
);
836 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, isom_remove_audio_description
);
837 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, isom_remove_audio_description
);
838 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, isom_remove_audio_description
);
839 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, isom_remove_audio_description
);
840 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, isom_remove_audio_description
);
841 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, isom_remove_audio_description
);
842 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, isom_remove_audio_description
);
843 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, isom_remove_audio_description
);
844 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, isom_remove_audio_description
);
845 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, isom_remove_audio_description
);
846 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
847 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, isom_remove_audio_description
);
848 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, isom_remove_audio_description
);
849 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, isom_remove_audio_description
);
850 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, isom_remove_audio_description
);
851 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, isom_remove_audio_description
);
852 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, isom_remove_audio_description
);
853 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, isom_remove_audio_description
);
854 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, isom_remove_audio_description
);
855 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, isom_remove_audio_description
);
856 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, isom_remove_audio_description
);
857 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, isom_remove_audio_description
);
858 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, isom_remove_audio_description
);
859 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, isom_remove_audio_description
);
860 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, isom_remove_audio_description
);
861 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, isom_remove_audio_description
);
862 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
863 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_FDP_HINT
, isom_remove_hint_description
);
864 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M2TS_HINT
, isom_remove_hint_description
);
865 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PM2T_HINT
, isom_remove_hint_description
);
866 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PRTP_HINT
, isom_remove_hint_description
);
867 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RM2T_HINT
, isom_remove_hint_description
);
868 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RRTP_HINT
, isom_remove_hint_description
);
869 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RSRP_HINT
, isom_remove_hint_description
);
870 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RTP_HINT
, isom_remove_hint_description
);
871 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SM2T_HINT
, isom_remove_hint_description
);
872 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SRTP_HINT
, isom_remove_hint_description
);
873 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_IXSE_META
, isom_remove_metadata_description
);
874 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METT_META
, isom_remove_metadata_description
);
875 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METX_META
, isom_remove_metadata_description
);
876 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLIX_META
, isom_remove_metadata_description
);
877 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_OKSD_META
, isom_remove_metadata_description
);
878 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVCM_META
, isom_remove_metadata_description
);
879 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TEXT_META
, isom_remove_metadata_description
);
880 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_URIM_META
, isom_remove_metadata_description
);
881 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_XML_META
, isom_remove_metadata_description
);
882 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, isom_remove_tx3g_description
);
883 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, isom_remove_qt_text_description
);
884 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, isom_remove_mp4s_description
);
885 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
887 for( int i
= 0; description_remover_table
[i
].func
; i
++ )
888 if( lsmash_check_codec_type_identical( sample_type
, description_remover_table
[i
].type
) )
890 description_remover_table
[i
].func( sample
);
895 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stts
, stts
, isom_stbl_t
)
896 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ctts
, ctts
, isom_stbl_t
)
897 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_cslg
, cslg
, isom_stbl_t
)
898 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsc
, stsc
, isom_stbl_t
)
899 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsz
, stsz
, isom_stbl_t
)
900 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stss
, stss
, isom_stbl_t
)
901 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stps
, stps
, isom_stbl_t
)
902 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stco
, stco
, isom_stbl_t
)
904 static void isom_remove_sdtp( isom_sdtp_t
*sdtp
)
908 lsmash_remove_list( sdtp
->list
, NULL
);
911 if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
912 REMOVE_BOX( sdtp
, isom_stbl_t
);
913 else if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
914 REMOVE_BOX( sdtp
, isom_traf_t
);
921 static void isom_remove_sgpd( isom_sgpd_t
*sgpd
)
925 lsmash_remove_list( sgpd
->list
, NULL
);
928 if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
929 REMOVE_BOX_IN_LIST( sgpd
, isom_stbl_t
);
930 else if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
931 REMOVE_BOX_IN_LIST( sgpd
, isom_traf_t
);
938 static void isom_remove_sbgp( isom_sbgp_t
*sbgp
)
942 lsmash_remove_list( sbgp
->list
, NULL
);
945 if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
946 REMOVE_BOX_IN_LIST( sbgp
, isom_stbl_t
);
947 else if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
948 REMOVE_BOX_IN_LIST( sbgp
, isom_traf_t
);
955 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stbl
, stbl
, isom_minf_t
)
957 static void isom_remove_dref_entry( isom_dref_entry_t
*data_entry
)
961 lsmash_free( data_entry
->name
);
962 lsmash_free( data_entry
->location
);
963 isom_remove_box_in_predefined_list( data_entry
, offsetof( isom_dref_t
, list
) );
966 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dref
, dref
, isom_dinf_t
)
967 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dinf
, dinf
, isom_minf_t
)
968 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_minf
, minf
, isom_mdia_t
)
969 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdia
, mdia
, isom_trak_t
)
971 static void isom_remove_chpl_entry( isom_chpl_entry_t
*data
)
975 lsmash_free( data
->chapter_name
);
978 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_chpl
, chpl
, isom_udta_t
, isom_remove_chpl_entry
)
980 static void isom_remove_keys_entry( isom_keys_entry_t
*data
)
984 lsmash_free( data
->key_value
);
987 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_keys
, keys
, isom_meta_t
, isom_remove_keys_entry
)
989 static void isom_remove_mean( isom_mean_t
*mean
)
993 lsmash_free( mean
->meaning_string
);
994 REMOVE_BOX( mean
, isom_metaitem_t
);
997 static void isom_remove_name( isom_name_t
*name
)
1001 lsmash_free( name
->name
);
1002 REMOVE_BOX( name
, isom_metaitem_t
);
1005 static void isom_remove_data( isom_data_t
*data
)
1009 lsmash_free( data
->value
);
1010 REMOVE_BOX( data
, isom_metaitem_t
);
1013 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_metaitem
, metaitem
, isom_ilst_t
)
1014 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_ilst
, ilst
, isom_meta_t
)
1016 static void isom_remove_meta( isom_meta_t
*meta
)
1022 if( lsmash_check_box_type_identical( meta
->parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
1023 REMOVE_BOX( meta
, lsmash_file_t
);
1024 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1025 REMOVE_BOX( meta
, isom_moov_t
);
1026 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1027 REMOVE_BOX( meta
, isom_trak_t
);
1028 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1029 REMOVE_BOX( meta
, isom_udta_t
);
1036 static void isom_remove_cprt( isom_cprt_t
*cprt
)
1040 lsmash_free( cprt
->notice
);
1041 REMOVE_BOX_IN_LIST( cprt
, isom_udta_t
);
1044 static void isom_remove_udta( isom_udta_t
*udta
)
1050 if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1051 REMOVE_BOX( udta
, isom_moov_t
);
1052 else if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1053 REMOVE_BOX( udta
, isom_trak_t
);
1060 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_WLOC
, WLOC
, isom_udta_t
)
1061 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_LOOP
, LOOP
, isom_udta_t
)
1062 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_SelO
, SelO
, isom_udta_t
)
1063 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_AllF
, AllF
, isom_udta_t
)
1065 static void isom_remove_ctab( isom_ctab_t
*ctab
)
1069 lsmash_free( ctab
->color_table
.array
);
1070 if( ctab
->parent
&& lsmash_check_box_type_identical( ctab
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1071 REMOVE_BOX( ctab
, isom_moov_t
);
1074 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvex
, mvex
, isom_moov_t
)
1075 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvhd
, mvhd
, isom_moov_t
)
1076 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mehd
, mehd
, isom_mvex_t
)
1077 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_trex
, trex
, isom_mvex_t
)
1078 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_moov
, moov
, lsmash_file_t
)
1079 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdat
, mdat
, lsmash_file_t
)
1080 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfhd
, mfhd
, isom_moof_t
)
1081 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfhd
, tfhd
, isom_traf_t
)
1082 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfdt
, tfdt
, isom_traf_t
)
1084 static void isom_remove_trun( isom_trun_t
*trun
)
1088 lsmash_remove_list( trun
->optional
, NULL
);
1089 REMOVE_BOX_IN_LIST( trun
, isom_traf_t
);
1092 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_traf
, traf
, isom_moof_t
)
1093 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_moof
, moof
, lsmash_file_t
)
1095 static void isom_remove_free( isom_free_t
*skip
)
1099 lsmash_free( skip
->data
);
1100 isom_remove_predefined_box( skip
, offsetof( lsmash_file_t
, free
) );
1102 #define isom_remove_skip isom_remove_free
1104 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfra
, mfra
, lsmash_file_t
)
1105 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfro
, mfro
, isom_mfra_t
)
1106 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_tfra
, tfra
, isom_mfra_t
)
1107 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_sidx
, sidx
, lsmash_file_t
)
1109 static void isom_remove_styp( isom_styp_t
*styp
)
1113 lsmash_free( styp
->compatible_brands
);
1114 REMOVE_BOX_IN_LIST( styp
, lsmash_file_t
);
1117 /* box size updater */
1118 uint64_t isom_update_box_size( void *opaque_box
)
1120 assert( opaque_box
);
1121 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
1122 if( box
->manager
& LSMASH_WRITTEN_BOX
)
1123 /* No need to calculate the size of this box since the size is already decided and fixed. */
1128 /* Calculate the size of this box excluding its children with a fake bytestream writer. */
1130 lsmash_bs_t fake_bs
= { NULL
};
1131 if( box
->write( &fake_bs
, box
) == 0 )
1132 size
= lsmash_bs_get_valid_data_size( &fake_bs
);
1134 /* Calculate the size of the children if no error. */
1135 if( size
>= ISOM_BASEBOX_COMMON_SIZE
)
1137 for( lsmash_entry_t
*entry
= box
->extensions
.head
; entry
; entry
= entry
->next
)
1139 size
+= isom_update_box_size( entry
->data
);
1140 /* Check large size. */
1141 if( size
> UINT32_MAX
)
1145 /* TODO: add error handling. */
1152 /* box adding functions */
1153 #define ATTACH_EXACTLY_ONE_BOX_TO_PARENT( box_name, parent_type ) \
1156 isom_box_t **p = (isom_box_t **)(((int8_t *)box_name->parent) \
1157 + offsetof( parent_type, box_name )); \
1159 *p = (isom_box_t *)box_name; \
1162 #define INIT_BOX_COMMON0( box_name, parent, box_type, precedence ) \
1163 const isom_extension_destructor_t isom_remove_##box_name = NULL; \
1164 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1165 #define INIT_BOX_COMMON1( box_name, parent, box_type, precedence ) \
1166 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1168 #define CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1171 isom_##box_name##_t *box_name = lsmash_malloc_zero( sizeof(isom_##box_name##_t) ); \
1174 INIT_BOX_COMMON ## has_destructor( box_name, parent, box_type, precedence ); \
1175 if( isom_add_box_to_extension_list( parent, box_name ) < 0 ) \
1177 lsmash_free( box_name ); \
1180 #define CREATE_LIST_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1181 CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ); \
1182 box_name->list = lsmash_create_entry_list(); \
1183 if( !box_name->list ) \
1185 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1189 #define ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1190 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1191 if( !(parent)->box_name ) \
1192 (parent)->box_name = box_name
1193 #define ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1194 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1195 if( lsmash_add_entry( &(parent)->box_name##_list, box_name ) < 0 ) \
1197 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1201 #define ADD_BOX( box_name, parent, box_type, precedence ) \
1202 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1203 #define ADD_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1204 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1205 #define ADD_LIST_BOX( box_name, parent, box_type, precedence ) \
1206 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1207 #define ADD_LIST_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1208 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1210 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ... ) CALL_FUNC_DEFAULT_ARGS( DEFINE_SIMPLE_BOX_ADDER_TEMPLATE, __VA_ARGS__ )
1211 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, parent_type ) \
1212 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1214 ADDER( box_name, parent_name, box_type, precedence ); \
1217 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5( ADDER, box_name, parent_name, box_type, precedence ) \
1218 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, isom_##parent_name##_t )
1220 #define DEFINE_SIMPLE_BOX_ADDER( func_name, ... ) \
1221 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX, __VA_ARGS__ )
1222 #define DEFINE_SIMPLE_BOX_IN_LIST_ADDER( func_name, ... ) \
1223 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX_IN_LIST, __VA_ARGS__ )
1224 #define DEFINE_SIMPLE_LIST_BOX_ADDER( func_name, ... ) \
1225 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_LIST_BOX, __VA_ARGS__ )
1227 #define DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( func_name, box_name, parent_name, box_type, precedence, has_destructor, parent_type ) \
1228 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1230 CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ); \
1234 lsmash_file_t
*isom_add_file( lsmash_root_t
*root
)
1236 lsmash_file_t
*file
= lsmash_malloc_zero( sizeof(lsmash_file_t
) );
1239 file
->class = &lsmash_box_class
;
1242 file
->parent
= (isom_box_t
*)root
;
1243 file
->destruct
= (isom_extension_destructor_t
)isom_remove_file
;
1245 file
->type
= LSMASH_BOX_TYPE_UNSPECIFIED
;
1246 if( isom_add_box_to_extension_list( root
, file
) < 0 )
1248 lsmash_free( file
);
1251 if( lsmash_add_entry( &root
->file_list
, file
) < 0 )
1253 lsmash_remove_entry_tail( &root
->extensions
, isom_remove_file
);
1259 isom_tref_type_t
*isom_add_track_reference_type( isom_tref_t
*tref
, isom_track_reference_type type
)
1263 isom_tref_type_t
*ref
= lsmash_malloc_zero( sizeof(isom_tref_type_t
) );
1266 /* Initialize common fields. */
1267 ref
->root
= tref
->root
;
1268 ref
->file
= tref
->file
;
1269 ref
->parent
= (isom_box_t
*)tref
;
1271 ref
->type
= lsmash_form_iso_box_type( type
);
1272 ref
->precedence
= LSMASH_BOX_PRECEDENCE_ISOM_TREF_TYPE
;
1273 ref
->destruct
= (isom_extension_destructor_t
)isom_remove_track_reference_type
;
1274 isom_set_box_writer( (isom_box_t
*)ref
);
1275 if( isom_add_box_to_extension_list( tref
, ref
) < 0 )
1280 if( lsmash_add_entry( &tref
->ref_list
, ref
) < 0 )
1282 lsmash_remove_entry_tail( &tref
->extensions
, isom_remove_track_reference_type
);
1288 DEFINE_SIMPLE_BOX_ADDER( isom_add_terminator
, terminator
, wave
, QT_BOX_TYPE_TERMINATOR
, LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
)
1289 DEFINE_SIMPLE_BOX_ADDER( isom_add_frma
, frma
, wave
, QT_BOX_TYPE_FRMA
, LSMASH_BOX_PRECEDENCE_QTFF_FRMA
)
1290 DEFINE_SIMPLE_BOX_ADDER( isom_add_enda
, enda
, wave
, QT_BOX_TYPE_ENDA
, LSMASH_BOX_PRECEDENCE_QTFF_ENDA
)
1291 DEFINE_SIMPLE_BOX_ADDER( isom_add_mp4a
, mp4a
, wave
, QT_BOX_TYPE_MP4A
, LSMASH_BOX_PRECEDENCE_QTFF_MP4A
)
1292 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ftab
, ftab
, tx3g
, ISOM_BOX_TYPE_FTAB
, LSMASH_BOX_PRECEDENCE_ISOM_FTAB
, isom_tx3g_entry_t
)
1293 DEFINE_SIMPLE_BOX_ADDER( isom_add_ftyp
, ftyp
, file
, ISOM_BOX_TYPE_FTYP
, LSMASH_BOX_PRECEDENCE_ISOM_FTYP
, lsmash_file_t
)
1294 DEFINE_SIMPLE_BOX_ADDER( isom_add_moov
, moov
, file
, ISOM_BOX_TYPE_MOOV
, LSMASH_BOX_PRECEDENCE_ISOM_MOOV
, lsmash_file_t
)
1295 DEFINE_SIMPLE_BOX_ADDER( isom_add_mvhd
, mvhd
, moov
, ISOM_BOX_TYPE_MVHD
, LSMASH_BOX_PRECEDENCE_ISOM_MVHD
)
1296 DEFINE_SIMPLE_BOX_ADDER( isom_add_iods
, iods
, moov
, ISOM_BOX_TYPE_IODS
, LSMASH_BOX_PRECEDENCE_ISOM_IODS
)
1298 isom_ctab_t
*isom_add_ctab( void *parent_box
)
1300 /* According to QuickTime File Format Specification, this box is placed inside Movie Box if present.
1301 * However, sometimes this box occurs inside an image description entry or the end of Sample Description Box. */
1304 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1305 CREATE_BOX( ctab
, parent
, QT_BOX_TYPE_CTAB
, LSMASH_BOX_PRECEDENCE_QTFF_CTAB
, 1 );
1306 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1307 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( ctab
, isom_moov_t
);
1311 isom_trak_t
*isom_add_trak( isom_moov_t
*moov
)
1313 if( !moov
|| !moov
->file
)
1315 CREATE_BOX( trak
, moov
, ISOM_BOX_TYPE_TRAK
, LSMASH_BOX_PRECEDENCE_ISOM_TRAK
, 1 );
1316 isom_fragment_t
*fragment
= NULL
;
1317 isom_cache_t
*cache
= lsmash_malloc_zero( sizeof(isom_cache_t
) );
1320 if( moov
->file
->fragment
)
1322 fragment
= lsmash_malloc_zero( sizeof(isom_fragment_t
) );
1325 cache
->fragment
= fragment
;
1327 if( lsmash_add_entry( &moov
->trak_list
, trak
) < 0 )
1329 trak
->cache
= cache
;
1332 lsmash_free( fragment
);
1333 lsmash_free( cache
);
1334 lsmash_remove_entry_tail( &moov
->extensions
, isom_remove_trak
);
1338 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tkhd
, tkhd
, trak
, ISOM_BOX_TYPE_TKHD
, LSMASH_BOX_PRECEDENCE_ISOM_TKHD
)
1339 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tapt
, tapt
, trak
, QT_BOX_TYPE_TAPT
, LSMASH_BOX_PRECEDENCE_QTFF_TAPT
)
1340 DEFINE_SIMPLE_BOX_ADDER ( isom_add_clef
, clef
, tapt
, QT_BOX_TYPE_CLEF
, LSMASH_BOX_PRECEDENCE_QTFF_CLEF
)
1341 DEFINE_SIMPLE_BOX_ADDER ( isom_add_prof
, prof
, tapt
, QT_BOX_TYPE_PROF
, LSMASH_BOX_PRECEDENCE_QTFF_PROF
)
1342 DEFINE_SIMPLE_BOX_ADDER ( isom_add_enof
, enof
, tapt
, QT_BOX_TYPE_ENOF
, LSMASH_BOX_PRECEDENCE_QTFF_ENOF
)
1343 DEFINE_SIMPLE_BOX_ADDER ( isom_add_edts
, edts
, trak
, ISOM_BOX_TYPE_EDTS
, LSMASH_BOX_PRECEDENCE_ISOM_EDTS
)
1344 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_elst
, elst
, edts
, ISOM_BOX_TYPE_ELST
, LSMASH_BOX_PRECEDENCE_ISOM_ELST
)
1345 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tref
, tref
, trak
, ISOM_BOX_TYPE_TREF
, LSMASH_BOX_PRECEDENCE_ISOM_TREF
)
1346 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdia
, mdia
, trak
, ISOM_BOX_TYPE_MDIA
, LSMASH_BOX_PRECEDENCE_ISOM_MDIA
)
1347 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdhd
, mdhd
, mdia
, ISOM_BOX_TYPE_MDHD
, LSMASH_BOX_PRECEDENCE_ISOM_MDHD
)
1349 isom_hdlr_t
*isom_add_hdlr( void *parent_box
)
1353 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1354 CREATE_BOX( hdlr
, parent
, ISOM_BOX_TYPE_HDLR
, LSMASH_BOX_PRECEDENCE_ISOM_HDLR
, 1 );
1355 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
) )
1356 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_mdia_t
);
1357 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1358 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1359 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_meta_t
);
1360 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1361 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_minf_t
);
1367 DEFINE_SIMPLE_BOX_ADDER( isom_add_minf
, minf
, mdia
, ISOM_BOX_TYPE_MINF
, LSMASH_BOX_PRECEDENCE_ISOM_MINF
)
1368 DEFINE_SIMPLE_BOX_ADDER( isom_add_vmhd
, vmhd
, minf
, ISOM_BOX_TYPE_VMHD
, LSMASH_BOX_PRECEDENCE_ISOM_VMHD
)
1369 DEFINE_SIMPLE_BOX_ADDER( isom_add_smhd
, smhd
, minf
, ISOM_BOX_TYPE_SMHD
, LSMASH_BOX_PRECEDENCE_ISOM_SMHD
)
1370 DEFINE_SIMPLE_BOX_ADDER( isom_add_hmhd
, hmhd
, minf
, ISOM_BOX_TYPE_HMHD
, LSMASH_BOX_PRECEDENCE_ISOM_HMHD
)
1371 DEFINE_SIMPLE_BOX_ADDER( isom_add_nmhd
, nmhd
, minf
, ISOM_BOX_TYPE_NMHD
, LSMASH_BOX_PRECEDENCE_ISOM_NMHD
)
1372 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmhd
, gmhd
, minf
, QT_BOX_TYPE_GMHD
, LSMASH_BOX_PRECEDENCE_QTFF_GMHD
)
1373 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmin
, gmin
, gmhd
, QT_BOX_TYPE_GMIN
, LSMASH_BOX_PRECEDENCE_QTFF_GMIN
)
1374 DEFINE_SIMPLE_BOX_ADDER( isom_add_text
, text
, gmhd
, QT_BOX_TYPE_TEXT
, LSMASH_BOX_PRECEDENCE_QTFF_TEXT
)
1376 isom_dinf_t
*isom_add_dinf( void *parent_box
)
1380 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1381 CREATE_BOX( dinf
, parent
, ISOM_BOX_TYPE_DINF
, LSMASH_BOX_PRECEDENCE_ISOM_DINF
, 1 );
1382 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1383 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_minf_t
);
1384 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1385 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1386 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_meta_t
);
1392 isom_dref_entry_t
*isom_add_dref_entry( isom_dref_t
*dref
, lsmash_box_type_t type
)
1396 isom_dref_entry_t
*data
= lsmash_malloc_zero( sizeof(isom_dref_entry_t
) );
1399 isom_init_box_common( data
, dref
, type
, LSMASH_BOX_PRECEDENCE_ISOM_DREF_ENTRY
, isom_remove_dref_entry
);
1400 if( isom_add_box_to_extension_list( dref
, data
) < 0 )
1402 lsmash_free( data
);
1405 if( lsmash_add_entry( &dref
->list
, data
) < 0 )
1407 lsmash_remove_entry_tail( &dref
->extensions
, isom_remove_dref_entry
);
1413 DEFINE_SIMPLE_BOX_ADDER( isom_add_dref
, dref
, dinf
, ISOM_BOX_TYPE_DREF
, LSMASH_BOX_PRECEDENCE_ISOM_DREF
)
1414 DEFINE_SIMPLE_BOX_ADDER( isom_add_stbl
, stbl
, minf
, ISOM_BOX_TYPE_STBL
, LSMASH_BOX_PRECEDENCE_ISOM_STBL
)
1415 DEFINE_SIMPLE_BOX_ADDER( isom_add_stsd
, stsd
, stbl
, ISOM_BOX_TYPE_STSD
, LSMASH_BOX_PRECEDENCE_ISOM_STSD
)
1417 static int isom_add_sample_description_entry
1421 void (*destructor
)( isom_sample_entry_t
* )
1424 if( isom_add_box_to_extension_list( stsd
, description
) < 0 )
1426 lsmash_free( description
);
1427 return LSMASH_ERR_MEMORY_ALLOC
;
1429 if( lsmash_add_entry( &stsd
->list
, description
) < 0 )
1431 lsmash_remove_entry_tail( &stsd
->extensions
, destructor
);
1432 return LSMASH_ERR_MEMORY_ALLOC
;
1437 isom_visual_entry_t
*isom_add_visual_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1440 isom_visual_entry_t
*visual
= lsmash_malloc_zero( sizeof(isom_visual_entry_t
) );
1443 isom_init_box_common( visual
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_visual_description
);
1444 visual
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1445 return isom_add_sample_description_entry( stsd
, visual
, isom_remove_visual_description
) ? NULL
: visual
;
1448 isom_audio_entry_t
*isom_add_audio_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1451 isom_audio_entry_t
*audio
= lsmash_malloc_zero( sizeof(isom_audio_entry_t
) );
1454 isom_init_box_common( audio
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_audio_description
);
1455 audio
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1456 return isom_add_sample_description_entry( stsd
, audio
, isom_remove_audio_description
) ? NULL
: audio
;
1459 isom_qt_text_entry_t
*isom_add_qt_text_description( isom_stsd_t
*stsd
)
1462 isom_qt_text_entry_t
*text
= lsmash_malloc_zero( sizeof(isom_qt_text_entry_t
) );
1465 isom_init_box_common( text
, stsd
, QT_CODEC_TYPE_TEXT_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_qt_text_description
);
1466 return isom_add_sample_description_entry( stsd
, text
, isom_remove_qt_text_description
) ? NULL
: text
;
1469 isom_tx3g_entry_t
*isom_add_tx3g_description( isom_stsd_t
*stsd
)
1472 isom_tx3g_entry_t
*tx3g
= lsmash_malloc_zero( sizeof(isom_tx3g_entry_t
) );
1475 isom_init_box_common( tx3g
, stsd
, ISOM_CODEC_TYPE_TX3G_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_tx3g_description
);
1476 return isom_add_sample_description_entry( stsd
, tx3g
, isom_remove_tx3g_description
) ? NULL
: tx3g
;
1479 isom_esds_t
*isom_add_esds( void *parent_box
)
1481 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1482 int is_qt
= lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
);
1483 lsmash_box_type_t box_type
= is_qt
? QT_BOX_TYPE_ESDS
: ISOM_BOX_TYPE_ESDS
;
1484 uint64_t precedence
= is_qt
? LSMASH_BOX_PRECEDENCE_QTFF_ESDS
: LSMASH_BOX_PRECEDENCE_ISOM_ESDS
;
1485 CREATE_BOX( esds
, parent
, box_type
, precedence
, 1 );
1489 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_glbl
, glbl
, parent_box
, QT_BOX_TYPE_GLBL
, LSMASH_BOX_PRECEDENCE_QTFF_GLBL
, 1, void )
1490 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_clap
, clap
, visual
, ISOM_BOX_TYPE_CLAP
, LSMASH_BOX_PRECEDENCE_ISOM_CLAP
, 0, isom_visual_entry_t
)
1491 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_pasp
, pasp
, visual
, ISOM_BOX_TYPE_PASP
, LSMASH_BOX_PRECEDENCE_ISOM_PASP
, 0, isom_visual_entry_t
)
1492 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_colr
, colr
, visual
, ISOM_BOX_TYPE_COLR
, LSMASH_BOX_PRECEDENCE_ISOM_COLR
, 0, isom_visual_entry_t
)
1493 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_gama
, gama
, visual
, QT_BOX_TYPE_GAMA
, LSMASH_BOX_PRECEDENCE_QTFF_GAMA
, 0, isom_visual_entry_t
)
1494 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_fiel
, fiel
, visual
, QT_BOX_TYPE_FIEL
, LSMASH_BOX_PRECEDENCE_QTFF_FIEL
, 0, isom_visual_entry_t
)
1495 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_cspc
, cspc
, visual
, QT_BOX_TYPE_CSPC
, LSMASH_BOX_PRECEDENCE_QTFF_CSPC
, 0, isom_visual_entry_t
)
1496 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_sgbt
, sgbt
, visual
, QT_BOX_TYPE_SGBT
, LSMASH_BOX_PRECEDENCE_QTFF_SGBT
, 0, isom_visual_entry_t
)
1497 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_stsl
, stsl
, visual
, ISOM_BOX_TYPE_STSL
, LSMASH_BOX_PRECEDENCE_ISOM_STSL
, 0, isom_visual_entry_t
)
1498 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_btrt
, btrt
, visual
, ISOM_BOX_TYPE_BTRT
, LSMASH_BOX_PRECEDENCE_ISOM_BTRT
, 0, isom_visual_entry_t
)
1499 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_wave
, wave
, audio
, QT_BOX_TYPE_WAVE
, LSMASH_BOX_PRECEDENCE_QTFF_WAVE
, 0, isom_audio_entry_t
)
1500 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_chan
, chan
, audio
, QT_BOX_TYPE_CHAN
, LSMASH_BOX_PRECEDENCE_QTFF_CHAN
, 1, isom_audio_entry_t
)
1501 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_srat
, srat
, audio
, ISOM_BOX_TYPE_SRAT
, LSMASH_BOX_PRECEDENCE_ISOM_SRAT
, 0, isom_audio_entry_t
)
1503 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stts
, stts
, stbl
, ISOM_BOX_TYPE_STTS
, LSMASH_BOX_PRECEDENCE_ISOM_STTS
)
1504 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ctts
, ctts
, stbl
, ISOM_BOX_TYPE_CTTS
, LSMASH_BOX_PRECEDENCE_ISOM_CTTS
)
1505 DEFINE_SIMPLE_BOX_ADDER ( isom_add_cslg
, cslg
, stbl
, ISOM_BOX_TYPE_CSLG
, LSMASH_BOX_PRECEDENCE_ISOM_CSLG
)
1506 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stsc
, stsc
, stbl
, ISOM_BOX_TYPE_STSC
, LSMASH_BOX_PRECEDENCE_ISOM_STSC
)
1507 DEFINE_SIMPLE_BOX_ADDER ( isom_add_stsz
, stsz
, stbl
, ISOM_BOX_TYPE_STSZ
, LSMASH_BOX_PRECEDENCE_ISOM_STSZ
) /* We don't create a list here. */
1508 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stss
, stss
, stbl
, ISOM_BOX_TYPE_STSS
, LSMASH_BOX_PRECEDENCE_ISOM_STSS
)
1509 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stps
, stps
, stbl
, QT_BOX_TYPE_STPS
, LSMASH_BOX_PRECEDENCE_QTFF_STPS
)
1511 isom_stco_t
*isom_add_stco( isom_stbl_t
*stbl
)
1513 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_STCO
, LSMASH_BOX_PRECEDENCE_ISOM_STCO
);
1514 stco
->large_presentation
= 0;
1518 isom_stco_t
*isom_add_co64( isom_stbl_t
*stbl
)
1520 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_CO64
, LSMASH_BOX_PRECEDENCE_ISOM_CO64
);
1521 stco
->large_presentation
= 1;
1525 isom_sdtp_t
*isom_add_sdtp( isom_box_t
*parent
)
1529 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1531 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1532 ADD_LIST_BOX( sdtp
, stbl
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1535 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1537 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1538 ADD_LIST_BOX( sdtp
, traf
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1545 isom_sgpd_t
*isom_add_sgpd( void *parent_box
)
1549 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1550 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1552 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1553 ADD_LIST_BOX_IN_LIST( sgpd
, stbl
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1556 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1558 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1559 ADD_LIST_BOX_IN_LIST( sgpd
, traf
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1566 isom_sbgp_t
*isom_add_sbgp( void *parent_box
)
1570 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1571 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1573 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1574 ADD_LIST_BOX_IN_LIST( sbgp
, stbl
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1577 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1579 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1580 ADD_LIST_BOX_IN_LIST( sbgp
, traf
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1587 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_chpl
, chpl
, udta
, ISOM_BOX_TYPE_CHPL
, LSMASH_BOX_PRECEDENCE_ISOM_CHPL
)
1589 isom_metaitem_t
*isom_add_metaitem( isom_ilst_t
*ilst
, lsmash_itunes_metadata_item item
)
1593 lsmash_box_type_t type
= lsmash_form_iso_box_type( item
);
1594 ADD_BOX_IN_LIST( metaitem
, ilst
, type
, LSMASH_BOX_PRECEDENCE_ISOM_METAITEM
);
1598 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mean
, mean
, metaitem
, ISOM_BOX_TYPE_MEAN
, LSMASH_BOX_PRECEDENCE_ISOM_MEAN
)
1599 DEFINE_SIMPLE_BOX_ADDER ( isom_add_name
, name
, metaitem
, ISOM_BOX_TYPE_NAME
, LSMASH_BOX_PRECEDENCE_ISOM_NAME
)
1600 DEFINE_SIMPLE_BOX_ADDER ( isom_add_data
, data
, metaitem
, ISOM_BOX_TYPE_DATA
, LSMASH_BOX_PRECEDENCE_ISOM_DATA
)
1601 DEFINE_SIMPLE_BOX_ADDER ( isom_add_ilst
, ilst
, meta
, ISOM_BOX_TYPE_ILST
, LSMASH_BOX_PRECEDENCE_ISOM_ILST
)
1602 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_keys
, keys
, meta
, QT_BOX_TYPE_KEYS
, LSMASH_BOX_PRECEDENCE_QTFF_KEYS
)
1604 isom_meta_t
*isom_add_meta( void *parent_box
)
1608 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1609 CREATE_BOX( meta
, parent
, ISOM_BOX_TYPE_META
, LSMASH_BOX_PRECEDENCE_ISOM_META
, 1 );
1610 if( parent
->file
== (lsmash_file_t
*)parent
)
1611 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, lsmash_file_t
);
1612 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1613 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_moov_t
);
1614 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1615 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_trak_t
);
1616 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1617 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_udta_t
);
1623 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_cprt
, cprt
, udta
, ISOM_BOX_TYPE_CPRT
, LSMASH_BOX_PRECEDENCE_ISOM_CPRT
)
1625 isom_udta_t
*isom_add_udta( void *parent_box
)
1629 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1630 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1632 isom_moov_t
*moov
= (isom_moov_t
*)parent
;
1633 ADD_BOX( udta
, moov
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1636 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1638 isom_trak_t
*trak
= (isom_trak_t
*)parent
;
1639 ADD_BOX( udta
, trak
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1646 DEFINE_SIMPLE_BOX_ADDER ( isom_add_WLOC
, WLOC
, udta
, QT_BOX_TYPE_WLOC
, LSMASH_BOX_PRECEDENCE_QTFF_WLOC
)
1647 DEFINE_SIMPLE_BOX_ADDER ( isom_add_LOOP
, LOOP
, udta
, QT_BOX_TYPE_LOOP
, LSMASH_BOX_PRECEDENCE_QTFF_LOOP
)
1648 DEFINE_SIMPLE_BOX_ADDER ( isom_add_SelO
, SelO
, udta
, QT_BOX_TYPE_SELO
, LSMASH_BOX_PRECEDENCE_QTFF_SELO
)
1649 DEFINE_SIMPLE_BOX_ADDER ( isom_add_AllF
, AllF
, udta
, QT_BOX_TYPE_ALLF
, LSMASH_BOX_PRECEDENCE_QTFF_ALLF
)
1650 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mvex
, mvex
, moov
, ISOM_BOX_TYPE_MVEX
, LSMASH_BOX_PRECEDENCE_ISOM_MVEX
)
1651 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mehd
, mehd
, mvex
, ISOM_BOX_TYPE_MEHD
, LSMASH_BOX_PRECEDENCE_ISOM_MEHD
)
1652 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trex
, trex
, mvex
, ISOM_BOX_TYPE_TREX
, LSMASH_BOX_PRECEDENCE_ISOM_TREX
)
1653 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_moof
, moof
, file
, ISOM_BOX_TYPE_MOOF
, LSMASH_BOX_PRECEDENCE_ISOM_MOOF
, lsmash_file_t
)
1654 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfhd
, mfhd
, moof
, ISOM_BOX_TYPE_MFHD
, LSMASH_BOX_PRECEDENCE_ISOM_MFHD
)
1655 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_traf
, traf
, moof
, ISOM_BOX_TYPE_TRAF
, LSMASH_BOX_PRECEDENCE_ISOM_TRAF
)
1656 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfhd
, tfhd
, traf
, ISOM_BOX_TYPE_TFHD
, LSMASH_BOX_PRECEDENCE_ISOM_TFHD
)
1657 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfdt
, tfdt
, traf
, ISOM_BOX_TYPE_TFDT
, LSMASH_BOX_PRECEDENCE_ISOM_TFDT
)
1658 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trun
, trun
, traf
, ISOM_BOX_TYPE_TRUN
, LSMASH_BOX_PRECEDENCE_ISOM_TRUN
)
1659 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfra
, mfra
, file
, ISOM_BOX_TYPE_MFRA
, LSMASH_BOX_PRECEDENCE_ISOM_MFRA
, lsmash_file_t
)
1660 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_tfra
, tfra
, mfra
, ISOM_BOX_TYPE_TFRA
, LSMASH_BOX_PRECEDENCE_ISOM_TFRA
)
1661 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfro
, mfro
, mfra
, ISOM_BOX_TYPE_MFRO
, LSMASH_BOX_PRECEDENCE_ISOM_MFRO
)
1663 isom_mdat_t
*isom_add_mdat( lsmash_file_t
*file
)
1665 assert( !file
->mdat
);
1666 CREATE_BOX( mdat
, file
, ISOM_BOX_TYPE_MDAT
, LSMASH_BOX_PRECEDENCE_ISOM_MDAT
, 1 );
1671 isom_free_t
*isom_add_free( void *parent_box
)
1675 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1676 if( parent
->file
== (lsmash_file_t
*)parent
)
1678 lsmash_file_t
*file
= (lsmash_file_t
*)parent
;
1679 CREATE_BOX( skip
, file
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1684 CREATE_BOX( skip
, parent
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1688 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_styp
, styp
, file
, ISOM_BOX_TYPE_STYP
, LSMASH_BOX_PRECEDENCE_ISOM_STYP
, lsmash_file_t
)
1690 isom_sidx_t
*isom_add_sidx( lsmash_file_t
*file
)
1692 ADD_LIST_BOX_IN_LIST( sidx
, file
, ISOM_BOX_TYPE_SIDX
, LSMASH_BOX_PRECEDENCE_ISOM_SIDX
);
1696 #undef ATTACH_EXACTLY_ONE_BOX_TO_PARENT
1698 #undef CREATE_LIST_BOX
1699 #undef ADD_BOX_TEMPLATE
1700 #undef ADD_BOX_IN_LIST_TEMPLATE
1702 #undef ADD_BOX_IN_LIST
1704 #undef ADD_LIST_BOX_IN_LIST
1705 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE
1706 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6
1707 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5
1708 #undef DEFINE_SIMPLE_BOX_ADDER
1709 #undef DEFINE_SIMPLE_BOX_IN_LIST_ADDER
1710 #undef DEFINE_SIMPLE_LIST_BOX_ADDER
1712 static int fake_file_read
1719 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1721 if( stream
->pos
+ size
> stream
->size
)
1722 read_size
= stream
->size
- stream
->pos
;
1725 memcpy( buf
, stream
->data
+ stream
->pos
, read_size
);
1726 stream
->pos
+= read_size
;
1730 static int64_t fake_file_seek
1737 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1738 if( whence
== SEEK_SET
)
1739 stream
->pos
= offset
;
1740 else if( whence
== SEEK_CUR
)
1741 stream
->pos
+= offset
;
1742 else if( whence
== SEEK_END
)
1743 stream
->pos
= stream
->size
+ offset
;
1747 /* Public functions */
1748 lsmash_root_t
*lsmash_create_root( void )
1750 lsmash_root_t
*root
= lsmash_malloc_zero( sizeof(lsmash_root_t
) );
1757 void lsmash_destroy_root( lsmash_root_t
*root
)
1759 isom_remove_box_by_itself( root
);
1762 lsmash_extended_box_type_t
lsmash_form_extended_box_type( uint32_t fourcc
, const uint8_t id
[12] )
1764 return (lsmash_extended_box_type_t
){ fourcc
, { id
[0], id
[1], id
[2], id
[3], id
[4], id
[5],
1765 id
[6], id
[7], id
[8], id
[9], id
[10], id
[11] } };
1768 lsmash_box_type_t
lsmash_form_iso_box_type( uint32_t fourcc
)
1770 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_ISO_12_BYTES
) };
1773 lsmash_box_type_t
lsmash_form_qtff_box_type( uint32_t fourcc
)
1775 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_QTFF_12_BYTES
) };
1778 #define CHECK_BOX_TYPE_IDENTICAL( a, b ) \
1779 a.fourcc == b.fourcc \
1780 && a.user.fourcc == b.user.fourcc \
1781 && a.user.id[0] == b.user.id[0] \
1782 && a.user.id[1] == b.user.id[1] \
1783 && a.user.id[2] == b.user.id[2] \
1784 && a.user.id[3] == b.user.id[3] \
1785 && a.user.id[4] == b.user.id[4] \
1786 && a.user.id[5] == b.user.id[5] \
1787 && a.user.id[6] == b.user.id[6] \
1788 && a.user.id[7] == b.user.id[7] \
1789 && a.user.id[8] == b.user.id[8] \
1790 && a.user.id[9] == b.user.id[9] \
1791 && a.user.id[10] == b.user.id[10] \
1792 && a.user.id[11] == b.user.id[11]
1794 int lsmash_check_box_type_identical( lsmash_box_type_t a
, lsmash_box_type_t b
)
1796 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1799 int lsmash_check_codec_type_identical( lsmash_codec_type_t a
, lsmash_codec_type_t b
)
1801 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1804 int lsmash_check_box_type_specified( const lsmash_box_type_t
*box_type
)
1809 return !!(box_type
->fourcc
1810 | box_type
->user
.fourcc
1811 | box_type
->user
.id
[0] | box_type
->user
.id
[1] | box_type
->user
.id
[2] | box_type
->user
.id
[3]
1812 | box_type
->user
.id
[4] | box_type
->user
.id
[5] | box_type
->user
.id
[6] | box_type
->user
.id
[7]
1813 | box_type
->user
.id
[8] | box_type
->user
.id
[9] | box_type
->user
.id
[10] | box_type
->user
.id
[11]);
1816 lsmash_box_t
*lsmash_get_box
1818 lsmash_box_t
*parent
,
1819 const lsmash_box_path_t box_path
[]
1822 lsmash_entry_t
*entry
= isom_get_entry_of_box( parent
, box_path
);
1823 return (lsmash_box_t
*)(entry
? entry
->data
: NULL
);
1826 lsmash_box_t
*lsmash_create_box
1828 lsmash_box_type_t type
,
1834 if( !lsmash_check_box_type_specified( &type
) )
1836 isom_unknown_box_t
*box
= lsmash_malloc_zero( sizeof(isom_unknown_box_t
) );
1841 box
->unknown_size
= size
;
1842 box
->unknown_field
= lsmash_memdup( data
, size
);
1843 if( !box
->unknown_field
)
1851 box
->unknown_size
= 0;
1852 box
->unknown_field
= NULL
;
1855 box
->class = &lsmash_box_class
;
1859 box
->destruct
= (isom_extension_destructor_t
)isom_remove_unknown_box
;
1860 box
->manager
= LSMASH_UNKNOWN_BOX
;
1861 box
->precedence
= precedence
;
1862 box
->size
= ISOM_BASEBOX_COMMON_SIZE
+ size
+ (type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0);
1864 isom_set_box_writer( (isom_box_t
*)box
);
1865 return (lsmash_box_t
*)box
;
1870 lsmash_box_t
*parent
,
1875 /* You cannot add any box without a box being its parent. */
1876 return LSMASH_ERR_FUNCTION_PARAM
;
1877 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1878 return LSMASH_ERR_FUNCTION_PARAM
;
1879 if( parent
->root
== (lsmash_root_t
*)parent
)
1881 /* Only files can be added into any ROOT.
1882 * For backward compatibility, use the active file as the parent. */
1884 parent
= (isom_box_t
*)parent
->file
;
1886 return LSMASH_ERR_FUNCTION_PARAM
;
1888 /* Add a box as a child box. */
1889 box
->root
= parent
->root
;
1890 box
->file
= parent
->file
;
1891 box
->parent
= parent
;
1892 return isom_add_box_to_extension_list( parent
, box
);
1895 int lsmash_add_box_ex
1897 lsmash_box_t
*parent
,
1898 lsmash_box_t
**p_box
1902 /* You cannot add any box without a box being its parent. */
1903 return LSMASH_ERR_FUNCTION_PARAM
;
1904 isom_unknown_box_t
*box
= (isom_unknown_box_t
*)*p_box
;
1905 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1906 return LSMASH_ERR_FUNCTION_PARAM
;
1907 if( !(box
->manager
& LSMASH_UNKNOWN_BOX
) )
1908 /* Simply add the box. */
1909 return lsmash_add_box( parent
, *p_box
);
1910 /* Check if the size of the box to be added is valid. */
1911 if( box
->size
!= ISOM_BASEBOX_COMMON_SIZE
+ box
->unknown_size
+ (box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0) )
1912 return LSMASH_ERR_FUNCTION_PARAM
;
1913 if( !parent
->file
|| parent
->file
== (lsmash_file_t
*)box
)
1914 return LSMASH_ERR_FUNCTION_PARAM
;
1915 if( parent
->root
== (lsmash_root_t
*)parent
)
1916 /* Only files can be added into any ROOT.
1917 * For backward compatibility, use the active file as the parent. */
1918 parent
= (isom_box_t
*)parent
->file
;
1919 /* Switch to the fake-file stream mode. */
1920 lsmash_file_t
*file
= parent
->file
;
1921 lsmash_bs_t
*bs_backup
= file
->bs
;
1922 lsmash_bs_t
*bs
= lsmash_bs_create();
1924 return LSMASH_ERR_MEMORY_ALLOC
;
1925 uint8_t *buf
= lsmash_malloc( box
->size
);
1928 lsmash_bs_cleanup( bs
);
1929 return LSMASH_ERR_MEMORY_ALLOC
;
1931 fake_file_stream_t fake_file
=
1937 bs
->stream
= &fake_file
;
1938 bs
->read
= fake_file_read
;
1940 bs
->seek
= fake_file_seek
;
1942 file
->fake_file_mode
= 1;
1943 /* Make the byte string representing the given box. */
1944 LSMASH_SET_BE32( &buf
[0], box
->size
);
1945 LSMASH_SET_BE32( &buf
[4], box
->type
.fourcc
);
1946 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
1948 LSMASH_SET_BE32( &buf
[8], box
->type
.user
.fourcc
);
1949 memcpy( &buf
[12], box
->type
.user
.id
, 12 );
1951 memcpy( buf
+ (uintptr_t)(box
->size
- box
->unknown_size
), box
->unknown_field
, box
->unknown_size
);
1952 /* Add a box as a child box and try to expand into struct format. */
1953 lsmash_box_t dummy
= { 0 };
1954 int ret
= isom_read_box( file
, &dummy
, parent
, 0, 0 );
1956 lsmash_bs_cleanup( bs
);
1957 file
->bs
= bs_backup
; /* Switch back to the normal file stream mode. */
1958 file
->fake_file_mode
= 0;
1961 /* Reorder the added box by 'precedence'. */
1962 *p_box
= (lsmash_box_t
*)parent
->extensions
.tail
->data
;
1963 (*p_box
)->precedence
= box
->precedence
;
1964 isom_reorder_tail_box( parent
);
1965 /* Do also its children by the same way. */
1966 lsmash_entry_list_t extensions
= box
->extensions
;
1967 lsmash_init_entry_list( &box
->extensions
); /* to avoid freeing the children */
1968 isom_remove_box_by_itself( box
);
1969 for( lsmash_entry_t
*entry
= extensions
.head
; entry
; entry
= entry
->next
)
1973 lsmash_box_t
*child
= (lsmash_box_t
*)entry
->data
;
1974 if( lsmash_add_box_ex( *p_box
, &child
) == 0 )
1976 (*p_box
)->size
+= child
->size
;
1977 /* Avoid freeing at the end of this function. */
1981 isom_remove_all_extension_boxes( &extensions
);
1985 void lsmash_destroy_box
1990 isom_remove_box_by_itself( box
);
1993 void lsmash_destroy_children
1999 isom_remove_all_extension_boxes( &box
->extensions
);
2002 int lsmash_get_box_precedence
2005 uint64_t *precedence
2008 if( !box
|| !precedence
)
2009 return LSMASH_ERR_FUNCTION_PARAM
;
2010 *precedence
= box
->precedence
;
2014 lsmash_box_t
*lsmash_root_as_box
2019 return (lsmash_box_t
*)root
;
2022 lsmash_box_t
*lsmash_file_as_box
2027 return (lsmash_box_t
*)file
;
2030 int lsmash_write_top_level_box
2035 if( !box
|| (isom_box_t
*)box
->file
!= box
->parent
)
2036 return LSMASH_ERR_FUNCTION_PARAM
;
2037 int ret
= isom_write_box( box
->file
->bs
, box
);
2040 box
->file
->size
+= box
->size
;
2044 uint8_t *lsmash_export_box
2052 lsmash_bs_t
*bs
= lsmash_bs_create();
2055 if( isom_write_box( bs
, box
) < 0 )
2057 lsmash_bs_cleanup( bs
);
2060 *size
= bs
->buffer
.store
;
2061 uint8_t *data
= bs
->buffer
.data
;
2062 bs
->buffer
.data
= NULL
;
2063 lsmash_bs_cleanup( bs
);