1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2015 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
34 #include "codecs/mp4a.h"
35 #include "codecs/mp4sys.h"
37 #include "importer/importer.h"
39 static const lsmash_class_t lsmash_box_class
=
44 const lsmash_box_type_t static_lsmash_box_type_unspecified
= LSMASH_BOX_TYPE_INITIALIZER
;
46 void isom_init_box_common_orig
50 lsmash_box_type_t box_type
,
52 isom_extension_destructor_t destructor
55 isom_box_t
*box
= (isom_box_t
*)_box
;
56 isom_box_t
*parent
= (isom_box_t
*)_parent
;
57 assert( box
&& parent
&& parent
->root
);
58 box
->class = &lsmash_box_class
;
59 box
->root
= parent
->root
;
60 box
->file
= parent
->file
;
62 box
->precedence
= precedence
;
63 box
->destruct
= destructor
;
66 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) && isom_is_fullbox( box
) )
71 isom_set_box_writer( box
);
74 static void isom_reorder_tail_box( isom_box_t
*parent
)
76 /* Reorder the appended box by 'precedence'. */
77 lsmash_entry_t
*x
= parent
->extensions
.tail
;
78 assert( x
&& x
->data
);
79 uint64_t precedence
= ((isom_box_t
*)x
->data
)->precedence
;
80 for( lsmash_entry_t
*y
= x
->prev
; y
; y
= y
->prev
)
82 isom_box_t
*box
= (isom_box_t
*)y
->data
;
83 if( !box
|| precedence
> box
->precedence
)
85 /* Exchange the entity data of adjacent two entries. */
95 int isom_add_box_to_extension_list( void *parent_box
, void *child_box
)
97 assert( parent_box
&& child_box
);
98 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
99 isom_box_t
*child
= (isom_box_t
*)child_box
;
100 /* Append at the end of the list. */
101 if( lsmash_add_entry( &parent
->extensions
, child
) < 0 )
102 return LSMASH_ERR_MEMORY_ALLOC
;
103 /* Don't reorder the appended box when the file is opened for reading. */
104 if( !parent
->file
|| (parent
->file
->flags
& LSMASH_FILE_MODE_READ
) || parent
->file
->fake_file_mode
)
106 isom_reorder_tail_box( parent
);
110 void isom_bs_put_basebox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
112 if( box
->size
> UINT32_MAX
)
114 lsmash_bs_put_be32( bs
, 1 );
115 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
116 lsmash_bs_put_be64( bs
, box
->size
); /* largesize */
120 lsmash_bs_put_be32( bs
, (uint32_t)box
->size
);
121 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
123 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
125 lsmash_bs_put_be32( bs
, box
->type
.user
.fourcc
);
126 lsmash_bs_put_bytes( bs
, 12, box
->type
.user
.id
);
130 void isom_bs_put_fullbox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
132 isom_bs_put_basebox_common( bs
, box
);
133 lsmash_bs_put_byte( bs
, box
->version
);
134 lsmash_bs_put_be24( bs
, box
->flags
);
137 void isom_bs_put_box_common( lsmash_bs_t
*bs
, void *box
)
144 isom_box_t
*parent
= ((isom_box_t
*)box
)->parent
;
145 if( parent
&& lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
147 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
150 if( isom_is_fullbox( box
) )
151 isom_bs_put_fullbox_common( bs
, (isom_box_t
*)box
);
153 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
156 /* Return 1 if the box is fullbox, Otherwise return 0. */
157 int isom_is_fullbox( void *box
)
159 isom_box_t
*current
= (isom_box_t
*)box
;
160 lsmash_box_type_t type
= current
->type
;
161 static lsmash_box_type_t fullbox_type_table
[50] = { LSMASH_BOX_TYPE_INITIALIZER
};
162 if( !lsmash_check_box_type_specified( &fullbox_type_table
[0] ) )
164 /* Initialize the table. */
166 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SIDX
;
167 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MVHD
;
168 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TKHD
;
169 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_IODS
;
170 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ESDS
;
171 fullbox_type_table
[i
++] = QT_BOX_TYPE_ESDS
;
172 fullbox_type_table
[i
++] = QT_BOX_TYPE_CLEF
;
173 fullbox_type_table
[i
++] = QT_BOX_TYPE_PROF
;
174 fullbox_type_table
[i
++] = QT_BOX_TYPE_ENOF
;
175 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ELST
;
176 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MDHD
;
177 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HDLR
;
178 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_VMHD
;
179 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SMHD
;
180 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HMHD
;
181 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NMHD
;
182 fullbox_type_table
[i
++] = QT_BOX_TYPE_GMIN
;
183 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_DREF
;
184 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSD
;
185 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSL
;
186 fullbox_type_table
[i
++] = QT_BOX_TYPE_CHAN
;
187 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SRAT
;
188 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STTS
;
189 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CTTS
;
190 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CSLG
;
191 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSS
;
192 fullbox_type_table
[i
++] = QT_BOX_TYPE_STPS
;
193 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SDTP
;
194 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSC
;
195 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSZ
;
196 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STZ2
;
197 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STCO
;
198 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CO64
;
199 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SGPD
;
200 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SBGP
;
201 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CHPL
;
202 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_META
;
203 fullbox_type_table
[i
++] = QT_BOX_TYPE_KEYS
;
204 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEAN
;
205 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NAME
;
206 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEHD
;
207 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TREX
;
208 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFHD
;
209 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFHD
;
210 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFDT
;
211 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TRUN
;
212 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFRA
;
213 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFRO
;
214 fullbox_type_table
[i
] = LSMASH_BOX_TYPE_UNSPECIFIED
;
216 for( int i
= 0; lsmash_check_box_type_specified( &fullbox_type_table
[i
] ); i
++ )
217 if( lsmash_check_box_type_identical( type
, fullbox_type_table
[i
] ) )
219 if( current
->parent
)
221 if( lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_DREF
)
222 || (lsmash_check_box_type_identical( type
, ISOM_BOX_TYPE_CPRT
)
223 && lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_UDTA
)) )
229 /* Return 1 if the sample type is LPCM audio, Otherwise return 0. */
230 int isom_is_lpcm_audio( void *box
)
232 isom_box_t
*current
= (isom_box_t
*)box
;
233 lsmash_box_type_t type
= current
->type
;
234 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
235 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
236 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
237 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
238 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
239 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
240 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
241 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
242 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
243 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
244 || (lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
) && (current
->manager
& LSMASH_AUDIO_DESCRIPTION
));
247 int isom_is_qt_audio( lsmash_codec_type_t type
)
249 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
250 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC3_AUDIO
)
251 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC6_AUDIO
)
252 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
253 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDM2_AUDIO
)
254 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDMC_AUDIO
)
255 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QCLP_AUDIO
)
256 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AC_3_AUDIO
)
257 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AGSM_AUDIO
)
258 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAC_AUDIO
)
259 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAW_AUDIO
)
260 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX2_AUDIO
)
261 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX4_AUDIO
)
262 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVCA_AUDIO
)
263 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVI_AUDIO
)
264 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
265 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
266 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IMA4_AUDIO
)
267 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
268 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
269 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
270 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP4A_AUDIO
)
271 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
)
272 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
273 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
274 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ULAW_AUDIO
)
275 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_VDVA_AUDIO
)
276 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
277 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
)
278 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
279 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
280 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
281 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
);
284 /* Return 1 if the sample type is uncompressed Y'CbCr video, Otherwise return 0. */
285 int isom_is_uncompressed_ycbcr( lsmash_codec_type_t type
)
287 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_2VUY_VIDEO
)
288 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V210_VIDEO
)
289 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V216_VIDEO
)
290 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V308_VIDEO
)
291 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V408_VIDEO
)
292 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V410_VIDEO
)
293 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_YUV2_VIDEO
);
296 int isom_is_waveform_audio( lsmash_box_type_t type
)
298 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
299 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
300 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
301 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
302 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
);
305 size_t isom_skip_box_common( uint8_t **p_data
)
307 uint8_t *orig
= *p_data
;
308 uint8_t *data
= *p_data
;
309 uint64_t size
= LSMASH_GET_BE32( data
);
310 data
+= ISOM_BASEBOX_COMMON_SIZE
;
313 size
= LSMASH_GET_BE64( data
);
320 /* TODO: more secure handling */
321 static size_t isom_read_box_size_and_type_from_binary_string( uint8_t **p_data
, uint64_t *size
, lsmash_box_type_t
*type
)
323 uint8_t *orig
= *p_data
;
324 uint8_t *data
= *p_data
;
325 *size
= LSMASH_GET_BE32( &data
[0] );
326 type
->fourcc
= LSMASH_GET_BE32( &data
[4] );
327 data
+= ISOM_BASEBOX_COMMON_SIZE
;
330 *size
= LSMASH_GET_BE64( data
);
334 if( type
->fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
336 type
->user
.fourcc
= LSMASH_GET_BE32( &data
[0] );
337 memcpy( type
->user
.id
, &data
[4], 12 );
342 uint8_t *isom_get_child_box_position( uint8_t *parent_data
, uint32_t parent_size
, lsmash_box_type_t child_type
, uint32_t *child_size
)
344 if( !parent_data
|| !child_size
|| parent_size
< ISOM_BASEBOX_COMMON_SIZE
)
346 uint8_t *data
= parent_data
;
348 lsmash_box_type_t type
;
349 uint32_t offset
= isom_read_box_size_and_type_from_binary_string( &data
, &size
, &type
);
350 if( size
!= parent_size
)
352 uint8_t *end
= parent_data
+ parent_size
;
353 for( uint8_t *pos
= data
; pos
+ ISOM_BASEBOX_COMMON_SIZE
<= end
; )
355 offset
= isom_read_box_size_and_type_from_binary_string( &pos
, &size
, &type
);
356 if( lsmash_check_box_type_identical( type
, child_type
) )
361 pos
+= size
- offset
; /* Move to the next box. */
366 static void isom_destruct_extension_binary( void *ext
)
370 isom_box_t
*box
= (isom_box_t
*)ext
;
371 lsmash_free( box
->binary
);
374 int isom_add_extension_binary
377 lsmash_box_type_t box_type
,
383 if( !parent_box
|| !box_data
|| box_size
< ISOM_BASEBOX_COMMON_SIZE
384 || !lsmash_check_box_type_specified( &box_type
) )
385 return LSMASH_ERR_FUNCTION_PARAM
;
386 isom_box_t
*ext
= lsmash_malloc_zero( sizeof(isom_box_t
) );
388 return LSMASH_ERR_MEMORY_ALLOC
;
389 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
390 ext
->class = &lsmash_box_class
;
391 ext
->root
= parent
->root
;
392 ext
->file
= parent
->file
;
393 ext
->parent
= parent
;
394 ext
->manager
= LSMASH_BINARY_CODED_BOX
;
395 ext
->precedence
= precedence
;
396 ext
->size
= box_size
;
397 ext
->type
= box_type
;
398 ext
->binary
= box_data
;
399 ext
->destruct
= isom_destruct_extension_binary
;
400 if( isom_add_box_to_extension_list( parent
, ext
) < 0 )
403 return LSMASH_ERR_MEMORY_ALLOC
;
405 isom_set_box_writer( ext
);
409 static void isom_remove_extension_box( isom_box_t
*ext
)
414 ext
->destruct( ext
);
415 isom_remove_all_extension_boxes( &ext
->extensions
);
419 void isom_remove_all_extension_boxes( lsmash_entry_list_t
*extensions
)
421 lsmash_remove_entries( extensions
, isom_remove_extension_box
);
424 isom_box_t
*isom_get_extension_box( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
426 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
428 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
431 if( lsmash_check_box_type_identical( ext
->type
, box_type
) )
437 void *isom_get_extension_box_format( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
439 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
441 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
442 if( !ext
|| (ext
->manager
& LSMASH_BINARY_CODED_BOX
) || !lsmash_check_box_type_identical( ext
->type
, box_type
) )
449 lsmash_entry_t
*isom_get_entry_of_box
451 lsmash_box_t
*parent
,
452 const lsmash_box_path_t box_path
[]
457 lsmash_entry_t
*entry
= NULL
;
458 const lsmash_box_path_t
*path
= &box_path
[0];
459 while( lsmash_check_box_type_specified( &path
->type
) )
461 entry
= parent
->extensions
.head
;
466 uint32_t number
= path
->number
? path
->number
: 1;
469 isom_box_t
*box
= entry
->data
;
470 if( box
&& lsmash_check_box_type_identical( path
->type
, box
->type
) )
474 /* Found a box. Move to a child box. */
489 /* box destructors */
490 #define REMOVE_BOX( box_name, parent_type ) \
491 isom_remove_predefined_box( box_name, offsetof( parent_type, box_name ) )
493 #define REMOVE_BOX_IN_LIST( box_name, parent_type ) \
494 isom_remove_box_in_predefined_list( box_name, offsetof( parent_type, box_name##_list ) )
496 #define REMOVE_LIST_BOX_TEMPLATE( REMOVER, box_name, parent_type, eliminator ) \
499 lsmash_remove_list( box_name->list, eliminator ); \
500 REMOVER( box_name, parent_type ); \
503 #define REMOVE_LIST_BOX( box_name, ... ) CALL_FUNC_DEFAULT_ARGS( REMOVE_LIST_BOX, box_name, __VA_ARGS__ )
504 #define REMOVE_LIST_BOX_3( box_name, parent_type, eliminator ) \
505 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX, box_name, parent_type, eliminator )
506 #define REMOVE_LIST_BOX_2( box_name, parent_type ) \
507 REMOVE_LIST_BOX_3( box_name, parent_type, NULL )
509 #define REMOVE_LIST_BOX_IN_LIST( box_name, parent_type ) \
510 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX_IN_LIST, box_name, parent_type, NULL )
512 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVER, box_name, ... ) \
513 static void isom_remove_##box_name( isom_##box_name##_t *box_name ) \
517 REMOVER( box_name, __VA_ARGS__ ); \
520 #define DEFINE_SIMPLE_BOX_REMOVER( func_name, box_name, ... ) \
521 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX, box_name, __VA_ARGS__ )
523 #define DEFINE_SIMPLE_LIST_BOX_REMOVER( func_name, box_name, ... ) \
524 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX, box_name, __VA_ARGS__ )
526 #define DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( func_name, box_name, ... ) \
527 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX_IN_LIST, box_name, __VA_ARGS__ )
529 #define DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( func_name, box_name, ... ) \
530 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX_IN_LIST, box_name, __VA_ARGS__ )
532 static void isom_remove_predefined_box( void *opaque_box
, size_t offset_of_box
)
534 assert( opaque_box
);
535 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
538 isom_box_t
**p
= (isom_box_t
**)(((int8_t *)box
->parent
) + offset_of_box
);
544 /* We always free boxes through the extension list of the parent box.
545 * Therefore, don't free boxes through any list other than the extension list. */
546 static void isom_remove_box_in_predefined_list( void *opaque_box
, size_t offset_of_list
)
548 assert( opaque_box
);
549 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
552 lsmash_entry_list_t
*list
= (lsmash_entry_list_t
*)(((int8_t *)box
->parent
) + offset_of_list
);
554 for( lsmash_entry_t
*entry
= list
->head
; entry
; entry
= entry
->next
)
555 if( box
== entry
->data
)
557 /* We don't free this box here.
558 * Because of freeing an entry of the list here, don't pass the list to free this box.
561 lsmash_remove_entry_direct( list
, entry
, NULL
);
567 /* Remove a box by the pointer containing its address.
568 * In addition, remove from the extension list of the parent box if possible.
569 * Don't call this function within a function freeing one or more entries of any extension list because of double free.
570 * Basically, don't use this function as a callback function. */
571 void isom_remove_box_by_itself( void *opaque_box
)
575 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
578 isom_box_t
*parent
= box
->parent
;
579 for( lsmash_entry_t
*entry
= parent
->extensions
.head
; entry
; entry
= entry
->next
)
580 if( box
== entry
->data
)
582 /* Free the corresponding entry here, therefore don't call this function as a callback function
583 * if a function frees the same entry later and calls this function. */
584 lsmash_remove_entry_direct( &parent
->extensions
, entry
, isom_remove_extension_box
);
588 isom_remove_extension_box( box
);
591 void isom_remove_unknown_box( isom_unknown_box_t
*unknown_box
)
595 lsmash_free( unknown_box
->unknown_field
);
598 static void isom_remove_file( lsmash_file_t
*file
)
602 isom_remove_print_funcs( file
);
603 isom_remove_timelines( file
);
604 lsmash_free( file
->compatible_brands
);
605 lsmash_bs_cleanup( file
->bs
);
606 lsmash_importer_destroy( file
->importer
);
609 lsmash_remove_list( file
->fragment
->pool
, isom_remove_sample_pool
);
610 lsmash_free( file
->fragment
);
612 REMOVE_BOX_IN_LIST( file
, lsmash_root_t
);
615 static void isom_remove_ftyp( isom_ftyp_t
*ftyp
)
619 lsmash_free( ftyp
->compatible_brands
);
620 REMOVE_BOX( ftyp
, lsmash_file_t
);
623 static void isom_remove_iods( isom_iods_t
*iods
)
627 mp4sys_remove_descriptor( iods
->OD
);
628 REMOVE_BOX( iods
, isom_moov_t
);
631 static void isom_remove_trak( isom_trak_t
*trak
)
637 isom_remove_sample_pool( trak
->cache
->chunk
.pool
);
638 lsmash_remove_list( trak
->cache
->roll
.pool
, NULL
);
639 lsmash_free( trak
->cache
->rap
);
640 lsmash_free( trak
->cache
->fragment
);
641 lsmash_free( trak
->cache
);
643 REMOVE_BOX_IN_LIST( trak
, isom_moov_t
);
646 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tkhd
, tkhd
, isom_trak_t
)
647 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_clef
, clef
, isom_tapt_t
)
648 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_prof
, prof
, isom_tapt_t
)
649 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enof
, enof
, isom_tapt_t
)
650 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tapt
, tapt
, isom_trak_t
)
651 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_edts
, edts
, isom_trak_t
)
652 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tref
, tref
, isom_trak_t
)
653 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_elst
, elst
, isom_edts_t
)
655 static void isom_remove_track_reference_type( isom_tref_type_t
*ref
)
659 lsmash_free( ref
->track_ID
);
660 isom_remove_box_in_predefined_list( ref
, offsetof( isom_tref_t
, ref_list
) );
663 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdhd
, mdhd
, isom_mdia_t
)
664 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_vmhd
, vmhd
, isom_minf_t
)
665 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_smhd
, smhd
, isom_minf_t
)
666 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_hmhd
, hmhd
, isom_minf_t
)
667 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_nmhd
, nmhd
, isom_minf_t
)
668 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmhd
, gmhd
, isom_minf_t
)
669 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmin
, gmin
, isom_gmhd_t
)
670 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_text
, text
, isom_gmhd_t
)
672 static void isom_remove_hdlr( isom_hdlr_t
*hdlr
)
676 lsmash_free( hdlr
->componentName
);
679 if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MDIA
) )
680 REMOVE_BOX( hdlr
, isom_mdia_t
);
681 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_META
)
682 || lsmash_check_box_type_identical( hdlr
->parent
->type
, QT_BOX_TYPE_META
) )
683 REMOVE_BOX( hdlr
, isom_meta_t
);
684 else if( lsmash_check_box_type_identical( hdlr
->parent
->type
, ISOM_BOX_TYPE_MINF
) )
685 REMOVE_BOX( hdlr
, isom_minf_t
);
692 static void isom_remove_glbl( isom_glbl_t
*glbl
)
696 lsmash_free( glbl
->header_data
);
699 static void isom_remove_esds( isom_esds_t
*esds
)
703 mp4sys_remove_descriptor( esds
->ES
);
706 static void isom_remove_font_record( isom_font_record_t
*font_record
)
710 lsmash_free( font_record
->font_name
);
711 lsmash_free( font_record
);
713 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ftab
, ftab
, isom_tx3g_entry_t
, isom_remove_font_record
)
715 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_frma
, frma
, isom_wave_t
)
716 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enda
, enda
, isom_wave_t
)
717 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mp4a
, mp4a
, isom_wave_t
)
718 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_terminator
, terminator
, isom_wave_t
)
720 static void isom_remove_chan( isom_chan_t
*chan
)
724 lsmash_free( chan
->channelDescriptions
);
727 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stsd
, stsd
, isom_stbl_t
)
729 static void isom_remove_visual_description( isom_sample_entry_t
*description
)
731 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)description
;
732 lsmash_free( visual
->color_table
.array
);
733 isom_remove_box_in_predefined_list( visual
, offsetof( isom_stsd_t
, list
) );
736 static void isom_remove_audio_description( isom_sample_entry_t
*description
)
738 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
741 static void isom_remove_hint_description( isom_sample_entry_t
*description
)
743 isom_hint_entry_t
*hint
= (isom_hint_entry_t
*)description
;
744 lsmash_free( hint
->data
);
745 isom_remove_box_in_predefined_list( hint
, offsetof( isom_stsd_t
, list
) );
748 static void isom_remove_metadata_description( isom_sample_entry_t
*description
)
750 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
753 static void isom_remove_tx3g_description( isom_sample_entry_t
*description
)
755 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
758 static void isom_remove_qt_text_description( isom_sample_entry_t
*description
)
760 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)description
;
761 lsmash_free( text
->font_name
);
762 isom_remove_box_in_predefined_list( text
, offsetof( isom_stsd_t
, list
) );
765 static void isom_remove_mp4s_description( isom_sample_entry_t
*description
)
767 isom_remove_box_in_predefined_list( description
, offsetof( isom_stsd_t
, list
) );
770 void isom_remove_sample_description( isom_sample_entry_t
*sample
)
774 lsmash_codec_type_t sample_type
= sample
->type
;
775 if( lsmash_check_box_type_identical( sample_type
, LSMASH_CODEC_TYPE_RAW
) )
777 if( sample
->manager
& LSMASH_VIDEO_DESCRIPTION
)
779 isom_remove_visual_description( sample
);
782 else if( sample
->manager
& LSMASH_AUDIO_DESCRIPTION
)
784 isom_remove_audio_description( sample
);
788 static struct description_remover_table_tag
790 lsmash_codec_type_t type
;
791 void (*func
)( isom_sample_entry_t
* );
792 } description_remover_table
[160] = { { LSMASH_CODEC_TYPE_INITIALIZER
, NULL
} };
793 if( !description_remover_table
[0].func
)
795 /* Initialize the table. */
797 #define ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( type, func ) \
798 description_remover_table[i++] = (struct description_remover_table_tag){ type, func }
799 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, isom_remove_visual_description
);
800 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, isom_remove_visual_description
);
801 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, isom_remove_visual_description
);
802 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, isom_remove_visual_description
);
803 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, isom_remove_visual_description
);
804 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, isom_remove_visual_description
);
805 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, isom_remove_visual_description
);
806 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, isom_remove_visual_description
);
807 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, isom_remove_visual_description
);
808 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, isom_remove_visual_description
);
809 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, isom_remove_visual_description
);
810 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
811 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, isom_remove_visual_description
);
812 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, isom_remove_visual_description
);
813 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, isom_remove_visual_description
);
814 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, isom_remove_visual_description
);
815 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, isom_remove_visual_description
);
816 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, isom_remove_visual_description
);
817 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, isom_remove_visual_description
);
818 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, isom_remove_visual_description
);
819 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, isom_remove_visual_description
);
820 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, isom_remove_visual_description
);
821 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, isom_remove_visual_description
);
822 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, isom_remove_visual_description
);
823 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, isom_remove_visual_description
);
824 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, isom_remove_visual_description
);
825 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, isom_remove_visual_description
);
826 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, isom_remove_visual_description
);
827 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, isom_remove_visual_description
);
828 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, isom_remove_visual_description
);
829 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, isom_remove_visual_description
);
830 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, isom_remove_visual_description
);
831 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, isom_remove_visual_description
);
832 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, isom_remove_visual_description
);
833 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, isom_remove_visual_description
);
834 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, isom_remove_visual_description
);
835 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, isom_remove_visual_description
);
836 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, isom_remove_visual_description
);
837 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, isom_remove_visual_description
);
838 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO
, isom_remove_visual_description
);
839 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, isom_remove_visual_description
);
840 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
841 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, isom_remove_visual_description
);
842 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, isom_remove_visual_description
);
843 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, isom_remove_visual_description
);
844 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, isom_remove_visual_description
);
845 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, isom_remove_visual_description
);
846 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, isom_remove_visual_description
);
847 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, isom_remove_visual_description
);
848 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, isom_remove_visual_description
);
849 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, isom_remove_visual_description
);
850 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, isom_remove_visual_description
);
851 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, isom_remove_visual_description
);
852 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, isom_remove_visual_description
);
853 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, isom_remove_visual_description
);
854 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, isom_remove_visual_description
);
855 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, isom_remove_visual_description
);
856 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, isom_remove_visual_description
);
857 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, isom_remove_visual_description
);
858 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, isom_remove_visual_description
);
859 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, isom_remove_visual_description
);
860 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, isom_remove_visual_description
);
861 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, isom_remove_visual_description
);
862 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, isom_remove_visual_description
);
863 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, isom_remove_visual_description
);
864 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, isom_remove_visual_description
);
865 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, isom_remove_visual_description
);
866 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, isom_remove_visual_description
);
867 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, isom_remove_visual_description
);
868 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, isom_remove_visual_description
);
869 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, isom_remove_visual_description
);
870 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO
, isom_remove_visual_description
);
871 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, isom_remove_visual_description
);
872 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, isom_remove_visual_description
);
873 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, isom_remove_visual_description
);
874 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, isom_remove_visual_description
);
875 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, isom_remove_visual_description
);
876 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, isom_remove_visual_description
);
877 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
878 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, isom_remove_audio_description
);
879 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, isom_remove_audio_description
);
880 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, isom_remove_audio_description
);
881 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, isom_remove_audio_description
);
882 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, isom_remove_audio_description
);
883 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, isom_remove_audio_description
);
884 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, isom_remove_audio_description
);
885 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, isom_remove_audio_description
);
886 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, isom_remove_audio_description
);
887 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
888 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, isom_remove_audio_description
);
889 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, isom_remove_audio_description
);
890 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, isom_remove_audio_description
);
891 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, isom_remove_audio_description
);
892 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
893 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, isom_remove_audio_description
);
894 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, isom_remove_audio_description
);
895 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, isom_remove_audio_description
);
896 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, isom_remove_audio_description
);
897 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, isom_remove_audio_description
);
898 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, isom_remove_audio_description
);
899 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, isom_remove_audio_description
);
900 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, isom_remove_audio_description
);
901 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, isom_remove_audio_description
);
902 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, isom_remove_audio_description
);
903 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, isom_remove_audio_description
);
904 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, isom_remove_audio_description
);
905 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, isom_remove_audio_description
);
906 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, isom_remove_audio_description
);
907 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, isom_remove_audio_description
);
908 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
909 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_FDP_HINT
, isom_remove_hint_description
);
910 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M2TS_HINT
, isom_remove_hint_description
);
911 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PM2T_HINT
, isom_remove_hint_description
);
912 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PRTP_HINT
, isom_remove_hint_description
);
913 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RM2T_HINT
, isom_remove_hint_description
);
914 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RRTP_HINT
, isom_remove_hint_description
);
915 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RSRP_HINT
, isom_remove_hint_description
);
916 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RTP_HINT
, isom_remove_hint_description
);
917 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SM2T_HINT
, isom_remove_hint_description
);
918 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SRTP_HINT
, isom_remove_hint_description
);
919 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_IXSE_META
, isom_remove_metadata_description
);
920 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METT_META
, isom_remove_metadata_description
);
921 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METX_META
, isom_remove_metadata_description
);
922 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLIX_META
, isom_remove_metadata_description
);
923 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_OKSD_META
, isom_remove_metadata_description
);
924 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVCM_META
, isom_remove_metadata_description
);
925 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TEXT_META
, isom_remove_metadata_description
);
926 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_URIM_META
, isom_remove_metadata_description
);
927 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_XML_META
, isom_remove_metadata_description
);
928 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, isom_remove_tx3g_description
);
929 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, isom_remove_qt_text_description
);
930 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, isom_remove_mp4s_description
);
931 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
933 for( int i
= 0; description_remover_table
[i
].func
; i
++ )
934 if( lsmash_check_codec_type_identical( sample_type
, description_remover_table
[i
].type
) )
936 description_remover_table
[i
].func( sample
);
941 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stts
, stts
, isom_stbl_t
)
942 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ctts
, ctts
, isom_stbl_t
)
943 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_cslg
, cslg
, isom_stbl_t
)
944 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsc
, stsc
, isom_stbl_t
)
945 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsz
, stsz
, isom_stbl_t
)
946 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stz2
, stz2
, isom_stbl_t
)
947 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stss
, stss
, isom_stbl_t
)
948 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stps
, stps
, isom_stbl_t
)
949 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stco
, stco
, isom_stbl_t
)
951 static void isom_remove_sdtp( isom_sdtp_t
*sdtp
)
955 lsmash_remove_list( sdtp
->list
, NULL
);
958 if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
959 REMOVE_BOX( sdtp
, isom_stbl_t
);
960 else if( lsmash_check_box_type_identical( sdtp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
961 REMOVE_BOX( sdtp
, isom_traf_t
);
968 static void isom_remove_sgpd( isom_sgpd_t
*sgpd
)
972 lsmash_remove_list( sgpd
->list
, NULL
);
975 if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
976 REMOVE_BOX_IN_LIST( sgpd
, isom_stbl_t
);
977 else if( lsmash_check_box_type_identical( sgpd
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
978 REMOVE_BOX_IN_LIST( sgpd
, isom_traf_t
);
985 static void isom_remove_sbgp( isom_sbgp_t
*sbgp
)
989 lsmash_remove_list( sbgp
->list
, NULL
);
992 if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_STBL
) )
993 REMOVE_BOX_IN_LIST( sbgp
, isom_stbl_t
);
994 else if( lsmash_check_box_type_identical( sbgp
->parent
->type
, ISOM_BOX_TYPE_TRAF
) )
995 REMOVE_BOX_IN_LIST( sbgp
, isom_traf_t
);
1002 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stbl
, stbl
, isom_minf_t
)
1004 static void isom_remove_dref_entry( isom_dref_entry_t
*data_entry
)
1008 lsmash_free( data_entry
->name
);
1009 lsmash_free( data_entry
->location
);
1010 isom_remove_box_in_predefined_list( data_entry
, offsetof( isom_dref_t
, list
) );
1013 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dref
, dref
, isom_dinf_t
)
1014 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dinf
, dinf
, isom_minf_t
)
1015 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_minf
, minf
, isom_mdia_t
)
1016 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdia
, mdia
, isom_trak_t
)
1018 static void isom_remove_chpl_entry( isom_chpl_entry_t
*data
)
1022 lsmash_free( data
->chapter_name
);
1023 lsmash_free( data
);
1025 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_chpl
, chpl
, isom_udta_t
, isom_remove_chpl_entry
)
1027 static void isom_remove_keys_entry( isom_keys_entry_t
*data
)
1031 lsmash_free( data
->key_value
);
1032 lsmash_free( data
);
1034 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_keys
, keys
, isom_meta_t
, isom_remove_keys_entry
)
1036 static void isom_remove_mean( isom_mean_t
*mean
)
1040 lsmash_free( mean
->meaning_string
);
1041 REMOVE_BOX( mean
, isom_metaitem_t
);
1044 static void isom_remove_name( isom_name_t
*name
)
1048 lsmash_free( name
->name
);
1049 REMOVE_BOX( name
, isom_metaitem_t
);
1052 static void isom_remove_data( isom_data_t
*data
)
1056 lsmash_free( data
->value
);
1057 REMOVE_BOX( data
, isom_metaitem_t
);
1060 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_metaitem
, metaitem
, isom_ilst_t
)
1061 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_ilst
, ilst
, isom_meta_t
)
1063 static void isom_remove_meta( isom_meta_t
*meta
)
1069 if( lsmash_check_box_type_identical( meta
->parent
->type
, LSMASH_BOX_TYPE_UNSPECIFIED
) )
1070 REMOVE_BOX( meta
, lsmash_file_t
);
1071 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1072 REMOVE_BOX( meta
, isom_moov_t
);
1073 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1074 REMOVE_BOX( meta
, isom_trak_t
);
1075 else if( lsmash_check_box_type_identical( meta
->parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1076 REMOVE_BOX( meta
, isom_udta_t
);
1083 static void isom_remove_cprt( isom_cprt_t
*cprt
)
1087 lsmash_free( cprt
->notice
);
1088 REMOVE_BOX_IN_LIST( cprt
, isom_udta_t
);
1091 static void isom_remove_udta( isom_udta_t
*udta
)
1097 if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1098 REMOVE_BOX( udta
, isom_moov_t
);
1099 else if( lsmash_check_box_type_identical( udta
->parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1100 REMOVE_BOX( udta
, isom_trak_t
);
1107 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_WLOC
, WLOC
, isom_udta_t
)
1108 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_LOOP
, LOOP
, isom_udta_t
)
1109 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_SelO
, SelO
, isom_udta_t
)
1110 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_AllF
, AllF
, isom_udta_t
)
1112 static void isom_remove_ctab( isom_ctab_t
*ctab
)
1116 lsmash_free( ctab
->color_table
.array
);
1117 if( ctab
->parent
&& lsmash_check_box_type_identical( ctab
->parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1118 REMOVE_BOX( ctab
, isom_moov_t
);
1121 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvex
, mvex
, isom_moov_t
)
1122 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvhd
, mvhd
, isom_moov_t
)
1123 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mehd
, mehd
, isom_mvex_t
)
1124 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_trex
, trex
, isom_mvex_t
)
1125 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_moov
, moov
, lsmash_file_t
)
1126 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdat
, mdat
, lsmash_file_t
)
1127 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfhd
, mfhd
, isom_moof_t
)
1128 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfhd
, tfhd
, isom_traf_t
)
1129 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfdt
, tfdt
, isom_traf_t
)
1131 static void isom_remove_trun( isom_trun_t
*trun
)
1135 lsmash_remove_list( trun
->optional
, NULL
);
1136 REMOVE_BOX_IN_LIST( trun
, isom_traf_t
);
1139 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_traf
, traf
, isom_moof_t
)
1140 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_moof
, moof
, lsmash_file_t
)
1142 static void isom_remove_free( isom_free_t
*skip
)
1146 lsmash_free( skip
->data
);
1147 isom_remove_predefined_box( skip
, offsetof( lsmash_file_t
, free
) );
1149 #define isom_remove_skip isom_remove_free
1151 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfra
, mfra
, lsmash_file_t
)
1152 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfro
, mfro
, isom_mfra_t
)
1153 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_tfra
, tfra
, isom_mfra_t
)
1154 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_sidx
, sidx
, lsmash_file_t
)
1156 static void isom_remove_styp( isom_styp_t
*styp
)
1160 lsmash_free( styp
->compatible_brands
);
1161 REMOVE_BOX_IN_LIST( styp
, lsmash_file_t
);
1164 /* box size updater */
1165 uint64_t isom_update_box_size( void *opaque_box
)
1167 assert( opaque_box
);
1168 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
1169 if( box
->manager
& LSMASH_WRITTEN_BOX
)
1170 /* No need to calculate the size of this box since the size is already decided and fixed. */
1175 /* Calculate the size of this box excluding its children with a fake bytestream writer. */
1177 lsmash_bs_t fake_bs
= { NULL
};
1178 if( box
->write( &fake_bs
, box
) == 0 )
1179 size
= lsmash_bs_get_valid_data_size( &fake_bs
);
1181 /* Calculate the size of the children if no error. */
1182 if( size
>= ISOM_BASEBOX_COMMON_SIZE
)
1184 for( lsmash_entry_t
*entry
= box
->extensions
.head
; entry
; entry
= entry
->next
)
1186 size
+= isom_update_box_size( entry
->data
);
1187 /* Check large size. */
1188 if( size
> UINT32_MAX
)
1192 /* TODO: add error handling. */
1199 /* box adding functions */
1200 #define ATTACH_EXACTLY_ONE_BOX_TO_PARENT( box_name, parent_type ) \
1203 isom_box_t **p = (isom_box_t **)(((int8_t *)box_name->parent) \
1204 + offsetof( parent_type, box_name )); \
1206 *p = (isom_box_t *)box_name; \
1209 #define INIT_BOX_COMMON0( box_name, parent, box_type, precedence ) \
1210 const isom_extension_destructor_t isom_remove_##box_name = NULL; \
1211 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1212 #define INIT_BOX_COMMON1( box_name, parent, box_type, precedence ) \
1213 isom_init_box_common( box_name, parent, box_type, precedence, isom_remove_##box_name )
1215 #define CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1218 isom_##box_name##_t *box_name = lsmash_malloc_zero( sizeof(isom_##box_name##_t) ); \
1221 INIT_BOX_COMMON ## has_destructor( box_name, parent, box_type, precedence ); \
1222 if( isom_add_box_to_extension_list( parent, box_name ) < 0 ) \
1224 lsmash_free( box_name ); \
1227 #define CREATE_LIST_BOX( box_name, parent, box_type, precedence, has_destructor ) \
1228 CREATE_BOX( box_name, parent, box_type, precedence, has_destructor ); \
1229 box_name->list = lsmash_create_entry_list(); \
1230 if( !box_name->list ) \
1232 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1236 #define ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1237 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1238 if( !(parent)->box_name ) \
1239 (parent)->box_name = box_name
1240 #define ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, BOX_CREATOR ) \
1241 BOX_CREATOR( box_name, parent, box_type, precedence, 1 ); \
1242 if( lsmash_add_entry( &(parent)->box_name##_list, box_name ) < 0 ) \
1244 lsmash_remove_entry_tail( &(parent)->extensions, isom_remove_##box_name ); \
1248 #define ADD_BOX( box_name, parent, box_type, precedence ) \
1249 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1250 #define ADD_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1251 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_BOX )
1252 #define ADD_LIST_BOX( box_name, parent, box_type, precedence ) \
1253 ADD_BOX_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1254 #define ADD_LIST_BOX_IN_LIST( box_name, parent, box_type, precedence ) \
1255 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent, box_type, precedence, CREATE_LIST_BOX )
1257 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ... ) CALL_FUNC_DEFAULT_ARGS( DEFINE_SIMPLE_BOX_ADDER_TEMPLATE, __VA_ARGS__ )
1258 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, parent_type ) \
1259 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1261 ADDER( box_name, parent_name, box_type, precedence ); \
1264 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5( ADDER, box_name, parent_name, box_type, precedence ) \
1265 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, isom_##parent_name##_t )
1267 #define DEFINE_SIMPLE_BOX_ADDER( func_name, ... ) \
1268 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX, __VA_ARGS__ )
1269 #define DEFINE_SIMPLE_BOX_IN_LIST_ADDER( func_name, ... ) \
1270 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX_IN_LIST, __VA_ARGS__ )
1271 #define DEFINE_SIMPLE_LIST_BOX_ADDER( func_name, ... ) \
1272 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_LIST_BOX, __VA_ARGS__ )
1274 #define DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( func_name, box_name, parent_name, box_type, precedence, has_destructor, parent_type ) \
1275 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1277 CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ); \
1281 lsmash_file_t
*isom_add_file( lsmash_root_t
*root
)
1283 lsmash_file_t
*file
= lsmash_malloc_zero( sizeof(lsmash_file_t
) );
1286 file
->class = &lsmash_box_class
;
1289 file
->parent
= (isom_box_t
*)root
;
1290 file
->destruct
= (isom_extension_destructor_t
)isom_remove_file
;
1292 file
->type
= LSMASH_BOX_TYPE_UNSPECIFIED
;
1293 if( isom_add_box_to_extension_list( root
, file
) < 0 )
1295 lsmash_free( file
);
1298 if( lsmash_add_entry( &root
->file_list
, file
) < 0 )
1300 lsmash_remove_entry_tail( &root
->extensions
, isom_remove_file
);
1306 isom_tref_type_t
*isom_add_track_reference_type( isom_tref_t
*tref
, isom_track_reference_type type
)
1310 isom_tref_type_t
*ref
= lsmash_malloc_zero( sizeof(isom_tref_type_t
) );
1313 /* Initialize common fields. */
1314 ref
->root
= tref
->root
;
1315 ref
->file
= tref
->file
;
1316 ref
->parent
= (isom_box_t
*)tref
;
1318 ref
->type
= lsmash_form_iso_box_type( type
);
1319 ref
->precedence
= LSMASH_BOX_PRECEDENCE_ISOM_TREF_TYPE
;
1320 ref
->destruct
= (isom_extension_destructor_t
)isom_remove_track_reference_type
;
1321 isom_set_box_writer( (isom_box_t
*)ref
);
1322 if( isom_add_box_to_extension_list( tref
, ref
) < 0 )
1327 if( lsmash_add_entry( &tref
->ref_list
, ref
) < 0 )
1329 lsmash_remove_entry_tail( &tref
->extensions
, isom_remove_track_reference_type
);
1335 DEFINE_SIMPLE_BOX_ADDER( isom_add_terminator
, terminator
, wave
, QT_BOX_TYPE_TERMINATOR
, LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
)
1336 DEFINE_SIMPLE_BOX_ADDER( isom_add_frma
, frma
, wave
, QT_BOX_TYPE_FRMA
, LSMASH_BOX_PRECEDENCE_QTFF_FRMA
)
1337 DEFINE_SIMPLE_BOX_ADDER( isom_add_enda
, enda
, wave
, QT_BOX_TYPE_ENDA
, LSMASH_BOX_PRECEDENCE_QTFF_ENDA
)
1338 DEFINE_SIMPLE_BOX_ADDER( isom_add_mp4a
, mp4a
, wave
, QT_BOX_TYPE_MP4A
, LSMASH_BOX_PRECEDENCE_QTFF_MP4A
)
1339 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ftab
, ftab
, tx3g
, ISOM_BOX_TYPE_FTAB
, LSMASH_BOX_PRECEDENCE_ISOM_FTAB
, isom_tx3g_entry_t
)
1340 DEFINE_SIMPLE_BOX_ADDER( isom_add_ftyp
, ftyp
, file
, ISOM_BOX_TYPE_FTYP
, LSMASH_BOX_PRECEDENCE_ISOM_FTYP
, lsmash_file_t
)
1341 DEFINE_SIMPLE_BOX_ADDER( isom_add_moov
, moov
, file
, ISOM_BOX_TYPE_MOOV
, LSMASH_BOX_PRECEDENCE_ISOM_MOOV
, lsmash_file_t
)
1342 DEFINE_SIMPLE_BOX_ADDER( isom_add_mvhd
, mvhd
, moov
, ISOM_BOX_TYPE_MVHD
, LSMASH_BOX_PRECEDENCE_ISOM_MVHD
)
1343 DEFINE_SIMPLE_BOX_ADDER( isom_add_iods
, iods
, moov
, ISOM_BOX_TYPE_IODS
, LSMASH_BOX_PRECEDENCE_ISOM_IODS
)
1345 isom_ctab_t
*isom_add_ctab( void *parent_box
)
1347 /* According to QuickTime File Format Specification, this box is placed inside Movie Box if present.
1348 * However, sometimes this box occurs inside an image description entry or the end of Sample Description Box. */
1351 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1352 CREATE_BOX( ctab
, parent
, QT_BOX_TYPE_CTAB
, LSMASH_BOX_PRECEDENCE_QTFF_CTAB
, 1 );
1353 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1354 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( ctab
, isom_moov_t
);
1358 isom_trak_t
*isom_add_trak( isom_moov_t
*moov
)
1360 if( !moov
|| !moov
->file
)
1362 CREATE_BOX( trak
, moov
, ISOM_BOX_TYPE_TRAK
, LSMASH_BOX_PRECEDENCE_ISOM_TRAK
, 1 );
1363 isom_fragment_t
*fragment
= NULL
;
1364 isom_cache_t
*cache
= lsmash_malloc_zero( sizeof(isom_cache_t
) );
1367 if( moov
->file
->fragment
)
1369 fragment
= lsmash_malloc_zero( sizeof(isom_fragment_t
) );
1372 cache
->fragment
= fragment
;
1374 if( lsmash_add_entry( &moov
->trak_list
, trak
) < 0 )
1376 trak
->cache
= cache
;
1379 lsmash_free( fragment
);
1380 lsmash_free( cache
);
1381 lsmash_remove_entry_tail( &moov
->extensions
, isom_remove_trak
);
1385 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tkhd
, tkhd
, trak
, ISOM_BOX_TYPE_TKHD
, LSMASH_BOX_PRECEDENCE_ISOM_TKHD
)
1386 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tapt
, tapt
, trak
, QT_BOX_TYPE_TAPT
, LSMASH_BOX_PRECEDENCE_QTFF_TAPT
)
1387 DEFINE_SIMPLE_BOX_ADDER ( isom_add_clef
, clef
, tapt
, QT_BOX_TYPE_CLEF
, LSMASH_BOX_PRECEDENCE_QTFF_CLEF
)
1388 DEFINE_SIMPLE_BOX_ADDER ( isom_add_prof
, prof
, tapt
, QT_BOX_TYPE_PROF
, LSMASH_BOX_PRECEDENCE_QTFF_PROF
)
1389 DEFINE_SIMPLE_BOX_ADDER ( isom_add_enof
, enof
, tapt
, QT_BOX_TYPE_ENOF
, LSMASH_BOX_PRECEDENCE_QTFF_ENOF
)
1390 DEFINE_SIMPLE_BOX_ADDER ( isom_add_edts
, edts
, trak
, ISOM_BOX_TYPE_EDTS
, LSMASH_BOX_PRECEDENCE_ISOM_EDTS
)
1391 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_elst
, elst
, edts
, ISOM_BOX_TYPE_ELST
, LSMASH_BOX_PRECEDENCE_ISOM_ELST
)
1392 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tref
, tref
, trak
, ISOM_BOX_TYPE_TREF
, LSMASH_BOX_PRECEDENCE_ISOM_TREF
)
1393 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdia
, mdia
, trak
, ISOM_BOX_TYPE_MDIA
, LSMASH_BOX_PRECEDENCE_ISOM_MDIA
)
1394 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdhd
, mdhd
, mdia
, ISOM_BOX_TYPE_MDHD
, LSMASH_BOX_PRECEDENCE_ISOM_MDHD
)
1396 isom_hdlr_t
*isom_add_hdlr( void *parent_box
)
1400 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1401 CREATE_BOX( hdlr
, parent
, ISOM_BOX_TYPE_HDLR
, LSMASH_BOX_PRECEDENCE_ISOM_HDLR
, 1 );
1402 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
) )
1403 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_mdia_t
);
1404 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1405 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1406 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_meta_t
);
1407 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1408 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_minf_t
);
1414 DEFINE_SIMPLE_BOX_ADDER( isom_add_minf
, minf
, mdia
, ISOM_BOX_TYPE_MINF
, LSMASH_BOX_PRECEDENCE_ISOM_MINF
)
1415 DEFINE_SIMPLE_BOX_ADDER( isom_add_vmhd
, vmhd
, minf
, ISOM_BOX_TYPE_VMHD
, LSMASH_BOX_PRECEDENCE_ISOM_VMHD
)
1416 DEFINE_SIMPLE_BOX_ADDER( isom_add_smhd
, smhd
, minf
, ISOM_BOX_TYPE_SMHD
, LSMASH_BOX_PRECEDENCE_ISOM_SMHD
)
1417 DEFINE_SIMPLE_BOX_ADDER( isom_add_hmhd
, hmhd
, minf
, ISOM_BOX_TYPE_HMHD
, LSMASH_BOX_PRECEDENCE_ISOM_HMHD
)
1418 DEFINE_SIMPLE_BOX_ADDER( isom_add_nmhd
, nmhd
, minf
, ISOM_BOX_TYPE_NMHD
, LSMASH_BOX_PRECEDENCE_ISOM_NMHD
)
1419 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmhd
, gmhd
, minf
, QT_BOX_TYPE_GMHD
, LSMASH_BOX_PRECEDENCE_QTFF_GMHD
)
1420 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmin
, gmin
, gmhd
, QT_BOX_TYPE_GMIN
, LSMASH_BOX_PRECEDENCE_QTFF_GMIN
)
1421 DEFINE_SIMPLE_BOX_ADDER( isom_add_text
, text
, gmhd
, QT_BOX_TYPE_TEXT
, LSMASH_BOX_PRECEDENCE_QTFF_TEXT
)
1423 isom_dinf_t
*isom_add_dinf( void *parent_box
)
1427 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1428 CREATE_BOX( dinf
, parent
, ISOM_BOX_TYPE_DINF
, LSMASH_BOX_PRECEDENCE_ISOM_DINF
, 1 );
1429 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1430 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_minf_t
);
1431 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1432 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1433 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_meta_t
);
1439 isom_dref_entry_t
*isom_add_dref_entry( isom_dref_t
*dref
, lsmash_box_type_t type
)
1443 isom_dref_entry_t
*data
= lsmash_malloc_zero( sizeof(isom_dref_entry_t
) );
1446 isom_init_box_common( data
, dref
, type
, LSMASH_BOX_PRECEDENCE_ISOM_DREF_ENTRY
, isom_remove_dref_entry
);
1447 if( isom_add_box_to_extension_list( dref
, data
) < 0 )
1449 lsmash_free( data
);
1452 if( lsmash_add_entry( &dref
->list
, data
) < 0 )
1454 lsmash_remove_entry_tail( &dref
->extensions
, isom_remove_dref_entry
);
1460 DEFINE_SIMPLE_BOX_ADDER( isom_add_dref
, dref
, dinf
, ISOM_BOX_TYPE_DREF
, LSMASH_BOX_PRECEDENCE_ISOM_DREF
)
1461 DEFINE_SIMPLE_BOX_ADDER( isom_add_stbl
, stbl
, minf
, ISOM_BOX_TYPE_STBL
, LSMASH_BOX_PRECEDENCE_ISOM_STBL
)
1462 DEFINE_SIMPLE_BOX_ADDER( isom_add_stsd
, stsd
, stbl
, ISOM_BOX_TYPE_STSD
, LSMASH_BOX_PRECEDENCE_ISOM_STSD
)
1464 static int isom_add_sample_description_entry
1468 void (*destructor
)( isom_sample_entry_t
* )
1471 if( isom_add_box_to_extension_list( stsd
, description
) < 0 )
1473 lsmash_free( description
);
1474 return LSMASH_ERR_MEMORY_ALLOC
;
1476 if( lsmash_add_entry( &stsd
->list
, description
) < 0 )
1478 lsmash_remove_entry_tail( &stsd
->extensions
, destructor
);
1479 return LSMASH_ERR_MEMORY_ALLOC
;
1484 isom_visual_entry_t
*isom_add_visual_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1487 isom_visual_entry_t
*visual
= lsmash_malloc_zero( sizeof(isom_visual_entry_t
) );
1490 isom_init_box_common( visual
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_visual_description
);
1491 visual
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1492 return isom_add_sample_description_entry( stsd
, visual
, isom_remove_visual_description
) ? NULL
: visual
;
1495 isom_audio_entry_t
*isom_add_audio_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1498 isom_audio_entry_t
*audio
= lsmash_malloc_zero( sizeof(isom_audio_entry_t
) );
1501 isom_init_box_common( audio
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_audio_description
);
1502 audio
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1503 return isom_add_sample_description_entry( stsd
, audio
, isom_remove_audio_description
) ? NULL
: audio
;
1506 isom_qt_text_entry_t
*isom_add_qt_text_description( isom_stsd_t
*stsd
)
1509 isom_qt_text_entry_t
*text
= lsmash_malloc_zero( sizeof(isom_qt_text_entry_t
) );
1512 isom_init_box_common( text
, stsd
, QT_CODEC_TYPE_TEXT_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_qt_text_description
);
1513 return isom_add_sample_description_entry( stsd
, text
, isom_remove_qt_text_description
) ? NULL
: text
;
1516 isom_tx3g_entry_t
*isom_add_tx3g_description( isom_stsd_t
*stsd
)
1519 isom_tx3g_entry_t
*tx3g
= lsmash_malloc_zero( sizeof(isom_tx3g_entry_t
) );
1522 isom_init_box_common( tx3g
, stsd
, ISOM_CODEC_TYPE_TX3G_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_tx3g_description
);
1523 return isom_add_sample_description_entry( stsd
, tx3g
, isom_remove_tx3g_description
) ? NULL
: tx3g
;
1526 isom_esds_t
*isom_add_esds( void *parent_box
)
1528 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1529 int is_qt
= lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
);
1530 lsmash_box_type_t box_type
= is_qt
? QT_BOX_TYPE_ESDS
: ISOM_BOX_TYPE_ESDS
;
1531 uint64_t precedence
= is_qt
? LSMASH_BOX_PRECEDENCE_QTFF_ESDS
: LSMASH_BOX_PRECEDENCE_ISOM_ESDS
;
1532 CREATE_BOX( esds
, parent
, box_type
, precedence
, 1 );
1536 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_glbl
, glbl
, parent_box
, QT_BOX_TYPE_GLBL
, LSMASH_BOX_PRECEDENCE_QTFF_GLBL
, 1, void )
1537 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_clap
, clap
, visual
, ISOM_BOX_TYPE_CLAP
, LSMASH_BOX_PRECEDENCE_ISOM_CLAP
, 0, isom_visual_entry_t
)
1538 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_pasp
, pasp
, visual
, ISOM_BOX_TYPE_PASP
, LSMASH_BOX_PRECEDENCE_ISOM_PASP
, 0, isom_visual_entry_t
)
1539 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_colr
, colr
, visual
, ISOM_BOX_TYPE_COLR
, LSMASH_BOX_PRECEDENCE_ISOM_COLR
, 0, isom_visual_entry_t
)
1540 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_gama
, gama
, visual
, QT_BOX_TYPE_GAMA
, LSMASH_BOX_PRECEDENCE_QTFF_GAMA
, 0, isom_visual_entry_t
)
1541 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_fiel
, fiel
, visual
, QT_BOX_TYPE_FIEL
, LSMASH_BOX_PRECEDENCE_QTFF_FIEL
, 0, isom_visual_entry_t
)
1542 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_cspc
, cspc
, visual
, QT_BOX_TYPE_CSPC
, LSMASH_BOX_PRECEDENCE_QTFF_CSPC
, 0, isom_visual_entry_t
)
1543 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_sgbt
, sgbt
, visual
, QT_BOX_TYPE_SGBT
, LSMASH_BOX_PRECEDENCE_QTFF_SGBT
, 0, isom_visual_entry_t
)
1544 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_stsl
, stsl
, visual
, ISOM_BOX_TYPE_STSL
, LSMASH_BOX_PRECEDENCE_ISOM_STSL
, 0, isom_visual_entry_t
)
1545 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_btrt
, btrt
, visual
, ISOM_BOX_TYPE_BTRT
, LSMASH_BOX_PRECEDENCE_ISOM_BTRT
, 0, isom_visual_entry_t
)
1546 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_wave
, wave
, audio
, QT_BOX_TYPE_WAVE
, LSMASH_BOX_PRECEDENCE_QTFF_WAVE
, 0, isom_audio_entry_t
)
1547 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_chan
, chan
, audio
, QT_BOX_TYPE_CHAN
, LSMASH_BOX_PRECEDENCE_QTFF_CHAN
, 1, isom_audio_entry_t
)
1548 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_srat
, srat
, audio
, ISOM_BOX_TYPE_SRAT
, LSMASH_BOX_PRECEDENCE_ISOM_SRAT
, 0, isom_audio_entry_t
)
1550 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stts
, stts
, stbl
, ISOM_BOX_TYPE_STTS
, LSMASH_BOX_PRECEDENCE_ISOM_STTS
)
1551 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ctts
, ctts
, stbl
, ISOM_BOX_TYPE_CTTS
, LSMASH_BOX_PRECEDENCE_ISOM_CTTS
)
1552 DEFINE_SIMPLE_BOX_ADDER ( isom_add_cslg
, cslg
, stbl
, ISOM_BOX_TYPE_CSLG
, LSMASH_BOX_PRECEDENCE_ISOM_CSLG
)
1553 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stsc
, stsc
, stbl
, ISOM_BOX_TYPE_STSC
, LSMASH_BOX_PRECEDENCE_ISOM_STSC
)
1554 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. */
1555 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stz2
, stz2
, stbl
, ISOM_BOX_TYPE_STZ2
, LSMASH_BOX_PRECEDENCE_ISOM_STZ2
)
1556 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stss
, stss
, stbl
, ISOM_BOX_TYPE_STSS
, LSMASH_BOX_PRECEDENCE_ISOM_STSS
)
1557 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stps
, stps
, stbl
, QT_BOX_TYPE_STPS
, LSMASH_BOX_PRECEDENCE_QTFF_STPS
)
1559 isom_stco_t
*isom_add_stco( isom_stbl_t
*stbl
)
1561 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_STCO
, LSMASH_BOX_PRECEDENCE_ISOM_STCO
);
1562 stco
->large_presentation
= 0;
1566 isom_stco_t
*isom_add_co64( isom_stbl_t
*stbl
)
1568 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_CO64
, LSMASH_BOX_PRECEDENCE_ISOM_CO64
);
1569 stco
->large_presentation
= 1;
1573 isom_sdtp_t
*isom_add_sdtp( isom_box_t
*parent
)
1577 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1579 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1580 ADD_LIST_BOX( sdtp
, stbl
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1583 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1585 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1586 ADD_LIST_BOX( sdtp
, traf
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1593 isom_sgpd_t
*isom_add_sgpd( void *parent_box
)
1597 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1598 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1600 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1601 ADD_LIST_BOX_IN_LIST( sgpd
, stbl
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1604 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1606 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1607 ADD_LIST_BOX_IN_LIST( sgpd
, traf
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1614 isom_sbgp_t
*isom_add_sbgp( void *parent_box
)
1618 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1619 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1621 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1622 ADD_LIST_BOX_IN_LIST( sbgp
, stbl
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1625 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1627 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1628 ADD_LIST_BOX_IN_LIST( sbgp
, traf
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1635 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_chpl
, chpl
, udta
, ISOM_BOX_TYPE_CHPL
, LSMASH_BOX_PRECEDENCE_ISOM_CHPL
)
1637 isom_metaitem_t
*isom_add_metaitem( isom_ilst_t
*ilst
, lsmash_itunes_metadata_item item
)
1641 lsmash_box_type_t type
= lsmash_form_iso_box_type( item
);
1642 ADD_BOX_IN_LIST( metaitem
, ilst
, type
, LSMASH_BOX_PRECEDENCE_ISOM_METAITEM
);
1646 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mean
, mean
, metaitem
, ISOM_BOX_TYPE_MEAN
, LSMASH_BOX_PRECEDENCE_ISOM_MEAN
)
1647 DEFINE_SIMPLE_BOX_ADDER ( isom_add_name
, name
, metaitem
, ISOM_BOX_TYPE_NAME
, LSMASH_BOX_PRECEDENCE_ISOM_NAME
)
1648 DEFINE_SIMPLE_BOX_ADDER ( isom_add_data
, data
, metaitem
, ISOM_BOX_TYPE_DATA
, LSMASH_BOX_PRECEDENCE_ISOM_DATA
)
1649 DEFINE_SIMPLE_BOX_ADDER ( isom_add_ilst
, ilst
, meta
, ISOM_BOX_TYPE_ILST
, LSMASH_BOX_PRECEDENCE_ISOM_ILST
)
1650 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_keys
, keys
, meta
, QT_BOX_TYPE_KEYS
, LSMASH_BOX_PRECEDENCE_QTFF_KEYS
)
1652 isom_meta_t
*isom_add_meta( void *parent_box
)
1656 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1657 CREATE_BOX( meta
, parent
, ISOM_BOX_TYPE_META
, LSMASH_BOX_PRECEDENCE_ISOM_META
, 1 );
1658 if( parent
->file
== (lsmash_file_t
*)parent
)
1659 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, lsmash_file_t
);
1660 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1661 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_moov_t
);
1662 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1663 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_trak_t
);
1664 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1665 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_udta_t
);
1671 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_cprt
, cprt
, udta
, ISOM_BOX_TYPE_CPRT
, LSMASH_BOX_PRECEDENCE_ISOM_CPRT
)
1673 isom_udta_t
*isom_add_udta( void *parent_box
)
1677 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1678 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1680 isom_moov_t
*moov
= (isom_moov_t
*)parent
;
1681 ADD_BOX( udta
, moov
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1684 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1686 isom_trak_t
*trak
= (isom_trak_t
*)parent
;
1687 ADD_BOX( udta
, trak
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1694 DEFINE_SIMPLE_BOX_ADDER ( isom_add_WLOC
, WLOC
, udta
, QT_BOX_TYPE_WLOC
, LSMASH_BOX_PRECEDENCE_QTFF_WLOC
)
1695 DEFINE_SIMPLE_BOX_ADDER ( isom_add_LOOP
, LOOP
, udta
, QT_BOX_TYPE_LOOP
, LSMASH_BOX_PRECEDENCE_QTFF_LOOP
)
1696 DEFINE_SIMPLE_BOX_ADDER ( isom_add_SelO
, SelO
, udta
, QT_BOX_TYPE_SELO
, LSMASH_BOX_PRECEDENCE_QTFF_SELO
)
1697 DEFINE_SIMPLE_BOX_ADDER ( isom_add_AllF
, AllF
, udta
, QT_BOX_TYPE_ALLF
, LSMASH_BOX_PRECEDENCE_QTFF_ALLF
)
1698 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mvex
, mvex
, moov
, ISOM_BOX_TYPE_MVEX
, LSMASH_BOX_PRECEDENCE_ISOM_MVEX
)
1699 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mehd
, mehd
, mvex
, ISOM_BOX_TYPE_MEHD
, LSMASH_BOX_PRECEDENCE_ISOM_MEHD
)
1700 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trex
, trex
, mvex
, ISOM_BOX_TYPE_TREX
, LSMASH_BOX_PRECEDENCE_ISOM_TREX
)
1701 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_moof
, moof
, file
, ISOM_BOX_TYPE_MOOF
, LSMASH_BOX_PRECEDENCE_ISOM_MOOF
, lsmash_file_t
)
1702 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfhd
, mfhd
, moof
, ISOM_BOX_TYPE_MFHD
, LSMASH_BOX_PRECEDENCE_ISOM_MFHD
)
1703 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_traf
, traf
, moof
, ISOM_BOX_TYPE_TRAF
, LSMASH_BOX_PRECEDENCE_ISOM_TRAF
)
1704 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfhd
, tfhd
, traf
, ISOM_BOX_TYPE_TFHD
, LSMASH_BOX_PRECEDENCE_ISOM_TFHD
)
1705 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfdt
, tfdt
, traf
, ISOM_BOX_TYPE_TFDT
, LSMASH_BOX_PRECEDENCE_ISOM_TFDT
)
1706 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trun
, trun
, traf
, ISOM_BOX_TYPE_TRUN
, LSMASH_BOX_PRECEDENCE_ISOM_TRUN
)
1707 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfra
, mfra
, file
, ISOM_BOX_TYPE_MFRA
, LSMASH_BOX_PRECEDENCE_ISOM_MFRA
, lsmash_file_t
)
1708 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_tfra
, tfra
, mfra
, ISOM_BOX_TYPE_TFRA
, LSMASH_BOX_PRECEDENCE_ISOM_TFRA
)
1709 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfro
, mfro
, mfra
, ISOM_BOX_TYPE_MFRO
, LSMASH_BOX_PRECEDENCE_ISOM_MFRO
)
1711 isom_mdat_t
*isom_add_mdat( lsmash_file_t
*file
)
1713 assert( !file
->mdat
);
1714 CREATE_BOX( mdat
, file
, ISOM_BOX_TYPE_MDAT
, LSMASH_BOX_PRECEDENCE_ISOM_MDAT
, 1 );
1719 isom_free_t
*isom_add_free( void *parent_box
)
1723 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1724 if( parent
->file
== (lsmash_file_t
*)parent
)
1726 lsmash_file_t
*file
= (lsmash_file_t
*)parent
;
1727 CREATE_BOX( skip
, file
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1732 CREATE_BOX( skip
, parent
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1736 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_styp
, styp
, file
, ISOM_BOX_TYPE_STYP
, LSMASH_BOX_PRECEDENCE_ISOM_STYP
, lsmash_file_t
)
1738 isom_sidx_t
*isom_add_sidx( lsmash_file_t
*file
)
1740 ADD_LIST_BOX_IN_LIST( sidx
, file
, ISOM_BOX_TYPE_SIDX
, LSMASH_BOX_PRECEDENCE_ISOM_SIDX
);
1744 #undef ATTACH_EXACTLY_ONE_BOX_TO_PARENT
1746 #undef CREATE_LIST_BOX
1747 #undef ADD_BOX_TEMPLATE
1748 #undef ADD_BOX_IN_LIST_TEMPLATE
1750 #undef ADD_BOX_IN_LIST
1752 #undef ADD_LIST_BOX_IN_LIST
1753 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE
1754 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6
1755 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5
1756 #undef DEFINE_SIMPLE_BOX_ADDER
1757 #undef DEFINE_SIMPLE_BOX_IN_LIST_ADDER
1758 #undef DEFINE_SIMPLE_LIST_BOX_ADDER
1760 static int fake_file_read
1767 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1769 if( stream
->pos
+ size
> stream
->size
)
1770 read_size
= stream
->size
- stream
->pos
;
1773 memcpy( buf
, stream
->data
+ stream
->pos
, read_size
);
1774 stream
->pos
+= read_size
;
1778 static int64_t fake_file_seek
1785 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1786 if( whence
== SEEK_SET
)
1787 stream
->pos
= offset
;
1788 else if( whence
== SEEK_CUR
)
1789 stream
->pos
+= offset
;
1790 else if( whence
== SEEK_END
)
1791 stream
->pos
= stream
->size
+ offset
;
1795 /* Public functions */
1796 lsmash_root_t
*lsmash_create_root( void )
1798 lsmash_root_t
*root
= lsmash_malloc_zero( sizeof(lsmash_root_t
) );
1805 void lsmash_destroy_root( lsmash_root_t
*root
)
1807 isom_remove_box_by_itself( root
);
1810 lsmash_extended_box_type_t
lsmash_form_extended_box_type( uint32_t fourcc
, const uint8_t id
[12] )
1812 return (lsmash_extended_box_type_t
){ fourcc
, { id
[0], id
[1], id
[2], id
[3], id
[4], id
[5],
1813 id
[6], id
[7], id
[8], id
[9], id
[10], id
[11] } };
1816 lsmash_box_type_t lsmash_form_box_type
1818 lsmash_compact_box_type_t type
,
1819 lsmash_extended_box_type_t user
1822 return (lsmash_box_type_t
){ type
, user
};
1825 lsmash_box_type_t
lsmash_form_iso_box_type( uint32_t fourcc
)
1827 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_ISO_12_BYTES
) };
1830 lsmash_box_type_t
lsmash_form_qtff_box_type( uint32_t fourcc
)
1832 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_QTFF_12_BYTES
) };
1835 #define CHECK_BOX_TYPE_IDENTICAL( a, b ) \
1836 a.fourcc == b.fourcc \
1837 && a.user.fourcc == b.user.fourcc \
1838 && a.user.id[0] == b.user.id[0] \
1839 && a.user.id[1] == b.user.id[1] \
1840 && a.user.id[2] == b.user.id[2] \
1841 && a.user.id[3] == b.user.id[3] \
1842 && a.user.id[4] == b.user.id[4] \
1843 && a.user.id[5] == b.user.id[5] \
1844 && a.user.id[6] == b.user.id[6] \
1845 && a.user.id[7] == b.user.id[7] \
1846 && a.user.id[8] == b.user.id[8] \
1847 && a.user.id[9] == b.user.id[9] \
1848 && a.user.id[10] == b.user.id[10] \
1849 && a.user.id[11] == b.user.id[11]
1851 int lsmash_check_box_type_identical( lsmash_box_type_t a
, lsmash_box_type_t b
)
1853 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1856 int lsmash_check_codec_type_identical( lsmash_codec_type_t a
, lsmash_codec_type_t b
)
1858 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1861 int lsmash_check_box_type_specified( const lsmash_box_type_t
*box_type
)
1866 return !!(box_type
->fourcc
1867 | box_type
->user
.fourcc
1868 | box_type
->user
.id
[0] | box_type
->user
.id
[1] | box_type
->user
.id
[2] | box_type
->user
.id
[3]
1869 | box_type
->user
.id
[4] | box_type
->user
.id
[5] | box_type
->user
.id
[6] | box_type
->user
.id
[7]
1870 | box_type
->user
.id
[8] | box_type
->user
.id
[9] | box_type
->user
.id
[10] | box_type
->user
.id
[11]);
1873 lsmash_box_t
*lsmash_get_box
1875 lsmash_box_t
*parent
,
1876 const lsmash_box_path_t box_path
[]
1879 lsmash_entry_t
*entry
= isom_get_entry_of_box( parent
, box_path
);
1880 return (lsmash_box_t
*)(entry
? entry
->data
: NULL
);
1883 lsmash_box_t
*lsmash_create_box
1885 lsmash_box_type_t type
,
1891 if( !lsmash_check_box_type_specified( &type
) )
1893 isom_unknown_box_t
*box
= lsmash_malloc_zero( sizeof(isom_unknown_box_t
) );
1898 box
->unknown_size
= size
;
1899 box
->unknown_field
= lsmash_memdup( data
, size
);
1900 if( !box
->unknown_field
)
1908 box
->unknown_size
= 0;
1909 box
->unknown_field
= NULL
;
1912 box
->class = &lsmash_box_class
;
1916 box
->destruct
= (isom_extension_destructor_t
)isom_remove_unknown_box
;
1917 box
->manager
= LSMASH_UNKNOWN_BOX
;
1918 box
->precedence
= precedence
;
1919 box
->size
= ISOM_BASEBOX_COMMON_SIZE
+ size
+ (type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0);
1921 isom_set_box_writer( (isom_box_t
*)box
);
1922 return (lsmash_box_t
*)box
;
1927 lsmash_box_t
*parent
,
1932 /* You cannot add any box without a box being its parent. */
1933 return LSMASH_ERR_FUNCTION_PARAM
;
1934 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1935 return LSMASH_ERR_FUNCTION_PARAM
;
1936 if( parent
->root
== (lsmash_root_t
*)parent
)
1938 /* Only files can be added into any ROOT.
1939 * For backward compatibility, use the active file as the parent. */
1941 parent
= (isom_box_t
*)parent
->file
;
1943 return LSMASH_ERR_FUNCTION_PARAM
;
1945 /* Add a box as a child box. */
1946 box
->root
= parent
->root
;
1947 box
->file
= parent
->file
;
1948 box
->parent
= parent
;
1949 return isom_add_box_to_extension_list( parent
, box
);
1952 int lsmash_add_box_ex
1954 lsmash_box_t
*parent
,
1955 lsmash_box_t
**p_box
1959 /* You cannot add any box without a box being its parent. */
1960 return LSMASH_ERR_FUNCTION_PARAM
;
1961 isom_unknown_box_t
*box
= (isom_unknown_box_t
*)*p_box
;
1962 if( !box
|| box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1963 return LSMASH_ERR_FUNCTION_PARAM
;
1964 if( !(box
->manager
& LSMASH_UNKNOWN_BOX
) )
1965 /* Simply add the box. */
1966 return lsmash_add_box( parent
, *p_box
);
1967 /* Check if the size of the box to be added is valid. */
1968 if( box
->size
!= ISOM_BASEBOX_COMMON_SIZE
+ box
->unknown_size
+ (box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0) )
1969 return LSMASH_ERR_FUNCTION_PARAM
;
1970 if( !parent
->file
|| parent
->file
== (lsmash_file_t
*)box
)
1971 return LSMASH_ERR_FUNCTION_PARAM
;
1972 if( parent
->root
== (lsmash_root_t
*)parent
)
1973 /* Only files can be added into any ROOT.
1974 * For backward compatibility, use the active file as the parent. */
1975 parent
= (isom_box_t
*)parent
->file
;
1976 /* Switch to the fake-file stream mode. */
1977 lsmash_file_t
*file
= parent
->file
;
1978 lsmash_bs_t
*bs_backup
= file
->bs
;
1979 lsmash_bs_t
*bs
= lsmash_bs_create();
1981 return LSMASH_ERR_MEMORY_ALLOC
;
1982 uint8_t *buf
= lsmash_malloc( box
->size
);
1985 lsmash_bs_cleanup( bs
);
1986 return LSMASH_ERR_MEMORY_ALLOC
;
1988 fake_file_stream_t fake_file
=
1994 bs
->stream
= &fake_file
;
1995 bs
->read
= fake_file_read
;
1997 bs
->seek
= fake_file_seek
;
1999 file
->fake_file_mode
= 1;
2000 /* Make the byte string representing the given box. */
2001 LSMASH_SET_BE32( &buf
[0], box
->size
);
2002 LSMASH_SET_BE32( &buf
[4], box
->type
.fourcc
);
2003 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
2005 LSMASH_SET_BE32( &buf
[8], box
->type
.user
.fourcc
);
2006 memcpy( &buf
[12], box
->type
.user
.id
, 12 );
2008 memcpy( buf
+ (uintptr_t)(box
->size
- box
->unknown_size
), box
->unknown_field
, box
->unknown_size
);
2009 /* Add a box as a child box and try to expand into struct format. */
2010 lsmash_box_t dummy
= { 0 };
2011 int ret
= isom_read_box( file
, &dummy
, parent
, 0, 0 );
2013 lsmash_bs_cleanup( bs
);
2014 file
->bs
= bs_backup
; /* Switch back to the normal file stream mode. */
2015 file
->fake_file_mode
= 0;
2018 /* Reorder the added box by 'precedence'. */
2019 *p_box
= (lsmash_box_t
*)parent
->extensions
.tail
->data
;
2020 (*p_box
)->precedence
= box
->precedence
;
2021 isom_reorder_tail_box( parent
);
2022 /* Do also its children by the same way. */
2023 lsmash_entry_list_t extensions
= box
->extensions
;
2024 lsmash_init_entry_list( &box
->extensions
); /* to avoid freeing the children */
2025 isom_remove_box_by_itself( box
);
2026 for( lsmash_entry_t
*entry
= extensions
.head
; entry
; entry
= entry
->next
)
2030 lsmash_box_t
*child
= (lsmash_box_t
*)entry
->data
;
2031 if( lsmash_add_box_ex( *p_box
, &child
) == 0 )
2033 (*p_box
)->size
+= child
->size
;
2034 /* Avoid freeing at the end of this function. */
2038 isom_remove_all_extension_boxes( &extensions
);
2042 void lsmash_destroy_box
2047 isom_remove_box_by_itself( box
);
2050 void lsmash_destroy_children
2056 isom_remove_all_extension_boxes( &box
->extensions
);
2059 int lsmash_get_box_precedence
2062 uint64_t *precedence
2065 if( !box
|| !precedence
)
2066 return LSMASH_ERR_FUNCTION_PARAM
;
2067 *precedence
= box
->precedence
;
2071 lsmash_box_t
*lsmash_root_as_box
2076 return (lsmash_box_t
*)root
;
2079 lsmash_box_t
*lsmash_file_as_box
2084 return (lsmash_box_t
*)file
;
2087 int lsmash_write_top_level_box
2092 if( !box
|| (isom_box_t
*)box
->file
!= box
->parent
)
2093 return LSMASH_ERR_FUNCTION_PARAM
;
2094 int ret
= isom_write_box( box
->file
->bs
, box
);
2097 box
->file
->size
+= box
->size
;
2101 uint8_t *lsmash_export_box
2109 lsmash_bs_t
*bs
= lsmash_bs_create();
2112 if( isom_write_box( bs
, box
) < 0 )
2114 lsmash_bs_cleanup( bs
);
2117 *size
= bs
->buffer
.store
;
2118 uint8_t *data
= bs
->buffer
.data
;
2119 bs
->buffer
.data
= NULL
;
2120 lsmash_bs_cleanup( bs
);