1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2017 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 */
29 #include "box_default.h"
35 #include "codecs/mp4a.h"
36 #include "codecs/mp4sys.h"
38 #include "importer/importer.h"
40 static const lsmash_class_t lsmash_box_class
=
45 const lsmash_box_type_t static_lsmash_box_type_unspecified
= LSMASH_BOX_TYPE_INITIALIZER
;
47 void isom_init_box_common_orig
51 lsmash_box_type_t box_type
,
53 isom_extension_destructor_t destructor
56 isom_box_t
*box
= (isom_box_t
*)_box
;
57 isom_box_t
*parent
= (isom_box_t
*)_parent
;
58 assert( box
&& parent
&& parent
->root
);
59 box
->class = &lsmash_box_class
;
60 box
->root
= parent
->root
;
61 box
->file
= parent
->file
;
63 box
->precedence
= precedence
;
64 box
->destruct
= destructor
;
67 if( !lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) && isom_is_fullbox( box
) )
72 isom_set_box_writer( box
);
75 static void isom_reorder_tail_box( isom_box_t
*parent
)
77 /* Reorder the appended box by 'precedence'. */
78 lsmash_entry_t
*x
= parent
->extensions
.tail
;
79 assert( x
&& x
->data
);
80 uint64_t precedence
= ((isom_box_t
*)x
->data
)->precedence
;
81 for( lsmash_entry_t
*y
= x
->prev
; y
; y
= y
->prev
)
83 isom_box_t
*box
= (isom_box_t
*)y
->data
;
84 if( LSMASH_IS_NON_EXISTING_BOX( box
) || precedence
> box
->precedence
)
86 /* Exchange the entity data of adjacent two entries. */
96 int isom_add_box_to_extension_list( void *parent_box
, void *child_box
)
98 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
99 isom_box_t
*child
= (isom_box_t
*)child_box
;
100 assert( LSMASH_IS_EXISTING_BOX( parent
) && LSMASH_IS_EXISTING_BOX( child
) );
101 /* Append at the end of the list. */
102 if( lsmash_list_add_entry( &parent
->extensions
, child
) < 0 )
103 return LSMASH_ERR_MEMORY_ALLOC
;
104 /* Don't reorder the appended box when the file is opened for reading. */
105 if( LSMASH_IS_NON_EXISTING_BOX( parent
->file
)
106 || (parent
->file
->flags
& LSMASH_FILE_MODE_READ
)
107 || parent
->file
->fake_file_mode
)
109 isom_reorder_tail_box( parent
);
113 void isom_bs_put_basebox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
115 if( box
->size
> UINT32_MAX
)
117 lsmash_bs_put_be32( bs
, 1 );
118 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
119 lsmash_bs_put_be64( bs
, box
->size
); /* largesize */
123 lsmash_bs_put_be32( bs
, (uint32_t)box
->size
);
124 lsmash_bs_put_be32( bs
, box
->type
.fourcc
);
126 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
128 lsmash_bs_put_be32( bs
, box
->type
.user
.fourcc
);
129 lsmash_bs_put_bytes( bs
, 12, box
->type
.user
.id
);
133 void isom_bs_put_fullbox_common( lsmash_bs_t
*bs
, isom_box_t
*box
)
135 isom_bs_put_basebox_common( bs
, box
);
136 lsmash_bs_put_byte( bs
, box
->version
);
137 lsmash_bs_put_be24( bs
, box
->flags
);
140 void isom_bs_put_box_common( lsmash_bs_t
*bs
, void *box
)
147 isom_box_t
*parent
= ((isom_box_t
*)box
)->parent
;
148 if( parent
&& lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
150 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
153 if( isom_is_fullbox( box
) )
154 isom_bs_put_fullbox_common( bs
, (isom_box_t
*)box
);
156 isom_bs_put_basebox_common( bs
, (isom_box_t
*)box
);
159 /* Return 1 if the box is fullbox, Otherwise return 0. */
160 int isom_is_fullbox( const void *box
)
162 const isom_box_t
*current
= (const isom_box_t
*)box
;
163 lsmash_box_type_t type
= current
->type
;
164 static lsmash_box_type_t fullbox_type_table
[50] = { LSMASH_BOX_TYPE_INITIALIZER
};
165 if( !lsmash_check_box_type_specified( &fullbox_type_table
[0] ) )
167 /* Initialize the table. */
169 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SIDX
;
170 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MVHD
;
171 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TKHD
;
172 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_IODS
;
173 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ESDS
;
174 fullbox_type_table
[i
++] = QT_BOX_TYPE_ESDS
;
175 fullbox_type_table
[i
++] = QT_BOX_TYPE_CLEF
;
176 fullbox_type_table
[i
++] = QT_BOX_TYPE_PROF
;
177 fullbox_type_table
[i
++] = QT_BOX_TYPE_ENOF
;
178 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_ELST
;
179 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MDHD
;
180 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HDLR
;
181 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_VMHD
;
182 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SMHD
;
183 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_HMHD
;
184 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NMHD
;
185 fullbox_type_table
[i
++] = QT_BOX_TYPE_GMIN
;
186 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_DREF
;
187 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSD
;
188 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSL
;
189 fullbox_type_table
[i
++] = QT_BOX_TYPE_CHAN
;
190 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SRAT
;
191 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STTS
;
192 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CTTS
;
193 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CSLG
;
194 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSS
;
195 fullbox_type_table
[i
++] = QT_BOX_TYPE_STPS
;
196 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SDTP
;
197 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSC
;
198 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STSZ
;
199 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STZ2
;
200 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_STCO
;
201 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CO64
;
202 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SGPD
;
203 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_SBGP
;
204 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_CHPL
;
205 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_META
;
206 fullbox_type_table
[i
++] = QT_BOX_TYPE_KEYS
;
207 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEAN
;
208 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_NAME
;
209 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MEHD
;
210 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TREX
;
211 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFHD
;
212 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFHD
;
213 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFDT
;
214 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TRUN
;
215 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_TFRA
;
216 fullbox_type_table
[i
++] = ISOM_BOX_TYPE_MFRO
;
217 fullbox_type_table
[i
] = LSMASH_BOX_TYPE_UNSPECIFIED
;
219 for( int i
= 0; lsmash_check_box_type_specified( &fullbox_type_table
[i
] ); i
++ )
220 if( lsmash_check_box_type_identical( type
, fullbox_type_table
[i
] ) )
222 if( current
->parent
)
224 if( lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_DREF
)
225 || (lsmash_check_box_type_identical( type
, ISOM_BOX_TYPE_CPRT
)
226 && lsmash_check_box_type_identical( current
->parent
->type
, ISOM_BOX_TYPE_UDTA
)) )
232 /* Return 1 if the sample type is LPCM audio, Otherwise return 0. */
233 int isom_is_lpcm_audio( const void *box
)
235 const isom_box_t
*current
= (const isom_box_t
*)box
;
236 lsmash_box_type_t type
= current
->type
;
237 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
238 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
239 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
240 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
241 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
242 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
243 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
244 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
245 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
246 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
)
247 || (lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
) && (current
->manager
& LSMASH_AUDIO_DESCRIPTION
));
250 int isom_is_qt_audio( lsmash_codec_type_t type
)
252 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_23NI_AUDIO
)
253 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC3_AUDIO
)
254 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MAC6_AUDIO
)
255 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NONE_AUDIO
)
256 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDM2_AUDIO
)
257 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QDMC_AUDIO
)
258 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_QCLP_AUDIO
)
259 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AC_3_AUDIO
)
260 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_AGSM_AUDIO
)
261 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAC_AUDIO
)
262 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ALAW_AUDIO
)
263 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX2_AUDIO
)
264 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_CDX4_AUDIO
)
265 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVCA_AUDIO
)
266 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_DVI_AUDIO
)
267 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL32_AUDIO
)
268 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FL64_AUDIO
)
269 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IMA4_AUDIO
)
270 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN24_AUDIO
)
271 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_IN32_AUDIO
)
272 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_LPCM_AUDIO
)
273 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP4A_AUDIO
)
274 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_RAW_AUDIO
)
275 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_SOWT_AUDIO
)
276 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_TWOS_AUDIO
)
277 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ULAW_AUDIO
)
278 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_VDVA_AUDIO
)
279 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
280 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
)
281 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
282 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
283 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
284 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_NOT_SPECIFIED
);
287 /* Return 1 if the sample type is uncompressed Y'CbCr video, Otherwise return 0. */
288 int isom_is_uncompressed_ycbcr( lsmash_codec_type_t type
)
290 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_2VUY_VIDEO
)
291 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V210_VIDEO
)
292 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V216_VIDEO
)
293 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V308_VIDEO
)
294 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V408_VIDEO
)
295 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_V410_VIDEO
)
296 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_YUV2_VIDEO
);
299 int isom_is_waveform_audio( lsmash_box_type_t type
)
301 return lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM2_AUDIO
)
302 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_ADPCM17_AUDIO
)
303 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_GSM49_AUDIO
)
304 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_FULLMP3_AUDIO
)
305 || lsmash_check_codec_type_identical( type
, QT_CODEC_TYPE_MP3_AUDIO
);
308 size_t isom_skip_box_common( uint8_t **p_data
)
310 uint8_t *orig
= *p_data
;
311 uint8_t *data
= *p_data
;
312 uint64_t size
= LSMASH_GET_BE32( data
);
313 data
+= ISOM_BASEBOX_COMMON_SIZE
;
316 /* 'size = LSMASH_GET_BE64( data );' is a dead assignment here. */
323 /* TODO: more secure handling */
324 static size_t isom_read_box_size_and_type_from_binary_string( uint8_t **p_data
, uint64_t *size
, lsmash_box_type_t
*type
)
326 uint8_t *orig
= *p_data
;
327 uint8_t *data
= *p_data
;
328 *size
= LSMASH_GET_BE32( &data
[0] );
329 type
->fourcc
= LSMASH_GET_BE32( &data
[4] );
330 data
+= ISOM_BASEBOX_COMMON_SIZE
;
333 *size
= LSMASH_GET_BE64( data
);
337 if( type
->fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
339 type
->user
.fourcc
= LSMASH_GET_BE32( &data
[0] );
340 memcpy( type
->user
.id
, &data
[4], 12 );
345 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
)
347 if( !parent_data
|| !child_size
|| parent_size
< ISOM_BASEBOX_COMMON_SIZE
)
349 uint8_t *data
= parent_data
;
351 lsmash_box_type_t type
;
352 (void)isom_read_box_size_and_type_from_binary_string( &data
, &size
, &type
);
353 if( size
!= parent_size
)
355 uint8_t *end
= parent_data
+ parent_size
;
356 for( uint8_t *pos
= data
; pos
+ ISOM_BASEBOX_COMMON_SIZE
<= end
; )
358 uint32_t offset
= isom_read_box_size_and_type_from_binary_string( &pos
, &size
, &type
);
359 if( lsmash_check_box_type_identical( type
, child_type
) )
364 pos
+= size
- offset
; /* Move to the next box. */
369 static void isom_destruct_extension_binary( void *ext
)
373 isom_box_t
*box
= (isom_box_t
*)ext
;
374 lsmash_free( box
->binary
);
377 int isom_add_extension_binary
380 lsmash_box_type_t box_type
,
386 if( !parent_box
|| !box_data
|| box_size
< ISOM_BASEBOX_COMMON_SIZE
387 || !lsmash_check_box_type_specified( &box_type
) )
388 return LSMASH_ERR_FUNCTION_PARAM
;
389 isom_box_t
*ext
= lsmash_malloc_zero( sizeof(isom_box_t
) );
391 return LSMASH_ERR_MEMORY_ALLOC
;
392 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
393 ext
->class = &lsmash_box_class
;
394 ext
->root
= parent
->root
;
395 ext
->file
= parent
->file
;
396 ext
->parent
= parent
;
397 ext
->manager
= LSMASH_BINARY_CODED_BOX
;
398 ext
->precedence
= precedence
;
399 ext
->size
= box_size
;
400 ext
->type
= box_type
;
401 ext
->binary
= box_data
;
402 ext
->destruct
= isom_destruct_extension_binary
;
403 if( isom_add_box_to_extension_list( parent
, ext
) < 0 )
406 return LSMASH_ERR_MEMORY_ALLOC
;
408 isom_set_box_writer( ext
);
412 void isom_remove_extension_box( isom_box_t
*ext
)
414 if( LSMASH_IS_NON_EXISTING_BOX( ext
) )
417 ext
->destruct( ext
);
418 isom_remove_all_extension_boxes( &ext
->extensions
);
422 void isom_remove_all_extension_boxes( lsmash_entry_list_t
*extensions
)
424 lsmash_list_remove_entries( extensions
);
427 isom_box_t
*isom_get_extension_box( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
429 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
431 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
432 if( LSMASH_IS_NON_EXISTING_BOX( ext
) )
434 if( lsmash_check_box_type_identical( ext
->type
, box_type
) )
437 return (isom_box_t
*)isom_non_existing_unknown();
440 void *isom_get_extension_box_format( lsmash_entry_list_t
*extensions
, lsmash_box_type_t box_type
)
442 for( lsmash_entry_t
*entry
= extensions
->head
; entry
; entry
= entry
->next
)
444 isom_box_t
*ext
= (isom_box_t
*)entry
->data
;
445 if( LSMASH_IS_NON_EXISTING_BOX( ext
)
446 || (ext
->manager
& LSMASH_BINARY_CODED_BOX
)
447 || !lsmash_check_box_type_identical( ext
->type
, box_type
) )
451 return isom_non_existing_unknown();
454 lsmash_entry_t
*isom_get_entry_of_box
456 lsmash_box_t
*parent
,
457 const lsmash_box_path_t box_path
[]
460 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
462 lsmash_entry_t
*entry
= NULL
;
463 const lsmash_box_path_t
*path
= &box_path
[0];
464 while( lsmash_check_box_type_specified( &path
->type
) )
466 entry
= parent
->extensions
.head
;
471 uint32_t number
= path
->number
? path
->number
: 1;
474 isom_box_t
*box
= entry
->data
;
475 if( box
&& lsmash_check_box_type_identical( path
->type
, box
->type
) )
479 /* Found a box. Move to a child box. */
488 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
495 * TODO: To eliminate REMOVE_LIST_BOX_2(), an eliminator should be determined when initializing
496 * the list to which the eliminator belongs. */
497 #define REMOVE_BOX( box_name ) \
498 isom_remove_predefined_box( box_name )
500 #define REMOVE_BOX_IN_LIST( box_name ) \
501 isom_remove_box_in_predefined_list( box_name )
503 #define REMOVE_LIST_BOX_TEMPLATE( REMOVER, box_name ) \
506 lsmash_list_destroy( box_name->list ); \
507 REMOVER( box_name ); \
510 #define REMOVE_LIST_BOX( box_name ) \
511 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX, box_name )
513 #define REMOVE_LIST_BOX_IN_LIST( box_name ) \
514 REMOVE_LIST_BOX_TEMPLATE( REMOVE_BOX_IN_LIST, box_name )
516 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( ... ) \
517 CALL_FUNC_DEFAULT_ARGS( DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE, __VA_ARGS__ )
518 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE_3( REMOVER, box_name, ... ) \
519 static void isom_remove_##box_name( isom_##box_name##_t *box_name ) \
521 REMOVER( box_name, __VA_ARGS__ ); \
523 #define DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE_2( REMOVER, box_name ) \
524 static void isom_remove_##box_name( isom_##box_name##_t *box_name ) \
526 REMOVER( box_name ); \
529 #define DEFINE_SIMPLE_BOX_REMOVER( func_name, box_name ) \
530 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX, box_name )
532 #define DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( func_name, box_name ) \
533 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_BOX_IN_LIST, box_name )
535 #define DEFINE_SIMPLE_LIST_BOX_REMOVER( func_name, box_name ) \
536 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX, box_name )
538 #define DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( func_name, box_name ) \
539 DEFINE_SIMPLE_BOX_REMOVER_TEMPLATE( REMOVE_LIST_BOX_IN_LIST, box_name )
541 static void isom_remove_predefined_box( void *opaque_box
)
543 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
544 if( LSMASH_IS_EXISTING_BOX( box
)
545 && LSMASH_IS_EXISTING_BOX( box
->parent
) )
547 isom_box_t
**p
= (isom_box_t
**)(((int8_t *)box
->parent
) + box
->offset_in_parent
);
549 *p
= box
->nonexist_ptr
;
553 /* We always free boxes through the extension list of the parent box.
554 * Therefore, don't free boxes through any list other than the extension list. */
555 static void isom_remove_box_in_predefined_list( void *opaque_box
)
557 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
558 if( LSMASH_IS_EXISTING_BOX( box
)
559 && LSMASH_IS_EXISTING_BOX( box
->parent
) )
561 lsmash_entry_list_t
*list
= (lsmash_entry_list_t
*)(((int8_t *)box
->parent
) + box
->offset_in_parent
);
563 for( lsmash_entry_t
*entry
= list
->head
; entry
; entry
= entry
->next
)
564 if( box
== entry
->data
)
566 /* We don't free this box here.
567 * Because of freeing an entry of the list here, don't pass the list to free this box.
570 lsmash_list_remove_entry_direct( list
, entry
);
576 /* Remove a box by the pointer containing its address.
577 * In addition, remove from the extension list of the parent box if possible.
578 * Don't call this function within a function freeing one or more entries of any extension list because of double free.
579 * Basically, don't use this function as a callback function. */
580 void isom_remove_box_by_itself( void *opaque_box
)
582 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
583 if( LSMASH_IS_NON_EXISTING_BOX( box
) )
585 if( LSMASH_IS_EXISTING_BOX( box
->parent
) )
587 isom_box_t
*parent
= box
->parent
;
588 for( lsmash_entry_t
*entry
= parent
->extensions
.head
; entry
; entry
= entry
->next
)
589 if( box
== entry
->data
)
591 /* Free the corresponding entry here, therefore don't call this function as a callback function
592 * if a function frees the same entry later and calls this function. */
593 lsmash_list_remove_entry_direct( &parent
->extensions
, entry
);
597 isom_remove_extension_box( box
);
600 void isom_remove_unknown_box( isom_unknown_box_t
*unknown_box
)
602 lsmash_free( unknown_box
->unknown_field
);
605 static void isom_remove_file_abstract( isom_file_abstract_t
*file_abstract
)
607 if( LSMASH_IS_NON_EXISTING_BOX( file_abstract
) )
609 isom_printer_destory_list( file_abstract
);
610 isom_remove_timelines( file_abstract
);
611 lsmash_free( file_abstract
->compatible_brands
);
612 lsmash_bs_cleanup( file_abstract
->bs
);
613 lsmash_importer_destroy( file_abstract
->importer
);
614 if( file_abstract
->fragment
)
616 lsmash_list_destroy( file_abstract
->fragment
->pool
);
617 lsmash_free( file_abstract
->fragment
);
619 REMOVE_BOX_IN_LIST( file_abstract
);
622 static void isom_remove_ftyp( isom_ftyp_t
*ftyp
)
624 lsmash_free( ftyp
->compatible_brands
);
628 static void isom_remove_iods( isom_iods_t
*iods
)
630 if( LSMASH_IS_NON_EXISTING_BOX( iods
) )
632 mp4sys_remove_descriptor( iods
->OD
);
636 static void isom_remove_trak( isom_trak_t
*trak
)
640 isom_remove_sample_pool( trak
->cache
->chunk
.pool
);
641 lsmash_list_destroy( trak
->cache
->roll
.pool
);
642 lsmash_free( trak
->cache
->rap
);
643 lsmash_free( trak
->cache
->fragment
);
644 lsmash_free( trak
->cache
);
646 REMOVE_BOX_IN_LIST( trak
);
649 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tkhd
, tkhd
)
650 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_clef
, clef
)
651 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_prof
, prof
)
652 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enof
, enof
)
653 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tapt
, tapt
)
654 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_edts
, edts
)
655 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tref
, tref
)
656 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_elst
, elst
)
658 static void isom_remove_track_reference_type( isom_tref_type_t
*ref
)
660 lsmash_free( ref
->track_ID
);
661 isom_remove_box_in_predefined_list( ref
);
664 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdhd
, mdhd
)
665 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_vmhd
, vmhd
)
666 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_smhd
, smhd
)
667 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_hmhd
, hmhd
)
668 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_nmhd
, nmhd
)
669 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmhd
, gmhd
)
670 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_gmin
, gmin
)
671 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_text
, text
)
673 static void isom_remove_hdlr( isom_hdlr_t
*hdlr
)
675 lsmash_free( hdlr
->componentName
);
679 static void isom_remove_glbl( isom_glbl_t
*glbl
)
681 lsmash_free( glbl
->header_data
);
684 static void isom_remove_esds( isom_esds_t
*esds
)
686 if( LSMASH_IS_NON_EXISTING_BOX( esds
) )
688 mp4sys_remove_descriptor( esds
->ES
);
691 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ftab
, ftab
)
693 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_frma
, frma
)
694 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_enda
, enda
)
695 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mp4a
, mp4a
)
696 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_terminator
, terminator
)
698 static void isom_remove_chan( isom_chan_t
*chan
)
700 lsmash_free( chan
->channelDescriptions
);
703 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stsd
, stsd
)
705 static void isom_remove_visual_description( isom_sample_entry_t
*description
)
707 isom_visual_entry_t
*visual
= (isom_visual_entry_t
*)description
;
708 lsmash_free( visual
->color_table
.array
);
709 isom_remove_box_in_predefined_list( visual
);
712 static void isom_remove_audio_description( isom_sample_entry_t
*description
)
714 isom_remove_box_in_predefined_list( description
);
717 static void isom_remove_hint_description( isom_sample_entry_t
*description
)
719 isom_hint_entry_t
*hint
= (isom_hint_entry_t
*)description
;
720 isom_remove_box_in_predefined_list( hint
);
723 static void isom_remove_metadata_description( isom_sample_entry_t
*description
)
725 isom_remove_box_in_predefined_list( description
);
728 static void isom_remove_tx3g_description( isom_sample_entry_t
*description
)
730 isom_remove_box_in_predefined_list( description
);
733 static void isom_remove_qt_text_description( isom_sample_entry_t
*description
)
735 isom_qt_text_entry_t
*text
= (isom_qt_text_entry_t
*)description
;
736 lsmash_free( text
->font_name
);
737 isom_remove_box_in_predefined_list( text
);
740 static void isom_remove_mp4s_description( isom_sample_entry_t
*description
)
742 isom_remove_box_in_predefined_list( description
);
745 void isom_remove_sample_description( isom_sample_entry_t
*sample
)
747 if( LSMASH_IS_NON_EXISTING_BOX( sample
) )
749 lsmash_codec_type_t sample_type
= sample
->type
;
750 if( lsmash_check_box_type_identical( sample_type
, LSMASH_CODEC_TYPE_RAW
) )
752 if( sample
->manager
& LSMASH_VIDEO_DESCRIPTION
)
754 isom_remove_visual_description( sample
);
757 else if( sample
->manager
& LSMASH_AUDIO_DESCRIPTION
)
759 isom_remove_audio_description( sample
);
763 static struct description_remover_table_tag
765 lsmash_codec_type_t type
;
766 void (*func
)( isom_sample_entry_t
* );
767 } description_remover_table
[160] = { { LSMASH_CODEC_TYPE_INITIALIZER
, NULL
} };
768 if( !description_remover_table
[0].func
)
770 /* Initialize the table. */
772 #define ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( type, func ) \
773 description_remover_table[i++] = (struct description_remover_table_tag){ type, func }
774 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC1_VIDEO
, isom_remove_visual_description
);
775 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC2_VIDEO
, isom_remove_visual_description
);
776 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC3_VIDEO
, isom_remove_visual_description
);
777 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVC4_VIDEO
, isom_remove_visual_description
);
778 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AVCP_VIDEO
, isom_remove_visual_description
);
779 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HVC1_VIDEO
, isom_remove_visual_description
);
780 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_HEV1_VIDEO
, isom_remove_visual_description
);
781 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVC1_VIDEO
, isom_remove_visual_description
);
782 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC1_VIDEO
, isom_remove_visual_description
);
783 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MVC2_VIDEO
, isom_remove_visual_description
);
784 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4V_VIDEO
, isom_remove_visual_description
);
785 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
786 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCV_VIDEO
, isom_remove_visual_description
);
787 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MJP2_VIDEO
, isom_remove_visual_description
);
788 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_S263_VIDEO
, isom_remove_visual_description
);
789 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_VC_1_VIDEO
, isom_remove_visual_description
);
790 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_2VUY_VIDEO
, isom_remove_visual_description
);
791 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CFHD_VIDEO
, isom_remove_visual_description
);
792 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV10_VIDEO
, isom_remove_visual_description
);
793 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOO_VIDEO
, isom_remove_visual_description
);
794 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVOR_VIDEO
, isom_remove_visual_description
);
795 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVTV_VIDEO
, isom_remove_visual_description
);
796 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVVT_VIDEO
, isom_remove_visual_description
);
797 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_HD10_VIDEO
, isom_remove_visual_description
);
798 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_M105_VIDEO
, isom_remove_visual_description
);
799 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNTG_VIDEO
, isom_remove_visual_description
);
800 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ1_VIDEO
, isom_remove_visual_description
);
801 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SVQ3_VIDEO
, isom_remove_visual_description
);
802 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR0_VIDEO
, isom_remove_visual_description
);
803 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR1_VIDEO
, isom_remove_visual_description
);
804 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR2_VIDEO
, isom_remove_visual_description
);
805 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR3_VIDEO
, isom_remove_visual_description
);
806 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SHR4_VIDEO
, isom_remove_visual_description
);
807 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_WRLE_VIDEO
, isom_remove_visual_description
);
808 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCH_VIDEO
, isom_remove_visual_description
);
809 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCN_VIDEO
, isom_remove_visual_description
);
810 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCS_VIDEO
, isom_remove_visual_description
);
811 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_APCO_VIDEO
, isom_remove_visual_description
);
812 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4H_VIDEO
, isom_remove_visual_description
);
813 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_AP4X_VIDEO
, isom_remove_visual_description
);
814 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_CIVD_VIDEO
, isom_remove_visual_description
);
815 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DRAC_VIDEO
, isom_remove_visual_description
);
816 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVC_VIDEO
, isom_remove_visual_description
);
817 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVCP_VIDEO
, isom_remove_visual_description
);
818 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVPP_VIDEO
, isom_remove_visual_description
);
819 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5N_VIDEO
, isom_remove_visual_description
);
820 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DV5P_VIDEO
, isom_remove_visual_description
);
821 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH2_VIDEO
, isom_remove_visual_description
);
822 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH3_VIDEO
, isom_remove_visual_description
);
823 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH5_VIDEO
, isom_remove_visual_description
);
824 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVH6_VIDEO
, isom_remove_visual_description
);
825 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHP_VIDEO
, isom_remove_visual_description
);
826 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_DVHQ_VIDEO
, isom_remove_visual_description
);
827 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FLIC_VIDEO
, isom_remove_visual_description
);
828 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_GIF_VIDEO
, isom_remove_visual_description
);
829 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H261_VIDEO
, isom_remove_visual_description
);
830 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_H263_VIDEO
, isom_remove_visual_description
);
831 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_JPEG_VIDEO
, isom_remove_visual_description
);
832 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPA_VIDEO
, isom_remove_visual_description
);
833 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MJPB_VIDEO
, isom_remove_visual_description
);
834 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_PNG_VIDEO
, isom_remove_visual_description
);
835 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RLE_VIDEO
, isom_remove_visual_description
);
836 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_RPZA_VIDEO
, isom_remove_visual_description
);
837 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TGA_VIDEO
, isom_remove_visual_description
);
838 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TIFF_VIDEO
, isom_remove_visual_description
);
839 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRA_VIDEO
, isom_remove_visual_description
);
840 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULRG_VIDEO
, isom_remove_visual_description
);
841 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY2_VIDEO
, isom_remove_visual_description
);
842 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULY0_VIDEO
, isom_remove_visual_description
);
843 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH2_VIDEO
, isom_remove_visual_description
);
844 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_ULH0_VIDEO
, isom_remove_visual_description
);
845 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_UQY2_VIDEO
, isom_remove_visual_description
);
846 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V210_VIDEO
, isom_remove_visual_description
);
847 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V216_VIDEO
, isom_remove_visual_description
);
848 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V308_VIDEO
, isom_remove_visual_description
);
849 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V408_VIDEO
, isom_remove_visual_description
);
850 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_V410_VIDEO
, isom_remove_visual_description
);
851 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_YUV2_VIDEO
, isom_remove_visual_description
);
852 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
853 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_AC_3_AUDIO
, isom_remove_audio_description
);
854 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ALAC_AUDIO
, isom_remove_audio_description
);
855 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSEL_AUDIO
, isom_remove_audio_description
);
856 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSDL_AUDIO
, isom_remove_audio_description
);
857 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSC_AUDIO
, isom_remove_audio_description
);
858 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSE_AUDIO
, isom_remove_audio_description
);
859 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSH_AUDIO
, isom_remove_audio_description
);
860 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSL_AUDIO
, isom_remove_audio_description
);
861 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DTSX_AUDIO
, isom_remove_audio_description
);
862 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_EC_3_AUDIO
, isom_remove_audio_description
);
863 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAMR_AUDIO
, isom_remove_audio_description
);
864 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWB_AUDIO
, isom_remove_audio_description
);
865 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_MP4A_AUDIO
, isom_remove_audio_description
);
866 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_23NI_AUDIO
, isom_remove_audio_description
);
867 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NONE_AUDIO
, isom_remove_audio_description
);
868 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_LPCM_AUDIO
, isom_remove_audio_description
);
869 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_SOWT_AUDIO
, isom_remove_audio_description
);
870 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
871 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL32_AUDIO
, isom_remove_audio_description
);
872 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_FL64_AUDIO
, isom_remove_audio_description
);
873 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN24_AUDIO
, isom_remove_audio_description
);
874 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_IN32_AUDIO
, isom_remove_audio_description
);
875 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_NOT_SPECIFIED
, isom_remove_audio_description
);
876 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_DRA1_AUDIO
, isom_remove_audio_description
);
877 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_ENCA_AUDIO
, isom_remove_audio_description
);
878 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G719_AUDIO
, isom_remove_audio_description
);
879 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_G726_AUDIO
, isom_remove_audio_description
);
880 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M4AE_AUDIO
, isom_remove_audio_description
);
881 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLPA_AUDIO
, isom_remove_audio_description
);
882 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SAWP_AUDIO
, isom_remove_audio_description
);
883 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SEVC_AUDIO
, isom_remove_audio_description
);
884 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SQCP_AUDIO
, isom_remove_audio_description
);
885 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SSMV_AUDIO
, isom_remove_audio_description
);
886 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TWOS_AUDIO
, isom_remove_audio_description
);
887 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_FDP_HINT
, isom_remove_hint_description
);
888 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_M2TS_HINT
, isom_remove_hint_description
);
889 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PM2T_HINT
, isom_remove_hint_description
);
890 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_PRTP_HINT
, isom_remove_hint_description
);
891 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RM2T_HINT
, isom_remove_hint_description
);
892 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RRTP_HINT
, isom_remove_hint_description
);
893 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RSRP_HINT
, isom_remove_hint_description
);
894 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_RTP_HINT
, isom_remove_hint_description
);
895 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SM2T_HINT
, isom_remove_hint_description
);
896 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SRTP_HINT
, isom_remove_hint_description
);
897 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_IXSE_META
, isom_remove_metadata_description
);
898 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METT_META
, isom_remove_metadata_description
);
899 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_METX_META
, isom_remove_metadata_description
);
900 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MLIX_META
, isom_remove_metadata_description
);
901 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_OKSD_META
, isom_remove_metadata_description
);
902 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_SVCM_META
, isom_remove_metadata_description
);
903 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TEXT_META
, isom_remove_metadata_description
);
904 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_URIM_META
, isom_remove_metadata_description
);
905 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_XML_META
, isom_remove_metadata_description
);
906 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_TX3G_TEXT
, isom_remove_tx3g_description
);
907 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( QT_CODEC_TYPE_TEXT_TEXT
, isom_remove_qt_text_description
);
908 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( ISOM_CODEC_TYPE_MP4S_SYSTEM
, isom_remove_mp4s_description
);
909 ADD_DESCRIPTION_REMOVER_TABLE_ELEMENT( LSMASH_CODEC_TYPE_UNSPECIFIED
, NULL
);
911 for( int i
= 0; description_remover_table
[i
].func
; i
++ )
912 if( lsmash_check_codec_type_identical( sample_type
, description_remover_table
[i
].type
) )
914 description_remover_table
[i
].func( sample
);
919 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stts
, stts
)
920 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_ctts
, ctts
)
921 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_cslg
, cslg
)
922 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsc
, stsc
)
923 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stsz
, stsz
)
924 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stz2
, stz2
)
925 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stss
, stss
)
926 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stps
, stps
)
927 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_stco
, stco
)
929 static void isom_remove_sdtp( isom_sdtp_t
*sdtp
)
931 if( LSMASH_IS_NON_EXISTING_BOX( sdtp
) )
933 lsmash_list_destroy( sdtp
->list
);
937 static void isom_remove_sgpd( isom_sgpd_t
*sgpd
)
939 if( LSMASH_IS_NON_EXISTING_BOX( sgpd
) )
941 lsmash_list_destroy( sgpd
->list
);
942 REMOVE_BOX_IN_LIST( sgpd
);
945 static void isom_remove_sbgp( isom_sbgp_t
*sbgp
)
947 if( LSMASH_IS_NON_EXISTING_BOX( sbgp
) )
949 lsmash_list_destroy( sbgp
->list
);
950 REMOVE_BOX_IN_LIST( sbgp
);
953 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_stbl
, stbl
)
955 static void isom_remove_dref_entry( isom_dref_entry_t
*data_entry
)
957 lsmash_free( data_entry
->name
);
958 lsmash_free( data_entry
->location
);
959 isom_remove_box_in_predefined_list( data_entry
);
962 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dref
, dref
)
963 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_dinf
, dinf
)
964 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_minf
, minf
)
965 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdia
, mdia
)
966 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_chpl
, chpl
)
967 DEFINE_SIMPLE_LIST_BOX_REMOVER( isom_remove_keys
, keys
)
969 static void isom_remove_mean( isom_mean_t
*mean
)
971 lsmash_free( mean
->meaning_string
);
975 static void isom_remove_name( isom_name_t
*name
)
977 lsmash_free( name
->name
);
981 static void isom_remove_data( isom_data_t
*data
)
983 lsmash_free( data
->value
);
987 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_metaitem
, metaitem
)
988 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_ilst
, ilst
)
989 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_meta
, meta
)
991 static void isom_remove_cprt( isom_cprt_t
*cprt
)
993 lsmash_free( cprt
->notice
);
994 REMOVE_BOX_IN_LIST( cprt
);
997 static void isom_remove_rtp( isom_rtp_t
*rtp
)
999 lsmash_free( rtp
->sdptext
);
1003 static void isom_remove_sdp( isom_sdp_t
*sdp
)
1005 lsmash_free( sdp
->sdptext
);
1009 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_udta
, udta
)
1010 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_WLOC
, WLOC
)
1011 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_LOOP
, LOOP
)
1012 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_SelO
, SelO
)
1013 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_AllF
, AllF
)
1014 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_hnti
, hnti
)
1016 static void isom_remove_ctab( isom_ctab_t
*ctab
)
1018 lsmash_free( ctab
->color_table
.array
);
1022 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvex
, mvex
)
1023 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mvhd
, mvhd
)
1024 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mehd
, mehd
)
1025 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_trex
, trex
)
1026 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_moov
, moov
)
1027 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mdat
, mdat
)
1028 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfhd
, mfhd
)
1029 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfhd
, tfhd
)
1030 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_tfdt
, tfdt
)
1032 static void isom_remove_trun( isom_trun_t
*trun
)
1034 lsmash_list_destroy( trun
->optional
);
1035 REMOVE_BOX_IN_LIST( trun
);
1038 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_traf
, traf
)
1039 DEFINE_SIMPLE_BOX_IN_LIST_REMOVER( isom_remove_moof
, moof
)
1041 static void isom_remove_free( isom_free_t
*skip
)
1043 lsmash_free( skip
->data
);
1045 #define isom_remove_skip isom_remove_free
1047 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfra
, mfra
)
1048 DEFINE_SIMPLE_BOX_REMOVER( isom_remove_mfro
, mfro
)
1049 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_tfra
, tfra
)
1050 DEFINE_SIMPLE_LIST_BOX_IN_LIST_REMOVER( isom_remove_sidx
, sidx
)
1052 static void isom_remove_styp( isom_styp_t
*styp
)
1054 lsmash_free( styp
->compatible_brands
);
1055 REMOVE_BOX_IN_LIST( styp
);
1058 #define isom_remove_elst_entry lsmash_free
1059 #define isom_remove_stts_entry lsmash_free
1060 #define isom_remove_ctts_entry lsmash_free
1061 #define isom_remove_stsz_entry lsmash_free
1062 #define isom_remove_stz2_entry lsmash_free
1063 #define isom_remove_stss_entry lsmash_free
1064 #define isom_remove_stps_entry lsmash_free
1065 #define isom_remove_sdtp_entry lsmash_free
1066 #define isom_remove_stsc_entry lsmash_free
1067 #define isom_remove_stco_entry lsmash_free
1068 #define isom_remove_co64_entry lsmash_free
1069 #define isom_remove_sgpd_entry lsmash_free
1070 #define isom_remove_sbgp_entry lsmash_free
1071 #define isom_remove_trun_entry lsmash_free
1072 #define isom_remove_tfra_entry lsmash_free
1073 #define isom_remove_sidx_entry lsmash_free
1075 static void isom_remove_ftab_entry( isom_font_record_t
*font_record
)
1079 lsmash_free( font_record
->font_name
);
1080 lsmash_free( font_record
);
1083 static void isom_remove_chpl_entry( isom_chpl_entry_t
*data
)
1087 lsmash_free( data
->chapter_name
);
1088 lsmash_free( data
);
1091 static void isom_remove_keys_entry( isom_keys_entry_t
*data
)
1095 lsmash_free( data
->key_value
);
1096 lsmash_free( data
);
1099 /* box size updater */
1100 uint64_t isom_update_box_size( void *opaque_box
)
1102 isom_box_t
*box
= (isom_box_t
*)opaque_box
;
1103 assert( LSMASH_IS_EXISTING_BOX( box
) );
1104 if( box
->manager
& LSMASH_WRITTEN_BOX
)
1105 /* No need to calculate the size of this box since the size is already decided and fixed. */
1110 /* Calculate the size of this box excluding its children with a fake bytestream writer. */
1112 lsmash_bs_t fake_bs
= { NULL
};
1113 if( box
->write( &fake_bs
, box
) == 0 )
1114 size
= lsmash_bs_get_valid_data_size( &fake_bs
);
1116 /* Calculate the size of the children if no error. */
1117 if( size
>= ISOM_BASEBOX_COMMON_SIZE
)
1119 for( lsmash_entry_t
*entry
= box
->extensions
.head
; entry
; entry
= entry
->next
)
1121 size
+= isom_update_box_size( entry
->data
);
1122 /* Check large size. */
1123 if( size
> UINT32_MAX
)
1127 /* TODO: add error handling. */
1134 /* box adding functions */
1135 #define ATTACH_EXACTLY_ONE_BOX_TO_PARENT( box_name, parent_type ) \
1138 size_t offset_in_parent = offsetof( parent_type, box_name ); \
1139 isom_box_t **p = (isom_box_t **)(((int8_t *)box_name->parent) \
1140 + offset_in_parent); \
1142 if( LSMASH_IS_NON_EXISTING_BOX( *p ) ) \
1144 *p = (isom_box_t *)box_name; \
1145 (*p)->offset_in_parent = offset_in_parent; \
1149 #define ADD_BOX_TO_PREDEFINED_LIST( box_name, parent_name ) \
1150 if( lsmash_list_add_entry( &parent_name->box_name##_list, box_name ) < 0 ) \
1152 lsmash_list_remove_entry_tail( &parent_name->extensions ); \
1153 return isom_non_existing_##box_name(); \
1155 box_name->offset_in_parent = offsetof( isom_##parent_name##_t, box_name##_list )
1157 #define INIT_BOX_COMMON0( box_name, parent_name, box_type, precedence ) \
1158 const isom_extension_destructor_t isom_remove_##box_name = NULL; \
1159 isom_init_box_common( box_name, parent_name, box_type, precedence, isom_remove_##box_name )
1160 #define INIT_BOX_COMMON1( box_name, parent_name, box_type, precedence ) \
1161 isom_init_box_common( box_name, parent_name, box_type, precedence, isom_remove_##box_name )
1163 #define CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ) \
1164 if( LSMASH_IS_NON_EXISTING_BOX( (isom_box_t *)parent_name ) ) \
1165 return isom_non_existing_##box_name(); \
1166 isom_##box_name##_t *box_name = ALLOCATE_BOX( box_name ); \
1167 if( LSMASH_IS_NON_EXISTING_BOX( box_name ) ) \
1169 INIT_BOX_COMMON ## has_destructor( box_name, parent_name, box_type, precedence ); \
1170 if( isom_add_box_to_extension_list( parent_name, box_name ) < 0 ) \
1172 lsmash_free( box_name ); \
1173 return isom_non_existing_##box_name(); \
1175 #define CREATE_LIST_BOX( box_name, parent_name, box_type, precedence, has_destructor ) \
1176 CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ); \
1177 box_name->list = lsmash_list_create( isom_remove_##box_name##_entry ); \
1178 if( !box_name->list ) \
1180 lsmash_list_remove_entry_tail( &parent_name->extensions ); \
1181 return isom_non_existing_##box_name(); \
1184 #define ADD_BOX_TEMPLATE( box_name, parent_name, box_type, precedence, BOX_CREATOR ) \
1185 BOX_CREATOR( box_name, parent_name, box_type, precedence, 1 ); \
1186 if( LSMASH_IS_NON_EXISTING_BOX( parent_name->box_name ) ) \
1188 parent_name->box_name = box_name; \
1189 box_name->offset_in_parent = offsetof( isom_##parent_name##_t, box_name ); \
1191 #define ADD_BOX_IN_LIST_TEMPLATE( box_name, parent_name, box_type, precedence, BOX_CREATOR ) \
1192 BOX_CREATOR( box_name, parent_name, box_type, precedence, 1 ); \
1193 ADD_BOX_TO_PREDEFINED_LIST( box_name, parent_name )
1195 #define ADD_BOX( box_name, parent_name, box_type, precedence ) \
1196 ADD_BOX_TEMPLATE( box_name, parent_name, box_type, precedence, CREATE_BOX )
1197 #define ADD_BOX_IN_LIST( box_name, parent_name, box_type, precedence ) \
1198 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent_name, box_type, precedence, CREATE_BOX )
1199 #define ADD_LIST_BOX( box_name, parent_name, box_type, precedence ) \
1200 ADD_BOX_TEMPLATE( box_name, parent_name, box_type, precedence, CREATE_LIST_BOX )
1201 #define ADD_LIST_BOX_IN_LIST( box_name, parent_name, box_type, precedence ) \
1202 ADD_BOX_IN_LIST_TEMPLATE( box_name, parent_name, box_type, precedence, CREATE_LIST_BOX )
1204 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ... ) CALL_FUNC_DEFAULT_ARGS( DEFINE_SIMPLE_BOX_ADDER_TEMPLATE, __VA_ARGS__ )
1205 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, postprocess ) \
1206 isom_##box_name##_t *isom_add_##box_name( isom_##parent_name##_t *parent_name ) \
1208 ADDER( box_name, parent_name, box_type, precedence ); \
1209 do { postprocess } while( 0 ); \
1212 #define DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5( ADDER, box_name, parent_name, box_type, precedence ) \
1213 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6( ADDER, box_name, parent_name, box_type, precedence, )
1215 #define DEFINE_SIMPLE_BOX_ADDER( func_name, ... ) \
1216 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX, __VA_ARGS__ )
1217 #define DEFINE_SIMPLE_BOX_IN_LIST_ADDER( func_name, ... ) \
1218 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_BOX_IN_LIST, __VA_ARGS__ )
1219 #define DEFINE_SIMPLE_LIST_BOX_ADDER( func_name, ... ) \
1220 DEFINE_SIMPLE_BOX_ADDER_TEMPLATE( ADD_LIST_BOX, __VA_ARGS__ )
1222 #define DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( func_name, box_name, parent_name, box_type, precedence, has_destructor, parent_type ) \
1223 isom_##box_name##_t *isom_add_##box_name( parent_type *parent_name ) \
1225 CREATE_BOX( box_name, parent_name, box_type, precedence, has_destructor ); \
1229 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_file_abstract
, file_abstract
, root_abstract
, LSMASH_BOX_TYPE_UNSPECIFIED
, 0,
1230 file_abstract
->file
= file_abstract
; )
1232 isom_tref_type_t
*isom_add_track_reference_type( isom_tref_t
*tref
, isom_track_reference_type type
)
1234 if( LSMASH_IS_NON_EXISTING_BOX( tref
) )
1235 return isom_non_existing_tref_type();
1236 isom_tref_type_t
*tref_type
= ALLOCATE_BOX( tref_type
);
1237 if( LSMASH_IS_NON_EXISTING_BOX( tref_type
) )
1239 /* Initialize common fields. */
1240 tref_type
->class = &lsmash_box_class
;
1241 tref_type
->root
= tref
->root
;
1242 tref_type
->file
= tref
->file
;
1243 tref_type
->parent
= (isom_box_t
*)tref
;
1244 tref_type
->precedence
= LSMASH_BOX_PRECEDENCE_ISOM_TREF_TYPE
;
1245 tref_type
->destruct
= (isom_extension_destructor_t
)isom_remove_track_reference_type
;
1246 tref_type
->size
= 0;
1247 tref_type
->type
= lsmash_form_iso_box_type( type
);
1248 isom_set_box_writer( (isom_box_t
*)tref_type
);
1249 if( isom_add_box_to_extension_list( tref
, tref_type
) < 0 )
1251 lsmash_free( tref_type
);
1252 return isom_non_existing_tref_type();
1254 if( lsmash_list_add_entry( &tref
->ref_list
, tref_type
) < 0 )
1256 lsmash_list_remove_entry_tail( &tref
->extensions
);
1257 return isom_non_existing_tref_type();
1259 tref_type
->offset_in_parent
= offsetof( isom_tref_t
, ref_list
);
1263 DEFINE_SIMPLE_BOX_ADDER( isom_add_terminator
, terminator
, wave
, QT_BOX_TYPE_TERMINATOR
, LSMASH_BOX_PRECEDENCE_QTFF_TERMINATOR
)
1264 DEFINE_SIMPLE_BOX_ADDER( isom_add_frma
, frma
, wave
, QT_BOX_TYPE_FRMA
, LSMASH_BOX_PRECEDENCE_QTFF_FRMA
)
1265 DEFINE_SIMPLE_BOX_ADDER( isom_add_enda
, enda
, wave
, QT_BOX_TYPE_ENDA
, LSMASH_BOX_PRECEDENCE_QTFF_ENDA
)
1266 DEFINE_SIMPLE_BOX_ADDER( isom_add_mp4a
, mp4a
, wave
, QT_BOX_TYPE_MP4A
, LSMASH_BOX_PRECEDENCE_QTFF_MP4A
)
1267 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ftab
, ftab
, tx3g_entry
, ISOM_BOX_TYPE_FTAB
, LSMASH_BOX_PRECEDENCE_ISOM_FTAB
)
1268 DEFINE_SIMPLE_BOX_ADDER( isom_add_ftyp
, ftyp
, file_abstract
, ISOM_BOX_TYPE_FTYP
, LSMASH_BOX_PRECEDENCE_ISOM_FTYP
)
1269 DEFINE_SIMPLE_BOX_ADDER( isom_add_moov
, moov
, file_abstract
, ISOM_BOX_TYPE_MOOV
, LSMASH_BOX_PRECEDENCE_ISOM_MOOV
)
1270 DEFINE_SIMPLE_BOX_ADDER( isom_add_mvhd
, mvhd
, moov
, ISOM_BOX_TYPE_MVHD
, LSMASH_BOX_PRECEDENCE_ISOM_MVHD
)
1271 DEFINE_SIMPLE_BOX_ADDER( isom_add_iods
, iods
, moov
, ISOM_BOX_TYPE_IODS
, LSMASH_BOX_PRECEDENCE_ISOM_IODS
)
1273 isom_ctab_t
*isom_add_ctab( void *parent_box
)
1275 /* According to QuickTime File Format Specification, this box is placed inside Movie Box if present.
1276 * However, sometimes this box occurs inside an image description entry or the end of Sample Description Box. */
1277 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1278 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1279 return isom_non_existing_ctab();
1280 CREATE_BOX( ctab
, parent
, QT_BOX_TYPE_CTAB
, LSMASH_BOX_PRECEDENCE_QTFF_CTAB
, 1 );
1281 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1282 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( ctab
, isom_moov_t
);
1286 isom_trak_t
*isom_add_trak( isom_moov_t
*moov
)
1288 if( LSMASH_IS_NON_EXISTING_BOX( moov
)
1289 || LSMASH_IS_NON_EXISTING_BOX( moov
->file
) )
1290 return isom_non_existing_trak();
1291 CREATE_BOX( trak
, moov
, ISOM_BOX_TYPE_TRAK
, LSMASH_BOX_PRECEDENCE_ISOM_TRAK
, 1 );
1292 isom_fragment_t
*fragment
= NULL
;
1293 isom_cache_t
*cache
= lsmash_malloc_zero( sizeof(isom_cache_t
) );
1296 if( moov
->file
->fragment
)
1298 fragment
= lsmash_malloc_zero( sizeof(isom_fragment_t
) );
1301 cache
->fragment
= fragment
;
1302 fragment
->largest_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1303 fragment
->subsegment
.largest_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1304 fragment
->subsegment
.smallest_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1305 fragment
->subsegment
.first_sample_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1306 fragment
->subsegment
.first_ed_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1307 fragment
->subsegment
.first_rp_cts
= LSMASH_TIMESTAMP_UNDEFINED
;
1309 if( lsmash_list_add_entry( &moov
->trak_list
, trak
) < 0 )
1311 trak
->offset_in_parent
= offsetof( isom_moov_t
, trak_list
);
1312 trak
->cache
= cache
;
1315 lsmash_free( fragment
);
1316 lsmash_free( cache
);
1317 lsmash_list_remove_entry_tail( &moov
->extensions
);
1318 return isom_non_existing_trak();
1321 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tkhd
, tkhd
, trak
, ISOM_BOX_TYPE_TKHD
, LSMASH_BOX_PRECEDENCE_ISOM_TKHD
)
1322 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tapt
, tapt
, trak
, QT_BOX_TYPE_TAPT
, LSMASH_BOX_PRECEDENCE_QTFF_TAPT
)
1323 DEFINE_SIMPLE_BOX_ADDER ( isom_add_clef
, clef
, tapt
, QT_BOX_TYPE_CLEF
, LSMASH_BOX_PRECEDENCE_QTFF_CLEF
)
1324 DEFINE_SIMPLE_BOX_ADDER ( isom_add_prof
, prof
, tapt
, QT_BOX_TYPE_PROF
, LSMASH_BOX_PRECEDENCE_QTFF_PROF
)
1325 DEFINE_SIMPLE_BOX_ADDER ( isom_add_enof
, enof
, tapt
, QT_BOX_TYPE_ENOF
, LSMASH_BOX_PRECEDENCE_QTFF_ENOF
)
1326 DEFINE_SIMPLE_BOX_ADDER ( isom_add_edts
, edts
, trak
, ISOM_BOX_TYPE_EDTS
, LSMASH_BOX_PRECEDENCE_ISOM_EDTS
)
1327 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_elst
, elst
, edts
, ISOM_BOX_TYPE_ELST
, LSMASH_BOX_PRECEDENCE_ISOM_ELST
)
1328 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tref
, tref
, trak
, ISOM_BOX_TYPE_TREF
, LSMASH_BOX_PRECEDENCE_ISOM_TREF
)
1329 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdia
, mdia
, trak
, ISOM_BOX_TYPE_MDIA
, LSMASH_BOX_PRECEDENCE_ISOM_MDIA
)
1330 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mdhd
, mdhd
, mdia
, ISOM_BOX_TYPE_MDHD
, LSMASH_BOX_PRECEDENCE_ISOM_MDHD
)
1332 isom_hdlr_t
*isom_add_hdlr( void *parent_box
)
1334 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1335 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1336 return isom_non_existing_hdlr();
1337 CREATE_BOX( hdlr
, parent
, ISOM_BOX_TYPE_HDLR
, LSMASH_BOX_PRECEDENCE_ISOM_HDLR
, 1 );
1338 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MDIA
) )
1339 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_mdia_t
);
1340 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1341 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1342 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_meta_t
);
1343 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1344 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( hdlr
, isom_minf_t
);
1350 DEFINE_SIMPLE_BOX_ADDER( isom_add_minf
, minf
, mdia
, ISOM_BOX_TYPE_MINF
, LSMASH_BOX_PRECEDENCE_ISOM_MINF
)
1351 DEFINE_SIMPLE_BOX_ADDER( isom_add_vmhd
, vmhd
, minf
, ISOM_BOX_TYPE_VMHD
, LSMASH_BOX_PRECEDENCE_ISOM_VMHD
)
1352 DEFINE_SIMPLE_BOX_ADDER( isom_add_smhd
, smhd
, minf
, ISOM_BOX_TYPE_SMHD
, LSMASH_BOX_PRECEDENCE_ISOM_SMHD
)
1353 DEFINE_SIMPLE_BOX_ADDER( isom_add_hmhd
, hmhd
, minf
, ISOM_BOX_TYPE_HMHD
, LSMASH_BOX_PRECEDENCE_ISOM_HMHD
)
1354 DEFINE_SIMPLE_BOX_ADDER( isom_add_nmhd
, nmhd
, minf
, ISOM_BOX_TYPE_NMHD
, LSMASH_BOX_PRECEDENCE_ISOM_NMHD
)
1355 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmhd
, gmhd
, minf
, QT_BOX_TYPE_GMHD
, LSMASH_BOX_PRECEDENCE_QTFF_GMHD
)
1356 DEFINE_SIMPLE_BOX_ADDER( isom_add_gmin
, gmin
, gmhd
, QT_BOX_TYPE_GMIN
, LSMASH_BOX_PRECEDENCE_QTFF_GMIN
)
1357 DEFINE_SIMPLE_BOX_ADDER( isom_add_text
, text
, gmhd
, QT_BOX_TYPE_TEXT
, LSMASH_BOX_PRECEDENCE_QTFF_TEXT
)
1359 isom_dinf_t
*isom_add_dinf( void *parent_box
)
1361 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1362 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1363 return isom_non_existing_dinf();
1364 CREATE_BOX( dinf
, parent
, ISOM_BOX_TYPE_DINF
, LSMASH_BOX_PRECEDENCE_ISOM_DINF
, 1 );
1365 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MINF
) )
1366 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_minf_t
);
1367 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_META
)
1368 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_META
) )
1369 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( dinf
, isom_meta_t
);
1375 isom_dref_entry_t
*isom_add_dref_entry( isom_dref_t
*dref
, lsmash_box_type_t type
)
1377 if( LSMASH_IS_NON_EXISTING_BOX( dref
) )
1378 return isom_non_existing_dref_entry();
1379 isom_dref_entry_t
*dref_entry
= ALLOCATE_BOX( dref_entry
);
1380 if( LSMASH_IS_NON_EXISTING_BOX( dref_entry
) )
1382 isom_init_box_common( dref_entry
, dref
, type
, LSMASH_BOX_PRECEDENCE_ISOM_DREF_ENTRY
, isom_remove_dref_entry
);
1383 if( isom_add_box_to_extension_list( dref
, dref_entry
) < 0 )
1385 lsmash_free( dref_entry
);
1386 return isom_non_existing_dref_entry();
1388 if( lsmash_list_add_entry( &dref
->list
, dref_entry
) < 0 )
1390 lsmash_list_remove_entry_tail( &dref
->extensions
);
1391 return isom_non_existing_dref_entry();
1393 dref_entry
->offset_in_parent
= offsetof( isom_dref_t
, list
);
1397 DEFINE_SIMPLE_BOX_ADDER( isom_add_dref
, dref
, dinf
, ISOM_BOX_TYPE_DREF
, LSMASH_BOX_PRECEDENCE_ISOM_DREF
)
1398 DEFINE_SIMPLE_BOX_ADDER( isom_add_stbl
, stbl
, minf
, ISOM_BOX_TYPE_STBL
, LSMASH_BOX_PRECEDENCE_ISOM_STBL
)
1399 DEFINE_SIMPLE_BOX_ADDER( isom_add_stsd
, stsd
, stbl
, ISOM_BOX_TYPE_STSD
, LSMASH_BOX_PRECEDENCE_ISOM_STSD
)
1401 static void *isom_add_sample_description_entry
1407 assert( description
);
1408 if( isom_add_box_to_extension_list( stsd
, description
) < 0 )
1410 isom_remove_box_by_itself( description
);
1413 if( lsmash_list_add_entry( &stsd
->list
, description
) < 0 )
1415 lsmash_list_remove_entry_tail( &stsd
->extensions
);
1418 ((isom_box_t
*)description
)->offset_in_parent
= offsetof( isom_stsd_t
, list
);
1422 isom_visual_entry_t
*isom_add_visual_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1424 assert( LSMASH_IS_EXISTING_BOX( stsd
) );
1425 isom_visual_entry_t
*visual
= ALLOCATE_BOX( visual_entry
);
1426 if( LSMASH_IS_NON_EXISTING_BOX( visual
) )
1428 isom_init_box_common( visual
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_visual_description
);
1429 visual
->manager
|= LSMASH_VIDEO_DESCRIPTION
;
1430 return isom_add_sample_description_entry( stsd
, visual
);
1433 isom_audio_entry_t
*isom_add_audio_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1435 assert( LSMASH_IS_EXISTING_BOX( stsd
) );
1436 isom_audio_entry_t
*audio
= ALLOCATE_BOX( audio_entry
);
1437 if( LSMASH_IS_NON_EXISTING_BOX( audio
) )
1439 isom_init_box_common( audio
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_audio_description
);
1440 audio
->manager
|= LSMASH_AUDIO_DESCRIPTION
;
1441 return isom_add_sample_description_entry( stsd
, audio
);
1444 isom_hint_entry_t
*isom_add_hint_description( isom_stsd_t
*stsd
, lsmash_codec_type_t sample_type
)
1447 isom_hint_entry_t
*hint
= ALLOCATE_BOX( hint_entry
);
1448 if ( LSMASH_IS_NON_EXISTING_BOX( hint
) )
1450 isom_init_box_common( hint
, stsd
, sample_type
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_hint_description
);
1451 return isom_add_sample_description_entry( stsd
, hint
);
1454 isom_qt_text_entry_t
*isom_add_qt_text_description( isom_stsd_t
*stsd
)
1456 assert( LSMASH_IS_EXISTING_BOX( stsd
) );
1457 isom_qt_text_entry_t
*text
= ALLOCATE_BOX( qt_text_entry
);
1458 if( LSMASH_IS_NON_EXISTING_BOX( text
) )
1460 isom_init_box_common( text
, stsd
, QT_CODEC_TYPE_TEXT_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_qt_text_description
);
1461 return isom_add_sample_description_entry( stsd
, text
);
1464 isom_tx3g_entry_t
*isom_add_tx3g_description( isom_stsd_t
*stsd
)
1466 assert( LSMASH_IS_EXISTING_BOX( stsd
) );
1467 isom_tx3g_entry_t
*tx3g
= ALLOCATE_BOX( tx3g_entry
);
1468 if( LSMASH_IS_NON_EXISTING_BOX( tx3g
) )
1470 isom_init_box_common( tx3g
, stsd
, ISOM_CODEC_TYPE_TX3G_TEXT
, LSMASH_BOX_PRECEDENCE_HM
, isom_remove_tx3g_description
);
1471 return isom_add_sample_description_entry( stsd
, tx3g
);
1474 isom_esds_t
*isom_add_esds( void *parent_box
)
1476 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1477 int is_qt
= lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
);
1478 lsmash_box_type_t box_type
= is_qt
? QT_BOX_TYPE_ESDS
: ISOM_BOX_TYPE_ESDS
;
1479 uint64_t precedence
= is_qt
? LSMASH_BOX_PRECEDENCE_QTFF_ESDS
: LSMASH_BOX_PRECEDENCE_ISOM_ESDS
;
1480 CREATE_BOX( esds
, parent
, box_type
, precedence
, 1 );
1484 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_glbl
, glbl
, parent_box
, QT_BOX_TYPE_GLBL
, LSMASH_BOX_PRECEDENCE_QTFF_GLBL
, 1, void )
1485 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_clap
, clap
, visual
, ISOM_BOX_TYPE_CLAP
, LSMASH_BOX_PRECEDENCE_ISOM_CLAP
, 0, isom_visual_entry_t
)
1486 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_pasp
, pasp
, visual
, ISOM_BOX_TYPE_PASP
, LSMASH_BOX_PRECEDENCE_ISOM_PASP
, 0, isom_visual_entry_t
)
1487 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_colr
, colr
, visual
, ISOM_BOX_TYPE_COLR
, LSMASH_BOX_PRECEDENCE_ISOM_COLR
, 0, isom_visual_entry_t
)
1488 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_gama
, gama
, visual
, QT_BOX_TYPE_GAMA
, LSMASH_BOX_PRECEDENCE_QTFF_GAMA
, 0, isom_visual_entry_t
)
1489 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_fiel
, fiel
, visual
, QT_BOX_TYPE_FIEL
, LSMASH_BOX_PRECEDENCE_QTFF_FIEL
, 0, isom_visual_entry_t
)
1490 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_clli
, clli
, visual
, QT_BOX_TYPE_CLLI
, LSMASH_BOX_PRECEDENCE_QTFF_CLLI
, 0, isom_visual_entry_t
)
1491 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_mdcv
, mdcv
, visual
, QT_BOX_TYPE_MDCV
, LSMASH_BOX_PRECEDENCE_QTFF_MDCV
, 0, isom_visual_entry_t
)
1492 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_cspc
, cspc
, visual
, QT_BOX_TYPE_CSPC
, LSMASH_BOX_PRECEDENCE_QTFF_CSPC
, 0, isom_visual_entry_t
)
1493 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_sgbt
, sgbt
, visual
, QT_BOX_TYPE_SGBT
, LSMASH_BOX_PRECEDENCE_QTFF_SGBT
, 0, isom_visual_entry_t
)
1494 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_stsl
, stsl
, visual
, ISOM_BOX_TYPE_STSL
, LSMASH_BOX_PRECEDENCE_ISOM_STSL
, 0, isom_visual_entry_t
)
1495 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_btrt
, btrt
, visual
, ISOM_BOX_TYPE_BTRT
, LSMASH_BOX_PRECEDENCE_ISOM_BTRT
, 0, isom_visual_entry_t
)
1496 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_wave
, wave
, audio
, QT_BOX_TYPE_WAVE
, LSMASH_BOX_PRECEDENCE_QTFF_WAVE
, 0, isom_audio_entry_t
)
1497 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_chan
, chan
, audio
, QT_BOX_TYPE_CHAN
, LSMASH_BOX_PRECEDENCE_QTFF_CHAN
, 1, isom_audio_entry_t
)
1498 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_srat
, srat
, audio
, ISOM_BOX_TYPE_SRAT
, LSMASH_BOX_PRECEDENCE_ISOM_SRAT
, 0, isom_audio_entry_t
)
1499 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_tims
, tims
, hint
, ISOM_BOX_TYPE_TIMS
, LSMASH_BOX_PRECEDENCE_ISOM_TIMS
, 0, isom_hint_entry_t
)
1500 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_tsro
, tsro
, hint
, ISOM_BOX_TYPE_TSRO
, LSMASH_BOX_PRECEDENCE_ISOM_TSRO
, 0, isom_hint_entry_t
)
1501 DEFINE_SIMPLE_SAMPLE_EXTENSION_ADDER( isom_add_tssy
, tssy
, hint
, ISOM_BOX_TYPE_TSSY
, LSMASH_BOX_PRECEDENCE_ISOM_TSSY
, 0, isom_hint_entry_t
)
1503 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stts
, stts
, stbl
, ISOM_BOX_TYPE_STTS
, LSMASH_BOX_PRECEDENCE_ISOM_STTS
)
1504 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_ctts
, ctts
, stbl
, ISOM_BOX_TYPE_CTTS
, LSMASH_BOX_PRECEDENCE_ISOM_CTTS
)
1505 DEFINE_SIMPLE_BOX_ADDER ( isom_add_cslg
, cslg
, stbl
, ISOM_BOX_TYPE_CSLG
, LSMASH_BOX_PRECEDENCE_ISOM_CSLG
)
1506 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stsc
, stsc
, stbl
, ISOM_BOX_TYPE_STSC
, LSMASH_BOX_PRECEDENCE_ISOM_STSC
)
1507 DEFINE_SIMPLE_BOX_ADDER ( isom_add_stsz
, stsz
, stbl
, ISOM_BOX_TYPE_STSZ
, LSMASH_BOX_PRECEDENCE_ISOM_STSZ
) /* We don't create a list here. */
1508 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stz2
, stz2
, stbl
, ISOM_BOX_TYPE_STZ2
, LSMASH_BOX_PRECEDENCE_ISOM_STZ2
)
1509 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stss
, stss
, stbl
, ISOM_BOX_TYPE_STSS
, LSMASH_BOX_PRECEDENCE_ISOM_STSS
)
1510 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_stps
, stps
, stbl
, QT_BOX_TYPE_STPS
, LSMASH_BOX_PRECEDENCE_QTFF_STPS
)
1512 isom_stco_t
*isom_add_stco( isom_stbl_t
*stbl
)
1514 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_STCO
, LSMASH_BOX_PRECEDENCE_ISOM_STCO
);
1515 stco
->large_presentation
= 0;
1519 isom_stco_t
*isom_add_co64( isom_stbl_t
*stbl
)
1521 ADD_LIST_BOX( stco
, stbl
, ISOM_BOX_TYPE_CO64
, LSMASH_BOX_PRECEDENCE_ISOM_CO64
);
1522 stco
->large_presentation
= 1;
1526 isom_sdtp_t
*isom_add_sdtp( isom_box_t
*parent
)
1528 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1529 return isom_non_existing_sdtp();
1530 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1532 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1533 ADD_LIST_BOX( sdtp
, stbl
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1536 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1538 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1539 ADD_LIST_BOX( sdtp
, traf
, ISOM_BOX_TYPE_SDTP
, LSMASH_BOX_PRECEDENCE_ISOM_SDTP
);
1543 return isom_non_existing_sdtp();
1546 isom_sgpd_t
*isom_add_sgpd( void *parent_box
)
1548 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1549 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1550 return isom_non_existing_sgpd();
1551 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1553 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1554 ADD_LIST_BOX_IN_LIST( sgpd
, stbl
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1557 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1559 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1560 ADD_LIST_BOX_IN_LIST( sgpd
, traf
, ISOM_BOX_TYPE_SGPD
, LSMASH_BOX_PRECEDENCE_ISOM_SGPD
);
1564 return isom_non_existing_sgpd();
1567 isom_sbgp_t
*isom_add_sbgp( void *parent_box
)
1569 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1570 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1571 return isom_non_existing_sbgp();
1572 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STBL
) )
1574 isom_stbl_t
*stbl
= (isom_stbl_t
*)parent
;
1575 ADD_LIST_BOX_IN_LIST( sbgp
, stbl
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1578 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAF
) )
1580 isom_traf_t
*traf
= (isom_traf_t
*)parent
;
1581 ADD_LIST_BOX_IN_LIST( sbgp
, traf
, ISOM_BOX_TYPE_SBGP
, LSMASH_BOX_PRECEDENCE_ISOM_SBGP
);
1585 return isom_non_existing_sbgp();
1588 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_chpl
, chpl
, udta
, ISOM_BOX_TYPE_CHPL
, LSMASH_BOX_PRECEDENCE_ISOM_CHPL
)
1590 isom_metaitem_t
*isom_add_metaitem( isom_ilst_t
*ilst
, lsmash_itunes_metadata_item item
)
1592 if( LSMASH_IS_NON_EXISTING_BOX( ilst
) )
1593 return isom_non_existing_metaitem();
1594 lsmash_box_type_t type
= lsmash_form_iso_box_type( item
);
1595 ADD_BOX_IN_LIST( metaitem
, ilst
, type
, LSMASH_BOX_PRECEDENCE_ISOM_METAITEM
);
1599 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mean
, mean
, metaitem
, ISOM_BOX_TYPE_MEAN
, LSMASH_BOX_PRECEDENCE_ISOM_MEAN
)
1600 DEFINE_SIMPLE_BOX_ADDER ( isom_add_name
, name
, metaitem
, ISOM_BOX_TYPE_NAME
, LSMASH_BOX_PRECEDENCE_ISOM_NAME
)
1601 DEFINE_SIMPLE_BOX_ADDER ( isom_add_data
, data
, metaitem
, ISOM_BOX_TYPE_DATA
, LSMASH_BOX_PRECEDENCE_ISOM_DATA
)
1602 DEFINE_SIMPLE_BOX_ADDER ( isom_add_ilst
, ilst
, meta
, ISOM_BOX_TYPE_ILST
, LSMASH_BOX_PRECEDENCE_ISOM_ILST
)
1603 DEFINE_SIMPLE_LIST_BOX_ADDER( isom_add_keys
, keys
, meta
, QT_BOX_TYPE_KEYS
, LSMASH_BOX_PRECEDENCE_QTFF_KEYS
)
1605 isom_meta_t
*isom_add_meta( void *parent_box
)
1607 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1608 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1609 return isom_non_existing_meta();
1610 CREATE_BOX( meta
, parent
, ISOM_BOX_TYPE_META
, LSMASH_BOX_PRECEDENCE_ISOM_META
, 1 );
1611 if( parent
->file
== (lsmash_file_t
*)parent
)
1612 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, lsmash_file_t
);
1613 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1614 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_moov_t
);
1615 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1616 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_trak_t
);
1617 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_UDTA
) )
1618 ATTACH_EXACTLY_ONE_BOX_TO_PARENT( meta
, isom_udta_t
);
1624 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_cprt
, cprt
, udta
, ISOM_BOX_TYPE_CPRT
, LSMASH_BOX_PRECEDENCE_ISOM_CPRT
)
1625 DEFINE_SIMPLE_BOX_ADDER( isom_add_hnti
, hnti
, udta
, ISOM_BOX_TYPE_HNTI
, LSMASH_BOX_PRECEDENCE_ISOM_HNTI
)
1626 DEFINE_SIMPLE_BOX_ADDER( isom_add_rtp
, rtp
, hnti
, ISOM_BOX_TYPE_RTP
, LSMASH_BOX_PRECEDENCE_ISOM_RTP
)
1627 DEFINE_SIMPLE_BOX_ADDER( isom_add_sdp
, sdp
, hnti
, ISOM_BOX_TYPE_SDP
, LSMASH_BOX_PRECEDENCE_ISOM_SDP
)
1629 isom_udta_t
*isom_add_udta( void *parent_box
)
1631 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1632 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1633 return isom_non_existing_udta();
1634 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_MOOV
) )
1636 isom_moov_t
*moov
= (isom_moov_t
*)parent
;
1637 ADD_BOX( udta
, moov
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1640 else if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TRAK
) )
1642 isom_trak_t
*trak
= (isom_trak_t
*)parent
;
1643 ADD_BOX( udta
, trak
, ISOM_BOX_TYPE_UDTA
, LSMASH_BOX_PRECEDENCE_ISOM_UDTA
);
1647 return isom_non_existing_udta();
1650 DEFINE_SIMPLE_BOX_ADDER ( isom_add_WLOC
, WLOC
, udta
, QT_BOX_TYPE_WLOC
, LSMASH_BOX_PRECEDENCE_QTFF_WLOC
)
1651 DEFINE_SIMPLE_BOX_ADDER ( isom_add_LOOP
, LOOP
, udta
, QT_BOX_TYPE_LOOP
, LSMASH_BOX_PRECEDENCE_QTFF_LOOP
)
1652 DEFINE_SIMPLE_BOX_ADDER ( isom_add_SelO
, SelO
, udta
, QT_BOX_TYPE_SELO
, LSMASH_BOX_PRECEDENCE_QTFF_SELO
)
1653 DEFINE_SIMPLE_BOX_ADDER ( isom_add_AllF
, AllF
, udta
, QT_BOX_TYPE_ALLF
, LSMASH_BOX_PRECEDENCE_QTFF_ALLF
)
1654 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mvex
, mvex
, moov
, ISOM_BOX_TYPE_MVEX
, LSMASH_BOX_PRECEDENCE_ISOM_MVEX
)
1655 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mehd
, mehd
, mvex
, ISOM_BOX_TYPE_MEHD
, LSMASH_BOX_PRECEDENCE_ISOM_MEHD
)
1656 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trex
, trex
, mvex
, ISOM_BOX_TYPE_TREX
, LSMASH_BOX_PRECEDENCE_ISOM_TREX
)
1657 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_moof
, moof
, file_abstract
, ISOM_BOX_TYPE_MOOF
, LSMASH_BOX_PRECEDENCE_ISOM_MOOF
)
1658 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfhd
, mfhd
, moof
, ISOM_BOX_TYPE_MFHD
, LSMASH_BOX_PRECEDENCE_ISOM_MFHD
)
1659 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_traf
, traf
, moof
, ISOM_BOX_TYPE_TRAF
, LSMASH_BOX_PRECEDENCE_ISOM_TRAF
)
1660 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfhd
, tfhd
, traf
, ISOM_BOX_TYPE_TFHD
, LSMASH_BOX_PRECEDENCE_ISOM_TFHD
)
1661 DEFINE_SIMPLE_BOX_ADDER ( isom_add_tfdt
, tfdt
, traf
, ISOM_BOX_TYPE_TFDT
, LSMASH_BOX_PRECEDENCE_ISOM_TFDT
)
1662 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_trun
, trun
, traf
, ISOM_BOX_TYPE_TRUN
, LSMASH_BOX_PRECEDENCE_ISOM_TRUN
)
1663 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfra
, mfra
, file_abstract
, ISOM_BOX_TYPE_MFRA
, LSMASH_BOX_PRECEDENCE_ISOM_MFRA
)
1664 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_tfra
, tfra
, mfra
, ISOM_BOX_TYPE_TFRA
, LSMASH_BOX_PRECEDENCE_ISOM_TFRA
)
1665 DEFINE_SIMPLE_BOX_ADDER ( isom_add_mfro
, mfro
, mfra
, ISOM_BOX_TYPE_MFRO
, LSMASH_BOX_PRECEDENCE_ISOM_MFRO
)
1667 isom_mdat_t
*isom_add_mdat( isom_file_abstract_t
*file
)
1669 assert( LSMASH_IS_NON_EXISTING_BOX( file
->mdat
) );
1670 CREATE_BOX( mdat
, file
, ISOM_BOX_TYPE_MDAT
, LSMASH_BOX_PRECEDENCE_ISOM_MDAT
, 1 );
1675 isom_free_t
*isom_add_free( void *parent_box
)
1677 isom_box_t
*parent
= (isom_box_t
*)parent_box
;
1678 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1679 return isom_non_existing_skip();
1680 CREATE_BOX( skip
, parent
, ISOM_BOX_TYPE_FREE
, LSMASH_BOX_PRECEDENCE_ISOM_FREE
, 1 );
1684 DEFINE_SIMPLE_BOX_IN_LIST_ADDER( isom_add_styp
, styp
, file_abstract
, ISOM_BOX_TYPE_STYP
, LSMASH_BOX_PRECEDENCE_ISOM_STYP
)
1686 isom_sidx_t
*isom_add_sidx( isom_file_abstract_t
*file_abstract
)
1688 ADD_LIST_BOX_IN_LIST( sidx
, file_abstract
, ISOM_BOX_TYPE_SIDX
, LSMASH_BOX_PRECEDENCE_ISOM_SIDX
);
1692 #undef ATTACH_EXACTLY_ONE_BOX_TO_PARENT
1694 #undef CREATE_LIST_BOX
1695 #undef ADD_BOX_TEMPLATE
1696 #undef ADD_BOX_IN_LIST_TEMPLATE
1698 #undef ADD_BOX_IN_LIST
1700 #undef ADD_LIST_BOX_IN_LIST
1701 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE
1702 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_6
1703 #undef DEFINE_SIMPLE_BOX_ADDER_TEMPLATE_5
1704 #undef DEFINE_SIMPLE_BOX_ADDER
1705 #undef DEFINE_SIMPLE_BOX_IN_LIST_ADDER
1706 #undef DEFINE_SIMPLE_LIST_BOX_ADDER
1708 static int fake_file_read
1715 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1717 if( stream
->pos
+ size
> stream
->size
)
1718 read_size
= stream
->size
- stream
->pos
;
1721 memcpy( buf
, stream
->data
+ stream
->pos
, read_size
);
1722 stream
->pos
+= read_size
;
1726 static int64_t fake_file_seek
1733 fake_file_stream_t
*stream
= (fake_file_stream_t
*)opaque
;
1734 if( whence
== SEEK_SET
)
1735 stream
->pos
= offset
;
1736 else if( whence
== SEEK_CUR
)
1737 stream
->pos
+= offset
;
1738 else if( whence
== SEEK_END
)
1739 stream
->pos
= stream
->size
+ offset
;
1743 /* Public functions */
1744 lsmash_root_t
*lsmash_create_root( void )
1746 lsmash_root_t
*root
= ALLOCATE_BOX( root_abstract
);
1747 if( LSMASH_IS_NON_EXISTING_BOX( root
) )
1753 void lsmash_destroy_root( lsmash_root_t
*root
)
1755 isom_remove_box_by_itself( root
);
1758 lsmash_extended_box_type_t
lsmash_form_extended_box_type( uint32_t fourcc
, const uint8_t id
[12] )
1760 return (lsmash_extended_box_type_t
){ fourcc
, { id
[0], id
[1], id
[2], id
[3], id
[4], id
[5],
1761 id
[6], id
[7], id
[8], id
[9], id
[10], id
[11] } };
1764 lsmash_box_type_t lsmash_form_box_type
1766 lsmash_compact_box_type_t type
,
1767 lsmash_extended_box_type_t user
1770 return (lsmash_box_type_t
){ type
, user
};
1773 lsmash_box_type_t
lsmash_form_iso_box_type( uint32_t fourcc
)
1775 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_ISO_12_BYTES
) };
1778 lsmash_box_type_t
lsmash_form_qtff_box_type( uint32_t fourcc
)
1780 return (lsmash_box_type_t
){ fourcc
, lsmash_form_extended_box_type( fourcc
, LSMASH_QTFF_12_BYTES
) };
1783 #define CHECK_BOX_TYPE_IDENTICAL( a, b ) \
1784 a.fourcc == b.fourcc \
1785 && a.user.fourcc == b.user.fourcc \
1786 && a.user.id[0] == b.user.id[0] \
1787 && a.user.id[1] == b.user.id[1] \
1788 && a.user.id[2] == b.user.id[2] \
1789 && a.user.id[3] == b.user.id[3] \
1790 && a.user.id[4] == b.user.id[4] \
1791 && a.user.id[5] == b.user.id[5] \
1792 && a.user.id[6] == b.user.id[6] \
1793 && a.user.id[7] == b.user.id[7] \
1794 && a.user.id[8] == b.user.id[8] \
1795 && a.user.id[9] == b.user.id[9] \
1796 && a.user.id[10] == b.user.id[10] \
1797 && a.user.id[11] == b.user.id[11]
1799 int lsmash_check_box_type_identical( lsmash_box_type_t a
, lsmash_box_type_t b
)
1801 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1804 int lsmash_check_codec_type_identical( lsmash_codec_type_t a
, lsmash_codec_type_t b
)
1806 return CHECK_BOX_TYPE_IDENTICAL( a
, b
);
1809 int lsmash_check_box_type_specified( const lsmash_box_type_t
*box_type
)
1814 return !!(box_type
->fourcc
1815 | box_type
->user
.fourcc
1816 | box_type
->user
.id
[0] | box_type
->user
.id
[1] | box_type
->user
.id
[2] | box_type
->user
.id
[3]
1817 | box_type
->user
.id
[4] | box_type
->user
.id
[5] | box_type
->user
.id
[6] | box_type
->user
.id
[7]
1818 | box_type
->user
.id
[8] | box_type
->user
.id
[9] | box_type
->user
.id
[10] | box_type
->user
.id
[11]);
1821 lsmash_box_t
*lsmash_get_box
1823 lsmash_box_t
*parent
,
1824 const lsmash_box_path_t box_path
[]
1827 lsmash_entry_t
*entry
= isom_get_entry_of_box( parent
, box_path
);
1828 return (lsmash_box_t
*)(entry
? entry
->data
: NULL
);
1831 lsmash_box_t
*lsmash_create_box
1833 lsmash_box_type_t type
,
1839 if( !lsmash_check_box_type_specified( &type
) )
1841 isom_unknown_box_t
*box
= ALLOCATE_BOX( unknown
);
1842 if( LSMASH_IS_NON_EXISTING_BOX( box
) )
1846 box
->unknown_size
= size
;
1847 box
->unknown_field
= lsmash_memdup( data
, size
);
1848 if( !box
->unknown_field
)
1856 box
->unknown_size
= 0;
1857 box
->unknown_field
= NULL
;
1860 box
->class = &lsmash_box_class
;
1861 box
->root
= isom_non_existing_root_abstract();
1862 box
->file
= isom_non_existing_file_abstract();
1863 box
->parent
= (isom_box_t
*)isom_non_existing_unknown();
1864 box
->destruct
= (isom_extension_destructor_t
)isom_remove_unknown_box
;
1865 box
->manager
= LSMASH_UNKNOWN_BOX
;
1866 box
->precedence
= precedence
;
1867 box
->size
= ISOM_BASEBOX_COMMON_SIZE
+ size
+ (type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0);
1869 isom_set_box_writer( (isom_box_t
*)box
);
1870 return (lsmash_box_t
*)box
;
1875 lsmash_box_t
*parent
,
1879 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1880 /* You cannot add any box without a box being its parent. */
1881 return LSMASH_ERR_FUNCTION_PARAM
;
1882 if( LSMASH_IS_NON_EXISTING_BOX( box
) || box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1883 return LSMASH_ERR_FUNCTION_PARAM
;
1884 if( parent
->root
== (lsmash_root_t
*)parent
)
1886 /* Only files can be added into any ROOT.
1887 * For backward compatibility, use the active file as the parent. */
1888 if( LSMASH_IS_EXISTING_BOX( parent
->file
) )
1889 parent
= (isom_box_t
*)parent
->file
;
1891 return LSMASH_ERR_FUNCTION_PARAM
;
1893 /* Add a box as a child box. */
1894 box
->class = &lsmash_box_class
;
1895 box
->root
= parent
->root
;
1896 box
->file
= parent
->file
;
1897 box
->parent
= parent
;
1898 return isom_add_box_to_extension_list( parent
, box
);
1901 int lsmash_add_box_ex
1903 lsmash_box_t
*parent
,
1904 lsmash_box_t
**p_box
1907 if( LSMASH_IS_NON_EXISTING_BOX( parent
) )
1908 /* You cannot add any box without a box being its parent. */
1909 return LSMASH_ERR_FUNCTION_PARAM
;
1910 isom_unknown_box_t
*box
= (isom_unknown_box_t
*)*p_box
;
1911 if( LSMASH_IS_NON_EXISTING_BOX( box
) || box
->size
< ISOM_BASEBOX_COMMON_SIZE
)
1912 return LSMASH_ERR_FUNCTION_PARAM
;
1913 if( !(box
->manager
& LSMASH_UNKNOWN_BOX
) )
1914 /* Simply add the box. */
1915 return lsmash_add_box( parent
, *p_box
);
1916 /* Check if the size of the box to be added is valid. */
1917 if( box
->size
!= ISOM_BASEBOX_COMMON_SIZE
+ box
->unknown_size
+ (box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
? 16 : 0) )
1918 return LSMASH_ERR_FUNCTION_PARAM
;
1919 if( LSMASH_IS_NON_EXISTING_BOX( parent
->file
) || parent
->file
== (lsmash_file_t
*)box
)
1920 return LSMASH_ERR_FUNCTION_PARAM
;
1921 if( parent
->root
== (lsmash_root_t
*)parent
)
1922 /* Only files can be added into any ROOT.
1923 * For backward compatibility, use the active file as the parent. */
1924 parent
= (isom_box_t
*)parent
->file
;
1925 /* Switch to the fake-file stream mode. */
1926 lsmash_file_t
*file
= parent
->file
;
1927 lsmash_bs_t
*bs_backup
= file
->bs
;
1928 lsmash_bs_t
*bs
= lsmash_bs_create();
1930 return LSMASH_ERR_MEMORY_ALLOC
;
1931 uint8_t *buf
= lsmash_malloc( box
->size
);
1934 lsmash_bs_cleanup( bs
);
1935 return LSMASH_ERR_MEMORY_ALLOC
;
1937 fake_file_stream_t fake_file
=
1943 bs
->stream
= &fake_file
;
1944 bs
->read
= fake_file_read
;
1946 bs
->seek
= fake_file_seek
;
1948 file
->fake_file_mode
= 1;
1949 /* Make the byte string representing the given box. */
1950 LSMASH_SET_BE32( &buf
[0], box
->size
);
1951 LSMASH_SET_BE32( &buf
[4], box
->type
.fourcc
);
1952 if( box
->type
.fourcc
== ISOM_BOX_TYPE_UUID
.fourcc
)
1954 LSMASH_SET_BE32( &buf
[8], box
->type
.user
.fourcc
);
1955 memcpy( &buf
[12], box
->type
.user
.id
, 12 );
1957 memcpy( buf
+ (uintptr_t)(box
->size
- box
->unknown_size
), box
->unknown_field
, box
->unknown_size
);
1958 /* Add a box as a child box and try to expand into struct format. */
1959 lsmash_box_t dummy
= { 0 };
1960 int ret
= isom_read_box( file
, &dummy
, parent
, 0, 0 );
1962 lsmash_bs_cleanup( bs
);
1963 file
->bs
= bs_backup
; /* Switch back to the normal file stream mode. */
1964 file
->fake_file_mode
= 0;
1967 /* Reorder the added box by 'precedence'. */
1968 *p_box
= (lsmash_box_t
*)parent
->extensions
.tail
->data
;
1969 (*p_box
)->precedence
= box
->precedence
;
1970 isom_reorder_tail_box( parent
);
1971 /* Do also its children by the same way. */
1972 lsmash_entry_list_t extensions
= box
->extensions
;
1973 lsmash_list_init_simple( &box
->extensions
); /* to avoid freeing the children */
1974 isom_remove_box_by_itself( box
);
1975 for( lsmash_entry_t
*entry
= extensions
.head
; entry
; entry
= entry
->next
)
1979 lsmash_box_t
*child
= (lsmash_box_t
*)entry
->data
;
1980 if( lsmash_add_box_ex( *p_box
, &child
) == 0 )
1982 (*p_box
)->size
+= child
->size
;
1983 /* Avoid freeing at the end of this function. */
1987 isom_remove_all_extension_boxes( &extensions
);
1991 void lsmash_destroy_box
1996 isom_remove_box_by_itself( box
);
1999 void lsmash_destroy_children
2004 if( LSMASH_IS_EXISTING_BOX( box
) )
2005 isom_remove_all_extension_boxes( &box
->extensions
);
2008 int lsmash_get_box_precedence
2011 uint64_t *precedence
2014 if( !box
|| !precedence
)
2015 return LSMASH_ERR_FUNCTION_PARAM
;
2016 *precedence
= box
->precedence
;
2020 lsmash_box_t
*lsmash_root_as_box
2025 return (lsmash_box_t
*)root
;
2028 lsmash_box_t
*lsmash_file_as_box
2033 return (lsmash_box_t
*)file
;
2036 int lsmash_write_top_level_box
2041 if( !box
|| (isom_box_t
*)box
->file
!= box
->parent
)
2042 return LSMASH_ERR_FUNCTION_PARAM
;
2043 int ret
= isom_write_box( box
->file
->bs
, box
);
2046 box
->file
->size
+= box
->size
;
2050 uint8_t *lsmash_export_box
2058 lsmash_bs_t
*bs
= lsmash_bs_create();
2061 if( isom_write_box( bs
, box
) < 0 )
2063 lsmash_bs_cleanup( bs
);
2066 *size
= bs
->buffer
.store
;
2067 uint8_t *data
= bs
->buffer
.data
;
2068 bs
->buffer
.data
= NULL
;
2069 lsmash_bs_cleanup( bs
);