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 static const lsmash_class_t lsmash_box_class
=
44 void isom_init_box_common_orig
48 lsmash_box_type_t box_type
,
50 isom_extension_destructor_t destructor
53 isom_box_t
*box
= (isom_box_t
*)_box
;
54 isom_box_t
*parent
= (isom_box_t
*)_parent
;
55 assert( box
&& parent
&& parent
->root
);
56 box
->class = &lsmash_box_class
;
57 box
->root
= parent
->root
;
58 box
->file
= parent
->file
;
60 box
->precedence
= precedence
;
61 box
->destruct
= destructor
;
64 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) && isom_is_fullbox( box
) )
69 isom_set_box_writer( box
);
72 static void isom_reorder_tail_box( isom_box_t
*parent
)
74 /* Reorder the appended box by 'precedence'. */
75 lsmash_entry_t
*x
= parent
->extensions
.tail
;
76 assert( x
&& x
->data
);
77 uint64_t precedence
= ((isom_box_t
*)x
->data
)->precedence
;
78 for( lsmash_entry_t
*y
= x
->prev
; y
; y
= y
->prev
)
80 isom_box_t
*box
= (isom_box_t
*)y
->data
;
81 if( !box
|| precedence
> box
->precedence
)
83 /* Exchange the entity data of adjacent two entries. */
93 int isom_add_box_to_extension_list( void *parent_box
, void *child_box
)
95 assert( parent_box
&& child_box
);
96 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
97 isom_box_t
*child
= (isom_box_t
*)child_box
;
98 /* Append at the end of the list. */
99 if( lsmash_add_entry( &parent
->extensions
, child
) < 0 )
101 /* Don't reorder the appended box when the file is opened for reading. */
102 if( !parent
->file
|| (parent
->file
->flags
& LSMASH_FILE_MODE_READ
) || parent
->file
->fake_file_mode
)
104 isom_reorder_tail_box( parent
);
108 void isom_bs_put_basebox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
110 if( box
->size
> UINT32_MAX
)
112 lsmash_bs_put_be32( bs
, 1 );
113 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
114 lsmash_bs_put_be64( bs
, box
->size
); /* largesize */
118 lsmash_bs_put_be32( bs
, (uint32_t)box
->size
);
119 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
121 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
123 lsmash_bs_put_be32( bs
, box
->type
.user
.fourcc
);
124 lsmash_bs_put_bytes( bs
, 12, box
->type
.user
.id
);
128 void isom_bs_put_fullbox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
130 isom_bs_put_basebox_common( bs
, box
);
131 lsmash_bs_put_byte( bs
, box
->version
);
132 lsmash_bs_put_be24( bs
, box
->flags
);
135 void isom_bs_put_box_common( lsmash_bs_t
*bs
, void *box
)
142 isom_box_t
*parent
= ((isom_box_t
*)box
)->parent
;
143 if( parent
&& lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
145 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
148 if( isom_is_fullbox( box
) )
149 isom_bs_put_fullbox_common( bs
, (isom_box_t
*)box
);
151 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
154 /* Return 1 if the box is fullbox, Otherwise return 0. */
155 int isom_is_fullbox( void *box
)
157 isom_box_t
*current
= (isom_box_t
*)box
;
158 lsmash_box_type_t type
= current
->type
;
159 static lsmash_box_type_t fullbox_type_table
[50] = { LSMASH_BOX_TYPE_INITIALIZER
};
160 if( !lsmash_check_box_type_specified( &fullbox_type_table
[0] ) )
162 /* Initialize the table. */
164 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SIDX
;
165 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MVHD
;
166 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TKHD
;
167 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_IODS
;
168 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ESDS
;
169 fullbox_type_table
[i
++] = QT_BOX_TYPE_ESDS
;
170 fullbox_type_table
[i
++] = QT_BOX_TYPE_CLEF
;
171 fullbox_type_table
[i
++] = QT_BOX_TYPE_PROF
;
172 fullbox_type_table
[i
++] = QT_BOX_TYPE_ENOF
;
173 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ELST
;
174 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MDHD
;
175 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HDLR
;
176 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_VMHD
;
177 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SMHD
;
178 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HMHD
;
179 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NMHD
;
180 fullbox_type_table
[i
++] = QT_BOX_TYPE_GMIN
;
181 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_DREF
;
182 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_URL
;
183 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSD
;
184 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSL
;
185 fullbox_type_table
[i
++] = QT_BOX_TYPE_CHAN
;
186 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SRAT
;
187 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STTS
;
188 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CTTS
;
189 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CSLG
;
190 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSS
;
191 fullbox_type_table
[i
++] = QT_BOX_TYPE_STPS
;
192 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SDTP
;
193 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSC
;
194 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSZ
;
195 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STCO
;
196 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CO64
;
197 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SGPD
;
198 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SBGP
;
199 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CHPL
;
200 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_META
;
201 fullbox_type_table
[i
++] = QT_BOX_TYPE_KEYS
;
202 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEAN
;
203 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NAME
;
204 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEHD
;
205 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TREX
;
206 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFHD
;
207 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFHD
;
208 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFDT
;
209 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TRUN
;
210 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFRA
;
211 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFRO
;
212 fullbox_type_table
[i
] = LSMASH_BOX_TYPE_UNSPECIFIED
;
214 for( int i
= 0; lsmash_check_box_type_specified( &fullbox_type_table
[i
] ); i
++ )
215 if( lsmash_check_box_type_identical( type
, fullbox_type_table
[i
] ) )
217 return lsmash_check_box_type_identical( type
, ISOM_BOX_TYPE_CPRT
)
218 && current
->parent
&& lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_UDTA
);
221 /* Return 1 if the sample type is LPCM audio, Otherwise return 0. */
222 int isom_is_lpcm_audio( void *box
)
224 isom_box_t
*current
= (isom_box_t
*)box
;
225 lsmash_box_type_t type
= current
->type
;
226 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
227 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
228 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
229 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
230 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
231 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
232 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
233 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
234 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
235 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
236 || (lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
) && (current
->manager
& LSMASH_AUDIO_DESCRIPTION
));
239 int isom_is_qt_audio( lsmash_codec_type_t type
)
241 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
242 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC3_AUDIO
)
243 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC6_AUDIO
)
244 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
245 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDM2_AUDIO
)
246 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDMC_AUDIO
)
247 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QCLP_AUDIO
)
248 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AC_3_AUDIO
)
249 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AGSM_AUDIO
)
250 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAC_AUDIO
)
251 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAW_AUDIO
)
252 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX2_AUDIO
)
253 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX4_AUDIO
)
254 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVCA_AUDIO
)
255 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVI_AUDIO
)
256 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
257 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
258 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IMA4_AUDIO
)
259 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
260 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
261 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
262 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP4A_AUDIO
)
263 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
)
264 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
265 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
266 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ULAW_AUDIO
)
267 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_VDVA_AUDIO
)
268 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
269 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
)
270 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
271 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
272 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
273 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
);
276 /* Return 1 if the sample type is uncompressed Y'CbCr video, Otherwise return 0. */
277 int isom_is_uncompressed_ycbcr( lsmash_codec_type_t type
)
279 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_2VUY_VIDEO
)
280 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V210_VIDEO
)
281 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V216_VIDEO
)
282 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V308_VIDEO
)
283 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V408_VIDEO
)
284 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V410_VIDEO
)
285 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_YUV2_VIDEO
);
288 int isom_is_waveform_audio( lsmash_box_type_t type
)
290 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
291 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
292 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
293 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
294 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
);
297 size_t isom_skip_box_common( uint8_t **p_data
)
299 uint8_t *orig
= *p_data
;
300 uint8_t *data
= *p_data
;
301 uint64_t size
= LSMASH_GET_BE32( data
);
302 data
+= ISOM_BASEBOX_COMMON_SIZE
;
305 size
= LSMASH_GET_BE64( data
);
312 static void isom_destruct_extension_binary( void *ext
)
316 isom_box_t
*box
= (isom_box_t
*)ext
;
317 lsmash_free( box
->binary
);
320 int isom_add_extension_binary
323 lsmash_box_type_t box_type
,
329 if( !parent_box
|| !box_data
|| box_size
< ISOM_BASEBOX_COMMON_SIZE
330 || !lsmash_check_box_type_specified( &box_type
) )
332 isom_box_t
*ext
= lsmash_malloc_zero( sizeof(isom_box_t
) );
335 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
336 ext
->class = &lsmash_box_class
;
337 ext
->root
= parent
->root
;
338 ext
->file
= parent
->file
;
339 ext
->parent
= parent
;
340 ext
->manager
= LSMASH_BINARY_CODED_BOX
;
341 ext
->precedence
= precedence
;
342 ext
->size
= box_size
;
343 ext
->type
= box_type
;
344 ext
->binary
= box_data
;
345 ext
->destruct
= isom_destruct_extension_binary
;
346 if( isom_add_box_to_extension_list( parent
, ext
) < 0 )
351 isom_set_box_writer( ext
);
355 static void isom_remove_extension_box( isom_box_t
*ext
)
360 ext
->destruct( ext
);
361 isom_remove_all_extension_boxes( &ext
->extensions
);
365 void isom_remove_all_extension_boxes( lsmash_entry_list_t
*extensions
)
367 lsmash_remove_entries( extensions
, isom_remove_extension_box
);
370 isom_box_t
*isom_get_extension_box( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
372 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
374 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
377 if( lsmash_check_box_type_identical( ext
->type
, box_type
) )
383 void *isom_get_extension_box_format( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
385 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
387 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
388 if( !ext
|| (ext
->manager
& LSMASH_BINARY_CODED_BOX
) || !lsmash_check_box_type_identical( ext
->type
, box_type
) )
395 lsmash_entry_t
*isom_get_entry_of_box
397 lsmash_box_t
*parent
,
398 const lsmash_box_path_t box_path
[]
403 lsmash_entry_t
*entry
= NULL
;
404 const lsmash_box_path_t
*path
= &box_path
[0];
405 while( lsmash_check_box_type_specified( &path
->type
) )
407 entry
= parent
->extensions
.head
;
412 uint32_t number
= path
->number
? path
->number
: 1;
415 isom_box_t
*box
= entry
->data
;
416 if( box
&& lsmash_check_box_type_identical( path
->type
, box
->type
) )
420 /* Found a box. Move to a child box. */
435 /* box destructors */
436 #define REMOVE_BOX( box_name, parent_type ) \
437 isom_remove_predefined_box( box_name, offsetof( parent_type, box_name ) )
439 #define REMOVE_BOX_IN_LIST( box_name, parent_type ) \
440 isom_remove_box_in_predefined_list( box_name, offsetof( parent_type, box_name##_list ) )
442 #define REMOVE_LIST_BOX_TEMPLATE( REMOVER, box_name, parent_type, eliminator ) \
445 lsmash_remove_list( box_name->list, eliminator ); \
446 REMOVER( box_name, parent_type ); \
449 #define REMOVE_LIST_BOX( ... ) CALL_FUNC_DEFAULT_ARGS( REMOVE_LIST_BOX, __VA_ARGS__ )
450 #define REMOVE_LIST_BOX_3( box_name, parent_type, eliminator ) \
451 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX, box_name, parent_type, eliminator )
452 #define REMOVE_LIST_BOX_2( box_name, parent_type ) \
453 REMOVE_LIST_BOX_3( box_name, parent_type, NULL )
455 #define REMOVE_LIST_BOX_IN_LIST( box_name, parent_type ) \
456 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX_IN_LIST, box_name, parent_type, NULL )
458 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVER, box_name, ... ) \
459 static void isom_remove_##box_name( isom_##box_name##_t *box_name ) \
463 REMOVER( box_name, __VA_ARGS__ ); \
466 #define DEFINE_SIMPLE_BOX_REMOVER( func_name, ... ) \
467 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX, __VA_ARGS__ )
469 #define DEFINE_SIMPLE_LIST_BOX_REMOVER( func_name, ... ) \
470 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX, __VA_ARGS__ )
472 #define DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( func_name, ... ) \
473 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX_IN_LIST, __VA_ARGS__ )
475 #define DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( func_name, ... ) \
476 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX_IN_LIST, __VA_ARGS__ )
478 static void isom_remove_predefined_box( void *opaque_box
, size_t offset_of_box
)
480 assert( opaque_box
);
481 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
484 isom_box_t
**p
= (isom_box_t
**)(((int8_t *)box
->parent
) + offset_of_box
);
490 /* We always free boxes through the extension list of the parent box.
491 * Therefore, don't free boxes through any list other than the extension list. */
492 static void isom_remove_box_in_predefined_list( void *opaque_box
, size_t offset_of_list
)
494 assert( opaque_box
);
495 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
498 lsmash_entry_list_t
*list
= (lsmash_entry_list_t
*)(((int8_t *)box
->parent
) + offset_of_list
);
500 for( lsmash_entry_t
*entry
= list
->head
; entry
; entry
= entry
->next
)
501 if( box
== entry
->data
)
503 /* We don't free this box here.
504 * Because of freeing an entry of the list here, don't pass the list to free this box.
507 lsmash_remove_entry_direct( list
, entry
, NULL
);
513 /* Remove a box by the pointer containing its address.
514 * In addition, remove from the extension list of the parent box if possible.
515 * Don't call this function within a function freeing one or more entries of any extension list because of double free.
516 * Basically, don't use this function as a callback function. */
517 void isom_remove_box_by_itself( void *opaque_box
)
521 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
524 isom_box_t
*parent
= box
->parent
;
525 for( lsmash_entry_t
*entry
= parent
->extensions
.head
; entry
; entry
= entry
->next
)
526 if( box
== entry
->data
)
528 /* Free the corresponding entry here, therefore don't call this function as a callback function
529 * if a function frees the same entry later and calls this function. */
530 lsmash_remove_entry_direct( &parent
->extensions
, entry
, isom_remove_extension_box
);
534 isom_remove_extension_box( box
);
537 void isom_remove_unknown_box( isom_unknown_box_t
*unknown_box
)
541 lsmash_free( unknown_box
->unknown_field
);
544 static void isom_remove_file( lsmash_file_t
*file
)
548 #ifdef LSMASH_DEMUXER_ENABLED
549 isom_remove_print_funcs( file
);
550 isom_remove_timelines( file
);
552 lsmash_free( file
->compatible_brands
);
553 lsmash_bs_cleanup( file
->bs
);
556 lsmash_remove_list( file
->fragment
->pool
, isom_remove_sample_pool
);
557 lsmash_free( file
->fragment
);
559 REMOVE_BOX_IN_LIST( file
, lsmash_root_t
);
562 static void isom_remove_ftyp( isom_ftyp_t
*ftyp
)
566 lsmash_free( ftyp
->compatible_brands
);
567 REMOVE_BOX( ftyp
, lsmash_file_t
);
570 static void isom_remove_iods( isom_iods_t
*iods
)
574 mp4sys_remove_descriptor( iods
->OD
);
575 REMOVE_BOX( iods
, isom_moov_t
);
578 static void isom_remove_trak( isom_trak_t
*trak
)
584 isom_remove_sample_pool( trak
->cache
->chunk
.pool
);
585 lsmash_remove_list( trak
->cache
->roll
.pool
, NULL
);
586 lsmash_free( trak
->cache
->rap
);
587 lsmash_free( trak
->cache
->fragment
);
588 lsmash_free( trak
->cache
);
590 REMOVE_BOX_IN_LIST( trak
, isom_moov_t
);
593 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tkhd
, tkhd
, isom_trak_t
)
594 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_clef
, clef
, isom_tapt_t
)
595 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_prof
, prof
, isom_tapt_t
)
596 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enof
, enof
, isom_tapt_t
)
597 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tapt
, tapt
, isom_trak_t
)
598 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_edts
, edts
, isom_trak_t
)
599 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tref
, tref
, isom_trak_t
)
600 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_elst
, elst
, isom_edts_t
)
602 static void isom_remove_track_reference_type( isom_tref_type_t
*ref
)
606 lsmash_free( ref
->track_ID
);
607 isom_remove_box_in_predefined_list( ref
, offsetof( isom_tref_t
, ref_list
) );
610 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdhd
, mdhd
, isom_mdia_t
)
611 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_vmhd
, vmhd
, isom_minf_t
)
612 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_smhd
, smhd
, isom_minf_t
)
613 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_hmhd
, hmhd
, isom_minf_t
)
614 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_nmhd
, nmhd
, isom_minf_t
)
615 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmhd
, gmhd
, isom_minf_t
)
616 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmin
, gmin
, isom_gmhd_t
)
617 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_text
, text
, isom_gmhd_t
)
619 static void isom_remove_hdlr( isom_hdlr_t
*hdlr
)
623 lsmash_free( hdlr
->componentName
);
626 if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MDIA
) )
627 REMOVE_BOX( hdlr
, isom_mdia_t
);
628 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_META
)
629 || lsmash_check_box_type_identical( hdlr
->parent
->type
, QT_BOX_TYPE_META
) )
630 REMOVE_BOX( hdlr
, isom_meta_t
);
631 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MINF
) )
632 REMOVE_BOX( hdlr
, isom_minf_t
);
639 static void isom_remove_glbl( isom_glbl_t
*glbl
)
643 lsmash_free( glbl
->header_data
);
646 static void isom_remove_esds( isom_esds_t
*esds
)
650 mp4sys_remove_descriptor( esds
->ES
);
653 static void isom_remove_font_record( isom_font_record_t
*font_record
)
657 lsmash_free( font_record
->font_name
);
658 lsmash_free( font_record
);
660 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ftab
, ftab
, isom_tx3g_entry_t
, isom_remove_font_record
)
662 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_frma
, frma
, isom_wave_t
)
663 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enda
, enda
, isom_wave_t
)
664 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mp4a
, mp4a
, isom_wave_t
)
665 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_terminator
, terminator
, isom_wave_t
)
667 static void isom_remove_chan( isom_chan_t
*chan
)
671 lsmash_free( chan
->channelDescriptions
);
674 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stsd
, stsd
, isom_stbl_t
)
676 static void isom_remove_visual_description( isom_sample_entry_t
*description
)
678 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)description
;
679 lsmash_free( visual
->color_table
.array
);
680 isom_remove_box_in_predefined_list( visual
, offsetof( isom_stsd_t
, list
) );
683 static void isom_remove_audio_description( isom_sample_entry_t
*description
)
685 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
688 static void isom_remove_hint_description( isom_sample_entry_t
*description
)
690 isom_hint_entry_t
*hint
= (isom_hint_entry_t
*)description
;
691 lsmash_free( hint
->data
);
692 isom_remove_box_in_predefined_list( hint
, offsetof( isom_stsd_t
, list
) );
695 static void isom_remove_metadata_description( isom_sample_entry_t
*description
)
697 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
700 static void isom_remove_tx3g_description( isom_sample_entry_t
*description
)
702 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
705 static void isom_remove_qt_text_description( isom_sample_entry_t
*description
)
707 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)description
;
708 lsmash_free( text
->font_name
);
709 isom_remove_box_in_predefined_list( text
, offsetof( isom_stsd_t
, list
) );
712 static void isom_remove_mp4s_description( isom_sample_entry_t
*description
)
714 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
717 void isom_remove_sample_description( isom_sample_entry_t
*sample
)
721 lsmash_codec_type_t sample_type
= sample
->type
;
722 if( lsmash_check_box_type_identical( sample_type
, LSMASH_CODEC_TYPE_RAW
) )
724 if( sample
->manager
& LSMASH_VIDEO_DESCRIPTION
)
726 isom_remove_visual_description( sample
);
729 else if( sample
->manager
& LSMASH_AUDIO_DESCRIPTION
)
731 isom_remove_audio_description( sample
);
735 static struct description_remover_table_tag
737 lsmash_codec_type_t type
;
738 void (*func
)( isom_sample_entry_t
* );
739 } description_remover_table
[160] = { { LSMASH_CODEC_TYPE_INITIALIZER
, NULL
} };
740 if( !description_remover_table
[0].func
)
742 /* Initialize the table. */
744 #define ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( type, func ) \
745 description_remover_table[i++] = (struct description_remover_table_tag){ type, func }
746 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, isom_remove_visual_description
);
747 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, isom_remove_visual_description
);
748 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, isom_remove_visual_description
);
749 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, isom_remove_visual_description
);
750 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, isom_remove_visual_description
);
751 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, isom_remove_visual_description
);
752 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, isom_remove_visual_description
);
753 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, isom_remove_visual_description
);
754 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, isom_remove_visual_description
);
755 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, isom_remove_visual_description
);
756 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, isom_remove_visual_description
);
757 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
758 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, isom_remove_visual_description
);
759 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, isom_remove_visual_description
);
760 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, isom_remove_visual_description
);
761 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, isom_remove_visual_description
);
762 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, isom_remove_visual_description
);
763 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, isom_remove_visual_description
);
764 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, isom_remove_visual_description
);
765 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, isom_remove_visual_description
);
766 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, isom_remove_visual_description
);
767 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, isom_remove_visual_description
);
768 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, isom_remove_visual_description
);
769 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, isom_remove_visual_description
);
770 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, isom_remove_visual_description
);
771 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, isom_remove_visual_description
);
772 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, isom_remove_visual_description
);
773 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, isom_remove_visual_description
);
774 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, isom_remove_visual_description
);
775 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, isom_remove_visual_description
);
776 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, isom_remove_visual_description
);
777 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, isom_remove_visual_description
);
778 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, isom_remove_visual_description
);
779 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, isom_remove_visual_description
);
780 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, isom_remove_visual_description
);
781 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, isom_remove_visual_description
);
782 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, isom_remove_visual_description
);
783 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, isom_remove_visual_description
);
784 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, isom_remove_visual_description
);
785 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, isom_remove_visual_description
);
786 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
787 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, isom_remove_visual_description
);
788 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, isom_remove_visual_description
);
789 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, isom_remove_visual_description
);
790 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, isom_remove_visual_description
);
791 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, isom_remove_visual_description
);
792 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, isom_remove_visual_description
);
793 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, isom_remove_visual_description
);
794 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, isom_remove_visual_description
);
795 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, isom_remove_visual_description
);
796 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, isom_remove_visual_description
);
797 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, isom_remove_visual_description
);
798 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, isom_remove_visual_description
);
799 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, isom_remove_visual_description
);
800 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, isom_remove_visual_description
);
801 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, isom_remove_visual_description
);
802 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, isom_remove_visual_description
);
803 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, isom_remove_visual_description
);
804 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, isom_remove_visual_description
);
805 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, isom_remove_visual_description
);
806 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, isom_remove_visual_description
);
807 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, isom_remove_visual_description
);
808 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, isom_remove_visual_description
);
809 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, isom_remove_visual_description
);
810 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, isom_remove_visual_description
);
811 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, isom_remove_visual_description
);
812 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, isom_remove_visual_description
);
813 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, isom_remove_visual_description
);
814 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, isom_remove_visual_description
);
815 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, isom_remove_visual_description
);
816 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, isom_remove_visual_description
);
817 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, isom_remove_visual_description
);
818 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, isom_remove_visual_description
);
819 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, isom_remove_visual_description
);
820 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, isom_remove_visual_description
);
821 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, isom_remove_visual_description
);
822 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
823 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, isom_remove_audio_description
);
824 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, isom_remove_audio_description
);
825 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, isom_remove_audio_description
);
826 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, isom_remove_audio_description
);
827 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, isom_remove_audio_description
);
828 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, isom_remove_audio_description
);
829 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, isom_remove_audio_description
);
830 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, isom_remove_audio_description
);
831 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, isom_remove_audio_description
);
832 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, isom_remove_audio_description
);
833 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, isom_remove_audio_description
);
834 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, isom_remove_audio_description
);
835 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, isom_remove_audio_description
);
836 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
837 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, isom_remove_audio_description
);
838 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, isom_remove_audio_description
);
839 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, isom_remove_audio_description
);
840 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, isom_remove_audio_description
);
841 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, isom_remove_audio_description
);
842 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, isom_remove_audio_description
);
843 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, isom_remove_audio_description
);
844 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, isom_remove_audio_description
);
845 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, isom_remove_audio_description
);
846 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, isom_remove_audio_description
);
847 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, isom_remove_audio_description
);
848 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, isom_remove_audio_description
);
849 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, isom_remove_audio_description
);
850 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, isom_remove_audio_description
);
851 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, isom_remove_audio_description
);
852 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
853 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_FDP_HINT
, isom_remove_hint_description
);
854 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M2TS_HINT
, isom_remove_hint_description
);
855 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PM2T_HINT
, isom_remove_hint_description
);
856 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PRTP_HINT
, isom_remove_hint_description
);
857 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RM2T_HINT
, isom_remove_hint_description
);
858 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RRTP_HINT
, isom_remove_hint_description
);
859 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RSRP_HINT
, isom_remove_hint_description
);
860 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RTP_HINT
, isom_remove_hint_description
);
861 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SM2T_HINT
, isom_remove_hint_description
);
862 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SRTP_HINT
, isom_remove_hint_description
);
863 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_IXSE_META
, isom_remove_metadata_description
);
864 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METT_META
, isom_remove_metadata_description
);
865 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METX_META
, isom_remove_metadata_description
);
866 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLIX_META
, isom_remove_metadata_description
);
867 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_OKSD_META
, isom_remove_metadata_description
);
868 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVCM_META
, isom_remove_metadata_description
);
869 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TEXT_META
, isom_remove_metadata_description
);
870 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_URIM_META
, isom_remove_metadata_description
);
871 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_XML_META
, isom_remove_metadata_description
);
872 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, isom_remove_tx3g_description
);
873 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, isom_remove_qt_text_description
);
874 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, isom_remove_mp4s_description
);
875 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
877 for( int i
= 0; description_remover_table
[i
].func
; i
++ )
878 if( lsmash_check_codec_type_identical( sample_type
, description_remover_table
[i
].type
) )
880 description_remover_table
[i
].func( sample
);
885 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stts
, stts
, isom_stbl_t
)
886 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ctts
, ctts
, isom_stbl_t
)
887 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_cslg
, cslg
, isom_stbl_t
)
888 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsc
, stsc
, isom_stbl_t
)
889 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsz
, stsz
, isom_stbl_t
)
890 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stss
, stss
, isom_stbl_t
)
891 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stps
, stps
, isom_stbl_t
)
892 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stco
, stco
, isom_stbl_t
)
894 static void isom_remove_sdtp( isom_sdtp_t
*sdtp
)
898 lsmash_remove_list( sdtp
->list
, NULL
);
901 if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
902 REMOVE_BOX( sdtp
, isom_stbl_t
);
903 else if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
904 REMOVE_BOX( sdtp
, isom_traf_t
);
911 static void isom_remove_sgpd( isom_sgpd_t
*sgpd
)
915 lsmash_remove_list( sgpd
->list
, NULL
);
918 if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
919 REMOVE_BOX_IN_LIST( sgpd
, isom_stbl_t
);
920 else if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
921 REMOVE_BOX_IN_LIST( sgpd
, isom_traf_t
);
928 static void isom_remove_sbgp( isom_sbgp_t
*sbgp
)
932 lsmash_remove_list( sbgp
->list
, NULL
);
935 if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
936 REMOVE_BOX_IN_LIST( sbgp
, isom_stbl_t
);
937 else if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
938 REMOVE_BOX_IN_LIST( sbgp
, isom_traf_t
);
945 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stbl
, stbl
, isom_minf_t
)
947 static void isom_remove_dref_entry( isom_dref_entry_t
*data_entry
)
951 lsmash_free( data_entry
->name
);
952 lsmash_free( data_entry
->location
);
953 isom_remove_box_in_predefined_list( data_entry
, offsetof( isom_dref_t
, list
) );
956 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dref
, dref
, isom_dinf_t
)
957 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dinf
, dinf
, isom_minf_t
)
958 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_minf
, minf
, isom_mdia_t
)
959 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdia
, mdia
, isom_trak_t
)
961 static void isom_remove_chpl_entry( isom_chpl_entry_t
*data
)
965 lsmash_free( data
->chapter_name
);
968 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_chpl
, chpl
, isom_udta_t
, isom_remove_chpl_entry
)
970 static void isom_remove_keys_entry( isom_keys_entry_t
*data
)
974 lsmash_free( data
->key_value
);
977 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_keys
, keys
, isom_meta_t
, isom_remove_keys_entry
)
979 static void isom_remove_mean( isom_mean_t
*mean
)
983 lsmash_free( mean
->meaning_string
);
984 REMOVE_BOX( mean
, isom_metaitem_t
);
987 static void isom_remove_name( isom_name_t
*name
)
991 lsmash_free( name
->name
);
992 REMOVE_BOX( name
, isom_metaitem_t
);
995 static void isom_remove_data( isom_data_t
*data
)
999 lsmash_free( data
->value
);
1000 REMOVE_BOX( data
, isom_metaitem_t
);
1003 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_metaitem
, metaitem
, isom_ilst_t
)
1004 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_ilst
, ilst
, isom_meta_t
)
1006 static void isom_remove_meta( isom_meta_t
*meta
)
1012 if( lsmash_check_box_type_identical( meta
->parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
1013 REMOVE_BOX( meta
, lsmash_file_t
);
1014 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1015 REMOVE_BOX( meta
, isom_moov_t
);
1016 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1017 REMOVE_BOX( meta
, isom_trak_t
);
1018 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1019 REMOVE_BOX( meta
, isom_udta_t
);
1026 static void isom_remove_cprt( isom_cprt_t
*cprt
)
1030 lsmash_free( cprt
->notice
);
1031 REMOVE_BOX_IN_LIST( cprt
, isom_udta_t
);
1034 static void isom_remove_udta( isom_udta_t
*udta
)
1040 if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1041 REMOVE_BOX( udta
, isom_moov_t
);
1042 else if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1043 REMOVE_BOX( udta
, isom_trak_t
);
1050 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_WLOC
, WLOC
, isom_udta_t
)
1051 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_LOOP
, LOOP
, isom_udta_t
)
1052 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_SelO
, SelO
, isom_udta_t
)
1053 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_AllF
, AllF
, isom_udta_t
)
1055 static void isom_remove_ctab( isom_ctab_t
*ctab
)
1059 lsmash_free( ctab
->color_table
.array
);
1060 if( ctab
->parent
&& lsmash_check_box_type_identical( ctab
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1061 REMOVE_BOX( ctab
, isom_moov_t
);
1064 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvex
, mvex
, isom_moov_t
)
1065 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvhd
, mvhd
, isom_moov_t
)
1066 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mehd
, mehd
, isom_mvex_t
)
1067 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_trex
, trex
, isom_mvex_t
)
1068 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_moov
, moov
, lsmash_file_t
)
1069 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdat
, mdat
, lsmash_file_t
)
1070 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfhd
, mfhd
, isom_moof_t
)
1071 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfhd
, tfhd
, isom_traf_t
)
1072 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfdt
, tfdt
, isom_traf_t
)
1074 static void isom_remove_trun( isom_trun_t
*trun
)
1078 lsmash_remove_list( trun
->optional
, NULL
);
1079 REMOVE_BOX_IN_LIST( trun
, isom_traf_t
);
1082 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_traf
, traf
, isom_moof_t
)
1083 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_moof
, moof
, lsmash_file_t
)
1085 static void isom_remove_free( isom_free_t
*skip
)
1089 lsmash_free( skip
->data
);
1090 isom_remove_predefined_box( skip
, offsetof( lsmash_file_t
, free
) );
1092 #define isom_remove_skip isom_remove_free
1094 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfra
, mfra
, lsmash_file_t
)
1095 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfro
, mfro
, isom_mfra_t
)
1096 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_tfra
, tfra
, isom_mfra_t
)
1097 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_sidx
, sidx
, lsmash_file_t
)
1099 static void isom_remove_styp( isom_styp_t
*styp
)
1103 lsmash_free( styp
->compatible_brands
);
1104 REMOVE_BOX_IN_LIST( styp
, lsmash_file_t
);
1107 /* box size updater */
1108 uint64_t isom_update_box_size( void *opaque_box
)
1110 assert( opaque_box
);
1111 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
1112 if( box
->manager
& LSMASH_WRITTEN_BOX
)
1113 /* No need to calculate the size of this box since the size is already decided and fixed. */
1118 /* Calculate the size of this box excluding its children with a fake bytestream writer. */
1120 lsmash_bs_t fake_bs
= { NULL
};
1121 if( box
->write( &fake_bs
, box
) == 0 )
1122 size
= lsmash_bs_get_valid_data_size( &fake_bs
);
1124 /* Calculate the size of the children if no error. */
1125 if( size
>= ISOM_BASEBOX_COMMON_SIZE
)
1127 for( lsmash_entry_t
*entry
= box
->extensions
.head
; entry
; entry
= entry
->next
)
1129 size
+= isom_update_box_size( entry
->data
);
1130 /* Check large size. */
1131 if( size
> UINT32_MAX
)
1135 /* TODO: add error handling. */
1142 /* box adding functions */
1143 #define ATTACH_EXACTLY_ONE_BOX_TO_PARENT( box_name, parent_type ) \
1146 isom_box_t **p = (isom_box_t **)(((int8_t *)box_name->parent) \
1147 + offsetof( parent_type, box_name )); \
1149 *p = (isom_box_t *)box_name; \
1152 #define INIT_BOX_COMMON0( box_name, parent, box_type, precedence ) \
1153 const isom_extension_destructor_t isom_remove_##box_name = NULL; \
1154 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1155 #define INIT_BOX_COMMON1( box_name, parent, box_type, precedence ) \
1156 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1158 #define CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1161 isom_##box_name##_t *box_name = lsmash_malloc_zero( sizeof(isom_##box_name##_t) ); \
1164 INIT_BOX_COMMON ## has_destructor( box_name, parent, box_type, precedence ); \
1165 if( isom_add_box_to_extension_list( parent, box_name ) < 0 ) \
1167 lsmash_free( box_name ); \
1170 #define CREATE_LIST_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1171 CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ); \
1172 box_name->list = lsmash_create_entry_list(); \
1173 if( !box_name->list ) \
1175 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1179 #define ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1180 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1181 if( !(parent)->box_name ) \
1182 (parent)->box_name = box_name
1183 #define ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1184 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1185 if( lsmash_add_entry( &(parent)->box_name##_list, box_name ) < 0 ) \
1187 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1191 #define ADD_BOX( box_name, parent, box_type, precedence ) \
1192 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1193 #define ADD_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1194 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1195 #define ADD_LIST_BOX( box_name, parent, box_type, precedence ) \
1196 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1197 #define ADD_LIST_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1198 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1200 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ... ) CALL_FUNC_DEFAULT_ARGS( DEFINE_SIMPLE_BOX_ADDER_TEMPLATE, __VA_ARGS__ )
1201 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, parent_type ) \
1202 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1204 ADDER( box_name, parent_name, box_type, precedence ); \
1207 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5( ADDER, box_name, parent_name, box_type, precedence ) \
1208 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, isom_##parent_name##_t )
1210 #define DEFINE_SIMPLE_BOX_ADDER( func_name, ... ) \
1211 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX, __VA_ARGS__ )
1212 #define DEFINE_SIMPLE_BOX_IN_LIST_ADDER( func_name, ... ) \
1213 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX_IN_LIST, __VA_ARGS__ )
1214 #define DEFINE_SIMPLE_LIST_BOX_ADDER( func_name, ... ) \
1215 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_LIST_BOX, __VA_ARGS__ )
1217 #define DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( func_name, box_name, parent_name, box_type, precedence, has_destructor, parent_type ) \
1218 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1220 CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ); \
1224 lsmash_file_t
*isom_add_file( lsmash_root_t
*root
)
1226 lsmash_file_t
*file
= lsmash_malloc_zero( sizeof(lsmash_file_t
) );
1229 file
->class = &lsmash_box_class
;
1232 file
->parent
= (isom_box_t
*)root
;
1233 file
->destruct
= (isom_extension_destructor_t
)isom_remove_file
;
1235 file
->type
= LSMASH_BOX_TYPE_UNSPECIFIED
;
1236 if( isom_add_box_to_extension_list( root
, file
) < 0 )
1238 lsmash_free( file
);
1241 if( lsmash_add_entry( &root
->file_list
, file
) < 0 )
1243 lsmash_remove_entry_tail( &root
->extensions
, isom_remove_file
);
1249 isom_tref_type_t
*isom_add_track_reference_type( isom_tref_t
*tref
, isom_track_reference_type type
)
1253 isom_tref_type_t
*ref
= lsmash_malloc_zero( sizeof(isom_tref_type_t
) );
1256 /* Initialize common fields. */
1257 ref
->root
= tref
->root
;
1258 ref
->file
= tref
->file
;
1259 ref
->parent
= (isom_box_t
*)tref
;
1261 ref
->type
= lsmash_form_iso_box_type( type
);
1262 ref
->precedence
= LSMASH_BOX_PRECEDENCE_ISOM_TREF_TYPE
;
1263 ref
->destruct
= (isom_extension_destructor_t
)isom_remove_track_reference_type
;
1264 isom_set_box_writer( (isom_box_t
*)ref
);
1265 if( isom_add_box_to_extension_list( tref
, ref
) < 0 )
1270 if( lsmash_add_entry( &tref
->ref_list
, ref
) < 0 )
1272 lsmash_remove_entry_tail( &tref
->extensions
, isom_remove_track_reference_type
);
1278 DEFINE_SIMPLE_BOX_ADDER( isom_add_terminator
, terminator
, wave
, QT_BOX_TYPE_TERMINATOR
, LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
)
1279 DEFINE_SIMPLE_BOX_ADDER( isom_add_frma
, frma
, wave
, QT_BOX_TYPE_FRMA
, LSMASH_BOX_PRECEDENCE_QTFF_FRMA
)
1280 DEFINE_SIMPLE_BOX_ADDER( isom_add_enda
, enda
, wave
, QT_BOX_TYPE_ENDA
, LSMASH_BOX_PRECEDENCE_QTFF_ENDA
)
1281 DEFINE_SIMPLE_BOX_ADDER( isom_add_mp4a
, mp4a
, wave
, QT_BOX_TYPE_MP4A
, LSMASH_BOX_PRECEDENCE_QTFF_MP4A
)
1282 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ftab
, ftab
, tx3g
, ISOM_BOX_TYPE_FTAB
, LSMASH_BOX_PRECEDENCE_ISOM_FTAB
, isom_tx3g_entry_t
)
1283 DEFINE_SIMPLE_BOX_ADDER( isom_add_ftyp
, ftyp
, file
, ISOM_BOX_TYPE_FTYP
, LSMASH_BOX_PRECEDENCE_ISOM_FTYP
, lsmash_file_t
)
1284 DEFINE_SIMPLE_BOX_ADDER( isom_add_moov
, moov
, file
, ISOM_BOX_TYPE_MOOV
, LSMASH_BOX_PRECEDENCE_ISOM_MOOV
, lsmash_file_t
)
1285 DEFINE_SIMPLE_BOX_ADDER( isom_add_mvhd
, mvhd
, moov
, ISOM_BOX_TYPE_MVHD
, LSMASH_BOX_PRECEDENCE_ISOM_MVHD
)
1286 DEFINE_SIMPLE_BOX_ADDER( isom_add_iods
, iods
, moov
, ISOM_BOX_TYPE_IODS
, LSMASH_BOX_PRECEDENCE_ISOM_IODS
)
1288 isom_ctab_t
*isom_add_ctab( void *parent_box
)
1290 /* According to QuickTime File Format Specification, this box is placed inside Movie Box if present.
1291 * However, sometimes this box occurs inside an image description entry or the end of Sample Description Box. */
1294 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1295 CREATE_BOX( ctab
, parent
, QT_BOX_TYPE_CTAB
, LSMASH_BOX_PRECEDENCE_QTFF_CTAB
, 1 );
1296 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1297 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( ctab
, isom_moov_t
);
1301 isom_trak_t
*isom_add_trak( isom_moov_t
*moov
)
1303 if( !moov
|| !moov
->file
)
1305 CREATE_BOX( trak
, moov
, ISOM_BOX_TYPE_TRAK
, LSMASH_BOX_PRECEDENCE_ISOM_TRAK
, 1 );
1306 isom_fragment_t
*fragment
= NULL
;
1307 isom_cache_t
*cache
= lsmash_malloc_zero( sizeof(isom_cache_t
) );
1310 if( moov
->file
->fragment
)
1312 fragment
= lsmash_malloc_zero( sizeof(isom_fragment_t
) );
1315 cache
->fragment
= fragment
;
1317 if( lsmash_add_entry( &moov
->trak_list
, trak
) < 0 )
1319 trak
->cache
= cache
;
1322 lsmash_free( fragment
);
1323 lsmash_free( cache
);
1324 lsmash_remove_entry_tail( &moov
->extensions
, isom_remove_trak
);
1328 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tkhd
, tkhd
, trak
, ISOM_BOX_TYPE_TKHD
, LSMASH_BOX_PRECEDENCE_ISOM_TKHD
)
1329 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tapt
, tapt
, trak
, QT_BOX_TYPE_TAPT
, LSMASH_BOX_PRECEDENCE_QTFF_TAPT
)
1330 DEFINE_SIMPLE_BOX_ADDER ( isom_add_clef
, clef
, tapt
, QT_BOX_TYPE_CLEF
, LSMASH_BOX_PRECEDENCE_QTFF_CLEF
)
1331 DEFINE_SIMPLE_BOX_ADDER ( isom_add_prof
, prof
, tapt
, QT_BOX_TYPE_PROF
, LSMASH_BOX_PRECEDENCE_QTFF_PROF
)
1332 DEFINE_SIMPLE_BOX_ADDER ( isom_add_enof
, enof
, tapt
, QT_BOX_TYPE_ENOF
, LSMASH_BOX_PRECEDENCE_QTFF_ENOF
)
1333 DEFINE_SIMPLE_BOX_ADDER ( isom_add_edts
, edts
, trak
, ISOM_BOX_TYPE_EDTS
, LSMASH_BOX_PRECEDENCE_ISOM_EDTS
)
1334 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_elst
, elst
, edts
, ISOM_BOX_TYPE_ELST
, LSMASH_BOX_PRECEDENCE_ISOM_ELST
)
1335 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tref
, tref
, trak
, ISOM_BOX_TYPE_TREF
, LSMASH_BOX_PRECEDENCE_ISOM_TREF
)
1336 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdia
, mdia
, trak
, ISOM_BOX_TYPE_MDIA
, LSMASH_BOX_PRECEDENCE_ISOM_MDIA
)
1337 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdhd
, mdhd
, mdia
, ISOM_BOX_TYPE_MDHD
, LSMASH_BOX_PRECEDENCE_ISOM_MDHD
)
1339 isom_hdlr_t
*isom_add_hdlr( void *parent_box
)
1343 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1344 CREATE_BOX( hdlr
, parent
, ISOM_BOX_TYPE_HDLR
, LSMASH_BOX_PRECEDENCE_ISOM_HDLR
, 1 );
1345 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
) )
1346 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_mdia_t
);
1347 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1348 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1349 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_meta_t
);
1350 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1351 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_minf_t
);
1357 DEFINE_SIMPLE_BOX_ADDER( isom_add_minf
, minf
, mdia
, ISOM_BOX_TYPE_MINF
, LSMASH_BOX_PRECEDENCE_ISOM_MINF
)
1358 DEFINE_SIMPLE_BOX_ADDER( isom_add_vmhd
, vmhd
, minf
, ISOM_BOX_TYPE_VMHD
, LSMASH_BOX_PRECEDENCE_ISOM_VMHD
)
1359 DEFINE_SIMPLE_BOX_ADDER( isom_add_smhd
, smhd
, minf
, ISOM_BOX_TYPE_SMHD
, LSMASH_BOX_PRECEDENCE_ISOM_SMHD
)
1360 DEFINE_SIMPLE_BOX_ADDER( isom_add_hmhd
, hmhd
, minf
, ISOM_BOX_TYPE_HMHD
, LSMASH_BOX_PRECEDENCE_ISOM_HMHD
)
1361 DEFINE_SIMPLE_BOX_ADDER( isom_add_nmhd
, nmhd
, minf
, ISOM_BOX_TYPE_NMHD
, LSMASH_BOX_PRECEDENCE_ISOM_NMHD
)
1362 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmhd
, gmhd
, minf
, QT_BOX_TYPE_GMHD
, LSMASH_BOX_PRECEDENCE_QTFF_GMHD
)
1363 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmin
, gmin
, gmhd
, QT_BOX_TYPE_GMIN
, LSMASH_BOX_PRECEDENCE_QTFF_GMIN
)
1364 DEFINE_SIMPLE_BOX_ADDER( isom_add_text
, text
, gmhd
, QT_BOX_TYPE_TEXT
, LSMASH_BOX_PRECEDENCE_QTFF_TEXT
)
1366 isom_dinf_t
*isom_add_dinf( void *parent_box
)
1370 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1371 CREATE_BOX( dinf
, parent
, ISOM_BOX_TYPE_DINF
, LSMASH_BOX_PRECEDENCE_ISOM_DINF
, 1 );
1372 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1373 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_minf_t
);
1374 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1375 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1376 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_meta_t
);
1382 isom_dref_entry_t
*isom_add_dref_entry( isom_dref_t
*dref
)
1386 isom_dref_entry_t
*data
= lsmash_malloc_zero( sizeof(isom_dref_entry_t
) );
1389 isom_init_box_common( data
, dref
, ISOM_BOX_TYPE_URL
, LSMASH_BOX_PRECEDENCE_ISOM_URL
, isom_remove_dref_entry
);
1390 if( isom_add_box_to_extension_list( dref
, data
) < 0 )
1392 lsmash_free( data
);
1395 if( lsmash_add_entry( &dref
->list
, data
) < 0 )
1397 lsmash_remove_entry_tail( &dref
->extensions
, isom_remove_dref_entry
);
1403 DEFINE_SIMPLE_BOX_ADDER( isom_add_dref
, dref
, dinf
, ISOM_BOX_TYPE_DREF
, LSMASH_BOX_PRECEDENCE_ISOM_DREF
)
1404 DEFINE_SIMPLE_BOX_ADDER( isom_add_stbl
, stbl
, minf
, ISOM_BOX_TYPE_STBL
, LSMASH_BOX_PRECEDENCE_ISOM_STBL
)
1405 DEFINE_SIMPLE_BOX_ADDER( isom_add_stsd
, stsd
, stbl
, ISOM_BOX_TYPE_STSD
, LSMASH_BOX_PRECEDENCE_ISOM_STSD
)
1407 static int isom_add_sample_description_entry
1411 void (*destructor
)( isom_sample_entry_t
* )
1414 if( isom_add_box_to_extension_list( stsd
, description
) < 0 )
1416 lsmash_free( description
);
1419 if( lsmash_add_entry( &stsd
->list
, description
) < 0 )
1421 lsmash_remove_entry_tail( &stsd
->extensions
, destructor
);
1427 isom_visual_entry_t
*isom_add_visual_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1430 isom_visual_entry_t
*visual
= lsmash_malloc_zero( sizeof(isom_visual_entry_t
) );
1433 isom_init_box_common( visual
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_visual_description
);
1434 visual
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1435 return isom_add_sample_description_entry( stsd
, visual
, isom_remove_visual_description
) ? NULL
: visual
;
1438 isom_audio_entry_t
*isom_add_audio_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1441 isom_audio_entry_t
*audio
= lsmash_malloc_zero( sizeof(isom_audio_entry_t
) );
1444 isom_init_box_common( audio
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_audio_description
);
1445 audio
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1446 return isom_add_sample_description_entry( stsd
, audio
, isom_remove_audio_description
) ? NULL
: audio
;
1449 isom_qt_text_entry_t
*isom_add_qt_text_description( isom_stsd_t
*stsd
)
1452 isom_qt_text_entry_t
*text
= lsmash_malloc_zero( sizeof(isom_qt_text_entry_t
) );
1455 isom_init_box_common( text
, stsd
, QT_CODEC_TYPE_TEXT_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_qt_text_description
);
1456 return isom_add_sample_description_entry( stsd
, text
, isom_remove_qt_text_description
) ? NULL
: text
;
1459 isom_tx3g_entry_t
*isom_add_tx3g_description( isom_stsd_t
*stsd
)
1462 isom_tx3g_entry_t
*tx3g
= lsmash_malloc_zero( sizeof(isom_tx3g_entry_t
) );
1465 isom_init_box_common( tx3g
, stsd
, ISOM_CODEC_TYPE_TX3G_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_tx3g_description
);
1466 return isom_add_sample_description_entry( stsd
, tx3g
, isom_remove_tx3g_description
) ? NULL
: tx3g
;
1469 isom_esds_t
*isom_add_esds( void *parent_box
)
1471 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1472 int is_qt
= lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
);
1473 lsmash_box_type_t box_type
= is_qt
? QT_BOX_TYPE_ESDS
: ISOM_BOX_TYPE_ESDS
;
1474 uint64_t precedence
= is_qt
? LSMASH_BOX_PRECEDENCE_QTFF_ESDS
: LSMASH_BOX_PRECEDENCE_ISOM_ESDS
;
1475 CREATE_BOX( esds
, parent
, box_type
, precedence
, 1 );
1479 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_glbl
, glbl
, parent_box
, QT_BOX_TYPE_GLBL
, LSMASH_BOX_PRECEDENCE_QTFF_GLBL
, 1, void )
1480 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_clap
, clap
, visual
, ISOM_BOX_TYPE_CLAP
, LSMASH_BOX_PRECEDENCE_ISOM_CLAP
, 0, isom_visual_entry_t
)
1481 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_pasp
, pasp
, visual
, ISOM_BOX_TYPE_PASP
, LSMASH_BOX_PRECEDENCE_ISOM_PASP
, 0, isom_visual_entry_t
)
1482 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_colr
, colr
, visual
, ISOM_BOX_TYPE_COLR
, LSMASH_BOX_PRECEDENCE_ISOM_COLR
, 0, isom_visual_entry_t
)
1483 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_gama
, gama
, visual
, QT_BOX_TYPE_GAMA
, LSMASH_BOX_PRECEDENCE_QTFF_GAMA
, 0, isom_visual_entry_t
)
1484 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_fiel
, fiel
, visual
, QT_BOX_TYPE_FIEL
, LSMASH_BOX_PRECEDENCE_QTFF_FIEL
, 0, isom_visual_entry_t
)
1485 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_cspc
, cspc
, visual
, QT_BOX_TYPE_CSPC
, LSMASH_BOX_PRECEDENCE_QTFF_CSPC
, 0, isom_visual_entry_t
)
1486 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_sgbt
, sgbt
, visual
, QT_BOX_TYPE_SGBT
, LSMASH_BOX_PRECEDENCE_QTFF_SGBT
, 0, isom_visual_entry_t
)
1487 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_stsl
, stsl
, visual
, ISOM_BOX_TYPE_STSL
, LSMASH_BOX_PRECEDENCE_ISOM_STSL
, 0, isom_visual_entry_t
)
1488 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_btrt
, btrt
, visual
, ISOM_BOX_TYPE_BTRT
, LSMASH_BOX_PRECEDENCE_ISOM_BTRT
, 0, isom_visual_entry_t
)
1489 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_wave
, wave
, audio
, QT_BOX_TYPE_WAVE
, LSMASH_BOX_PRECEDENCE_QTFF_WAVE
, 0, isom_audio_entry_t
)
1490 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_chan
, chan
, audio
, QT_BOX_TYPE_CHAN
, LSMASH_BOX_PRECEDENCE_QTFF_CHAN
, 1, isom_audio_entry_t
)
1491 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_srat
, srat
, audio
, ISOM_BOX_TYPE_SRAT
, LSMASH_BOX_PRECEDENCE_ISOM_SRAT
, 0, isom_audio_entry_t
)
1493 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stts
, stts
, stbl
, ISOM_BOX_TYPE_STTS
, LSMASH_BOX_PRECEDENCE_ISOM_STTS
)
1494 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ctts
, ctts
, stbl
, ISOM_BOX_TYPE_CTTS
, LSMASH_BOX_PRECEDENCE_ISOM_CTTS
)
1495 DEFINE_SIMPLE_BOX_ADDER ( isom_add_cslg
, cslg
, stbl
, ISOM_BOX_TYPE_CSLG
, LSMASH_BOX_PRECEDENCE_ISOM_CSLG
)
1496 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stsc
, stsc
, stbl
, ISOM_BOX_TYPE_STSC
, LSMASH_BOX_PRECEDENCE_ISOM_STSC
)
1497 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. */
1498 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stss
, stss
, stbl
, ISOM_BOX_TYPE_STSS
, LSMASH_BOX_PRECEDENCE_ISOM_STSS
)
1499 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stps
, stps
, stbl
, QT_BOX_TYPE_STPS
, LSMASH_BOX_PRECEDENCE_QTFF_STPS
)
1501 isom_stco_t
*isom_add_stco( isom_stbl_t
*stbl
)
1503 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_STCO
, LSMASH_BOX_PRECEDENCE_ISOM_STCO
);
1504 stco
->large_presentation
= 0;
1508 isom_stco_t
*isom_add_co64( isom_stbl_t
*stbl
)
1510 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_CO64
, LSMASH_BOX_PRECEDENCE_ISOM_CO64
);
1511 stco
->large_presentation
= 1;
1515 isom_sdtp_t
*isom_add_sdtp( isom_box_t
*parent
)
1519 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1521 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1522 ADD_LIST_BOX( sdtp
, stbl
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1525 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1527 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1528 ADD_LIST_BOX( sdtp
, traf
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1535 isom_sgpd_t
*isom_add_sgpd( void *parent_box
)
1539 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1540 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1542 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1543 ADD_LIST_BOX_IN_LIST( sgpd
, stbl
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1546 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1548 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1549 ADD_LIST_BOX_IN_LIST( sgpd
, traf
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1556 isom_sbgp_t
*isom_add_sbgp( void *parent_box
)
1560 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1561 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1563 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1564 ADD_LIST_BOX_IN_LIST( sbgp
, stbl
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1567 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1569 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1570 ADD_LIST_BOX_IN_LIST( sbgp
, traf
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1577 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_chpl
, chpl
, udta
, ISOM_BOX_TYPE_CHPL
, LSMASH_BOX_PRECEDENCE_ISOM_CHPL
)
1579 isom_metaitem_t
*isom_add_metaitem( isom_ilst_t
*ilst
, lsmash_itunes_metadata_item item
)
1583 lsmash_box_type_t type
= lsmash_form_iso_box_type( item
);
1584 ADD_BOX_IN_LIST( metaitem
, ilst
, type
, LSMASH_BOX_PRECEDENCE_ISOM_METAITEM
);
1588 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mean
, mean
, metaitem
, ISOM_BOX_TYPE_MEAN
, LSMASH_BOX_PRECEDENCE_ISOM_MEAN
)
1589 DEFINE_SIMPLE_BOX_ADDER ( isom_add_name
, name
, metaitem
, ISOM_BOX_TYPE_NAME
, LSMASH_BOX_PRECEDENCE_ISOM_NAME
)
1590 DEFINE_SIMPLE_BOX_ADDER ( isom_add_data
, data
, metaitem
, ISOM_BOX_TYPE_DATA
, LSMASH_BOX_PRECEDENCE_ISOM_DATA
)
1591 DEFINE_SIMPLE_BOX_ADDER ( isom_add_ilst
, ilst
, meta
, ISOM_BOX_TYPE_ILST
, LSMASH_BOX_PRECEDENCE_ISOM_ILST
)
1592 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_keys
, keys
, meta
, QT_BOX_TYPE_KEYS
, LSMASH_BOX_PRECEDENCE_QTFF_KEYS
)
1594 isom_meta_t
*isom_add_meta( void *parent_box
)
1598 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1599 CREATE_BOX( meta
, parent
, ISOM_BOX_TYPE_META
, LSMASH_BOX_PRECEDENCE_ISOM_META
, 1 );
1600 if( parent
->file
== (lsmash_file_t
*)parent
)
1601 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, lsmash_file_t
);
1602 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1603 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_moov_t
);
1604 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1605 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_trak_t
);
1606 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1607 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_udta_t
);
1613 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_cprt
, cprt
, udta
, ISOM_BOX_TYPE_CPRT
, LSMASH_BOX_PRECEDENCE_ISOM_CPRT
)
1615 isom_udta_t
*isom_add_udta( void *parent_box
)
1619 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1620 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1622 isom_moov_t
*moov
= (isom_moov_t
*)parent
;
1623 ADD_BOX( udta
, moov
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1626 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1628 isom_trak_t
*trak
= (isom_trak_t
*)parent
;
1629 ADD_BOX( udta
, trak
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1636 DEFINE_SIMPLE_BOX_ADDER ( isom_add_WLOC
, WLOC
, udta
, QT_BOX_TYPE_WLOC
, LSMASH_BOX_PRECEDENCE_QTFF_WLOC
)
1637 DEFINE_SIMPLE_BOX_ADDER ( isom_add_LOOP
, LOOP
, udta
, QT_BOX_TYPE_LOOP
, LSMASH_BOX_PRECEDENCE_QTFF_LOOP
)
1638 DEFINE_SIMPLE_BOX_ADDER ( isom_add_SelO
, SelO
, udta
, QT_BOX_TYPE_SELO
, LSMASH_BOX_PRECEDENCE_QTFF_SELO
)
1639 DEFINE_SIMPLE_BOX_ADDER ( isom_add_AllF
, AllF
, udta
, QT_BOX_TYPE_ALLF
, LSMASH_BOX_PRECEDENCE_QTFF_ALLF
)
1640 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mvex
, mvex
, moov
, ISOM_BOX_TYPE_MVEX
, LSMASH_BOX_PRECEDENCE_ISOM_MVEX
)
1641 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mehd
, mehd
, mvex
, ISOM_BOX_TYPE_MEHD
, LSMASH_BOX_PRECEDENCE_ISOM_MEHD
)
1642 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trex
, trex
, mvex
, ISOM_BOX_TYPE_TREX
, LSMASH_BOX_PRECEDENCE_ISOM_TREX
)
1643 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_moof
, moof
, file
, ISOM_BOX_TYPE_MOOF
, LSMASH_BOX_PRECEDENCE_ISOM_MOOF
, lsmash_file_t
)
1644 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfhd
, mfhd
, moof
, ISOM_BOX_TYPE_MFHD
, LSMASH_BOX_PRECEDENCE_ISOM_MFHD
)
1645 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_traf
, traf
, moof
, ISOM_BOX_TYPE_TRAF
, LSMASH_BOX_PRECEDENCE_ISOM_TRAF
)
1646 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfhd
, tfhd
, traf
, ISOM_BOX_TYPE_TFHD
, LSMASH_BOX_PRECEDENCE_ISOM_TFHD
)
1647 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfdt
, tfdt
, traf
, ISOM_BOX_TYPE_TFDT
, LSMASH_BOX_PRECEDENCE_ISOM_TFDT
)
1648 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trun
, trun
, traf
, ISOM_BOX_TYPE_TRUN
, LSMASH_BOX_PRECEDENCE_ISOM_TRUN
)
1649 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfra
, mfra
, file
, ISOM_BOX_TYPE_MFRA
, LSMASH_BOX_PRECEDENCE_ISOM_MFRA
, lsmash_file_t
)
1650 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_tfra
, tfra
, mfra
, ISOM_BOX_TYPE_TFRA
, LSMASH_BOX_PRECEDENCE_ISOM_TFRA
)
1651 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfro
, mfro
, mfra
, ISOM_BOX_TYPE_MFRO
, LSMASH_BOX_PRECEDENCE_ISOM_MFRO
)
1653 isom_mdat_t
*isom_add_mdat( lsmash_file_t
*file
)
1655 assert( !file
->mdat
);
1656 CREATE_BOX( mdat
, file
, ISOM_BOX_TYPE_MDAT
, LSMASH_BOX_PRECEDENCE_ISOM_MDAT
, 1 );
1661 isom_free_t
*isom_add_free( void *parent_box
)
1665 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1666 if( parent
->file
== (lsmash_file_t
*)parent
)
1668 lsmash_file_t
*file
= (lsmash_file_t
*)parent
;
1669 CREATE_BOX( skip
, file
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1674 CREATE_BOX( skip
, parent
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1678 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_styp
, styp
, file
, ISOM_BOX_TYPE_STYP
, LSMASH_BOX_PRECEDENCE_ISOM_STYP
, lsmash_file_t
)
1680 isom_sidx_t
*isom_add_sidx( lsmash_file_t
*file
)
1682 ADD_LIST_BOX_IN_LIST( sidx
, file
, ISOM_BOX_TYPE_SIDX
, LSMASH_BOX_PRECEDENCE_ISOM_SIDX
);
1686 #undef ATTACH_EXACTLY_ONE_BOX_TO_PARENT
1688 #undef CREATE_LIST_BOX
1689 #undef ADD_BOX_TEMPLATE
1690 #undef ADD_BOX_IN_LIST_TEMPLATE
1692 #undef ADD_BOX_IN_LIST
1694 #undef ADD_LIST_BOX_IN_LIST
1695 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE
1696 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6
1697 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5
1698 #undef DEFINE_SIMPLE_BOX_ADDER
1699 #undef DEFINE_SIMPLE_BOX_IN_LIST_ADDER
1700 #undef DEFINE_SIMPLE_LIST_BOX_ADDER
1702 static int fake_file_read
1709 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1711 if( stream
->pos
+ size
> stream
->size
)
1712 read_size
= stream
->size
- stream
->pos
;
1715 memcpy( buf
, stream
->data
+ stream
->pos
, read_size
);
1716 stream
->pos
+= read_size
;
1720 static int64_t fake_file_seek
1727 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1728 if( whence
== SEEK_SET
)
1729 stream
->pos
= offset
;
1730 else if( whence
== SEEK_CUR
)
1731 stream
->pos
+= offset
;
1732 else if( whence
== SEEK_END
)
1733 stream
->pos
= stream
->size
+ offset
;
1737 /* Public functions */
1738 lsmash_root_t
*lsmash_create_root( void )
1740 lsmash_root_t
*root
= lsmash_malloc_zero( sizeof(lsmash_root_t
) );
1747 void lsmash_destroy_root( lsmash_root_t
*root
)
1749 isom_remove_box_by_itself( root
);
1752 lsmash_extended_box_type_t
lsmash_form_extended_box_type( uint32_t fourcc
, const uint8_t id
[12] )
1754 return (lsmash_extended_box_type_t
){ fourcc
, { id
[0], id
[1], id
[2], id
[3], id
[4], id
[5],
1755 id
[6], id
[7], id
[8], id
[9], id
[10], id
[11] } };
1758 lsmash_box_type_t
lsmash_form_iso_box_type( uint32_t fourcc
)
1760 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_ISO_12_BYTES
) };
1763 lsmash_box_type_t
lsmash_form_qtff_box_type( uint32_t fourcc
)
1765 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_QTFF_12_BYTES
) };
1768 #define CHECK_BOX_TYPE_IDENTICAL( a, b ) \
1769 a.fourcc == b.fourcc \
1770 && a.user.fourcc == b.user.fourcc \
1771 && a.user.id[0] == b.user.id[0] \
1772 && a.user.id[1] == b.user.id[1] \
1773 && a.user.id[2] == b.user.id[2] \
1774 && a.user.id[3] == b.user.id[3] \
1775 && a.user.id[4] == b.user.id[4] \
1776 && a.user.id[5] == b.user.id[5] \
1777 && a.user.id[6] == b.user.id[6] \
1778 && a.user.id[7] == b.user.id[7] \
1779 && a.user.id[8] == b.user.id[8] \
1780 && a.user.id[9] == b.user.id[9] \
1781 && a.user.id[10] == b.user.id[10] \
1782 && a.user.id[11] == b.user.id[11]
1784 int lsmash_check_box_type_identical( lsmash_box_type_t a
, lsmash_box_type_t b
)
1786 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1789 int lsmash_check_codec_type_identical( lsmash_codec_type_t a
, lsmash_codec_type_t b
)
1791 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1794 int lsmash_check_box_type_specified( const lsmash_box_type_t
*box_type
)
1799 return !!(box_type
->fourcc
1800 | box_type
->user
.fourcc
1801 | box_type
->user
.id
[0] | box_type
->user
.id
[1] | box_type
->user
.id
[2] | box_type
->user
.id
[3]
1802 | box_type
->user
.id
[4] | box_type
->user
.id
[5] | box_type
->user
.id
[6] | box_type
->user
.id
[7]
1803 | box_type
->user
.id
[8] | box_type
->user
.id
[9] | box_type
->user
.id
[10] | box_type
->user
.id
[11]);
1806 lsmash_box_t
*lsmash_get_box
1808 lsmash_box_t
*parent
,
1809 const lsmash_box_path_t box_path
[]
1812 lsmash_entry_t
*entry
= isom_get_entry_of_box( parent
, box_path
);
1813 return (lsmash_box_t
*)(entry
? entry
->data
: NULL
);
1816 lsmash_box_t
*lsmash_create_box
1818 lsmash_box_type_t type
,
1824 if( !lsmash_check_box_type_specified( &type
) )
1826 isom_unknown_box_t
*box
= lsmash_malloc_zero( sizeof(isom_unknown_box_t
) );
1831 box
->unknown_size
= size
;
1832 box
->unknown_field
= lsmash_memdup( data
, size
);
1833 if( !box
->unknown_field
)
1841 box
->unknown_size
= 0;
1842 box
->unknown_field
= NULL
;
1845 box
->class = &lsmash_box_class
;
1849 box
->destruct
= (isom_extension_destructor_t
)isom_remove_unknown_box
;
1850 box
->manager
= LSMASH_UNKNOWN_BOX
;
1851 box
->precedence
= precedence
;
1852 box
->size
= ISOM_BASEBOX_COMMON_SIZE
+ size
+ (type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0);
1854 isom_set_box_writer( (isom_box_t
*)box
);
1855 return (lsmash_box_t
*)box
;
1860 lsmash_box_t
*parent
,
1865 /* You cannot add any box without a box being its parent. */
1867 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1869 if( parent
->root
== (lsmash_root_t
*)parent
)
1871 /* Only files can be added into any ROOT.
1872 * For backward compatibility, use the active file as the parent. */
1874 parent
= (isom_box_t
*)parent
->file
;
1878 /* Add a box as a child box. */
1879 box
->root
= parent
->root
;
1880 box
->file
= parent
->file
;
1881 box
->parent
= parent
;
1882 return isom_add_box_to_extension_list( parent
, box
);
1885 int lsmash_add_box_ex
1887 lsmash_box_t
*parent
,
1888 lsmash_box_t
**p_box
1892 /* You cannot add any box without a box being its parent. */
1894 isom_unknown_box_t
*box
= (isom_unknown_box_t
*)*p_box
;
1895 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1897 if( !(box
->manager
& LSMASH_UNKNOWN_BOX
) )
1898 /* Simply add the box. */
1899 return lsmash_add_box( parent
, *p_box
);
1900 /* Check if the size of the box to be added is valid. */
1901 if( box
->size
!= ISOM_BASEBOX_COMMON_SIZE
+ box
->unknown_size
+ (box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0) )
1903 if( !parent
->file
|| parent
->file
== (lsmash_file_t
*)box
)
1905 if( parent
->root
== (lsmash_root_t
*)parent
)
1906 /* Only files can be added into any ROOT.
1907 * For backward compatibility, use the active file as the parent. */
1908 parent
= (isom_box_t
*)parent
->file
;
1909 /* Switch to the fake-file stream mode. */
1910 lsmash_file_t
*file
= parent
->file
;
1911 lsmash_bs_t
*bs_backup
= file
->bs
;
1912 lsmash_bs_t
*bs
= lsmash_bs_create();
1915 uint8_t *buf
= lsmash_malloc( box
->size
);
1918 lsmash_bs_cleanup( bs
);
1921 fake_file_stream_t fake_file
=
1927 bs
->stream
= &fake_file
;
1928 bs
->read
= fake_file_read
;
1930 bs
->seek
= fake_file_seek
;
1932 file
->fake_file_mode
= 1;
1933 /* Make the byte string representing the given box. */
1934 LSMASH_SET_BE32( &buf
[0], box
->size
);
1935 LSMASH_SET_BE32( &buf
[4], box
->type
.fourcc
);
1936 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
1938 LSMASH_SET_BE32( &buf
[8], box
->type
.user
.fourcc
);
1939 memcpy( &buf
[12], box
->type
.user
.id
, 12 );
1941 memcpy( buf
+ (uintptr_t)(box
->size
- box
->unknown_size
), box
->unknown_field
, box
->unknown_size
);
1942 /* Add a box as a child box and try to expand into struct format. */
1943 lsmash_box_t dummy
= { 0 };
1944 int ret
= isom_read_box( file
, &dummy
, parent
, 0, 0 );
1946 lsmash_bs_cleanup( bs
);
1947 file
->bs
= bs_backup
; /* Switch back to the normal file stream mode. */
1948 file
->fake_file_mode
= 0;
1951 /* Reorder the added box by 'precedence'. */
1952 *p_box
= (lsmash_box_t
*)parent
->extensions
.tail
->data
;
1953 (*p_box
)->precedence
= box
->precedence
;
1954 isom_reorder_tail_box( parent
);
1955 /* Do also its children by the same way. */
1956 lsmash_entry_list_t extensions
= box
->extensions
;
1957 lsmash_init_entry_list( &box
->extensions
); /* to avoid freeing the children */
1958 isom_remove_box_by_itself( box
);
1959 for( lsmash_entry_t
*entry
= extensions
.head
; entry
; entry
= entry
->next
)
1963 lsmash_box_t
*child
= (lsmash_box_t
*)entry
->data
;
1964 if( lsmash_add_box_ex( *p_box
, &child
) == 0 )
1966 (*p_box
)->size
+= child
->size
;
1967 /* Avoid freeing at the end of this function. */
1971 isom_remove_all_extension_boxes( &extensions
);
1975 void lsmash_destroy_box
1980 isom_remove_box_by_itself( box
);
1983 void lsmash_destroy_children
1989 isom_remove_all_extension_boxes( &box
->extensions
);
1992 int lsmash_get_box_precedence
1995 uint64_t *precedence
1998 if( !box
|| !precedence
)
2000 *precedence
= box
->precedence
;
2004 lsmash_box_t
*lsmash_root_as_box
2009 return (lsmash_box_t
*)root
;
2012 lsmash_box_t
*lsmash_file_as_box
2017 return (lsmash_box_t
*)file
;
2020 int lsmash_write_top_level_box
2025 if( !box
|| (isom_box_t
*)box
->file
!= box
->parent
)
2027 if( isom_write_box( box
->file
->bs
, box
) < 0 )
2029 box
->file
->size
+= box
->size
;
2033 uint8_t *lsmash_export_box
2041 lsmash_bs_t
*bs
= lsmash_bs_create();
2044 if( isom_write_box( bs
, box
) < 0 )
2046 lsmash_bs_cleanup( bs
);
2049 *size
= bs
->buffer
.store
;
2050 uint8_t *data
= bs
->buffer
.data
;
2051 bs
->buffer
.data
= NULL
;
2052 lsmash_bs_cleanup( bs
);