1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-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 */
32 #include "codecs/mp4a.h"
33 #include "codecs/mp4sys.h"
34 #include "codecs/description.h"
36 static int isom_write_children( lsmash_bs_t
*bs
, isom_box_t
*box
)
38 for( lsmash_entry_t
*entry
= box
->extensions
.head
; entry
; entry
= entry
->next
)
40 isom_box_t
*child
= (isom_box_t
*)entry
->data
;
41 if( LSMASH_IS_NON_EXISTING_BOX( child
) )
43 int ret
= isom_write_box( bs
, child
);
50 static int isom_write_binary_coded_box( lsmash_bs_t
*bs
, isom_box_t
*box
)
52 lsmash_bs_put_bytes( bs
, box
->size
, box
->binary
);
56 static int isom_write_unknown_box( lsmash_bs_t
*bs
, isom_box_t
*box
)
58 isom_unknown_box_t
*unknown_box
= (isom_unknown_box_t
*)box
;
59 isom_bs_put_box_common( bs
, unknown_box
);
60 if( unknown_box
->unknown_field
61 && unknown_box
->unknown_size
)
62 lsmash_bs_put_bytes( bs
, unknown_box
->unknown_size
, unknown_box
->unknown_field
);
66 static void isom_bs_put_qt_color_table( lsmash_bs_t
*bs
, isom_qt_color_table_t
*color_table
)
68 lsmash_bs_put_be32( bs
, color_table
->seed
);
69 lsmash_bs_put_be16( bs
, color_table
->flags
);
70 lsmash_bs_put_be16( bs
, color_table
->size
);
71 isom_qt_color_array_t
*array
= color_table
->array
;
73 for( uint16_t i
= 0; i
<= color_table
->size
; i
++ )
75 lsmash_bs_put_be16( bs
, array
[i
].value
);
76 lsmash_bs_put_be16( bs
, array
[i
].r
);
77 lsmash_bs_put_be16( bs
, array
[i
].g
);
78 lsmash_bs_put_be16( bs
, array
[i
].b
);
82 static int isom_write_ctab( lsmash_bs_t
*bs
, isom_box_t
*box
)
84 isom_ctab_t
*ctab
= (isom_ctab_t
*)box
;
85 isom_bs_put_box_common( bs
, ctab
);
86 isom_bs_put_qt_color_table( bs
, &ctab
->color_table
);
90 static int isom_write_tkhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
92 isom_tkhd_t
*tkhd
= (isom_tkhd_t
*)box
;
93 /* Check the version. */
94 if( (LSMASH_IS_EXISTING_BOX( tkhd
->file
) && !tkhd
->file
->undefined_64_ver
)
95 && (tkhd
->creation_time
> UINT32_MAX
96 || tkhd
->modification_time
> UINT32_MAX
97 || tkhd
->duration
> UINT32_MAX
) )
102 isom_bs_put_box_common( bs
, tkhd
);
105 lsmash_bs_put_be64( bs
, tkhd
->creation_time
);
106 lsmash_bs_put_be64( bs
, tkhd
->modification_time
);
107 lsmash_bs_put_be32( bs
, tkhd
->track_ID
);
108 lsmash_bs_put_be32( bs
, tkhd
->reserved1
);
109 lsmash_bs_put_be64( bs
, tkhd
->duration
);
113 lsmash_bs_put_be32( bs
, LSMASH_MIN( tkhd
->creation_time
, UINT32_MAX
) );
114 lsmash_bs_put_be32( bs
, LSMASH_MIN( tkhd
->modification_time
, UINT32_MAX
) );
115 lsmash_bs_put_be32( bs
, tkhd
->track_ID
);
116 lsmash_bs_put_be32( bs
, tkhd
->reserved1
);
117 lsmash_bs_put_be32( bs
, LSMASH_MIN( tkhd
->duration
, UINT32_MAX
) );
119 lsmash_bs_put_be32( bs
, tkhd
->reserved2
[0] );
120 lsmash_bs_put_be32( bs
, tkhd
->reserved2
[1] );
121 lsmash_bs_put_be16( bs
, tkhd
->layer
);
122 lsmash_bs_put_be16( bs
, tkhd
->alternate_group
);
123 lsmash_bs_put_be16( bs
, tkhd
->volume
);
124 lsmash_bs_put_be16( bs
, tkhd
->reserved3
);
125 for( uint32_t i
= 0; i
< 9; i
++ )
126 lsmash_bs_put_be32( bs
, tkhd
->matrix
[i
] );
127 lsmash_bs_put_be32( bs
, tkhd
->width
);
128 lsmash_bs_put_be32( bs
, tkhd
->height
);
132 static int isom_write_clef( lsmash_bs_t
*bs
, isom_box_t
*box
)
134 isom_clef_t
*clef
= (isom_clef_t
*)box
;
135 isom_bs_put_box_common( bs
, clef
);
136 lsmash_bs_put_be32( bs
, clef
->width
);
137 lsmash_bs_put_be32( bs
, clef
->height
);
141 static int isom_write_prof( lsmash_bs_t
*bs
, isom_box_t
*box
)
143 isom_prof_t
*prof
= (isom_prof_t
*)box
;
144 isom_bs_put_box_common( bs
, prof
);
145 lsmash_bs_put_be32( bs
, prof
->width
);
146 lsmash_bs_put_be32( bs
, prof
->height
);
150 static int isom_write_enof( lsmash_bs_t
*bs
, isom_box_t
*box
)
152 isom_enof_t
*enof
= (isom_enof_t
*)box
;
153 isom_bs_put_box_common( bs
, enof
);
154 lsmash_bs_put_be32( bs
, enof
->width
);
155 lsmash_bs_put_be32( bs
, enof
->height
);
159 static int isom_write_tapt( lsmash_bs_t
*bs
, isom_box_t
*box
)
161 isom_bs_put_box_common( bs
, box
);
165 static int isom_write_elst( lsmash_bs_t
*bs
, isom_box_t
*box
)
167 isom_elst_t
*elst
= (isom_elst_t
*)box
;
168 assert( elst
->list
);
169 if( elst
->list
->entry_count
== 0 )
172 lsmash_file_t
*file
= elst
->file
;
173 if( LSMASH_IS_EXISTING_BOX( file
) )
175 /* Check the version. */
176 if( !file
->undefined_64_ver
)
177 for( lsmash_entry_t
*entry
= elst
->list
->head
; entry
; entry
= entry
->next
)
179 isom_elst_entry_t
*data
= (isom_elst_entry_t
*)entry
->data
;
181 return LSMASH_ERR_NAMELESS
;
182 if( data
->segment_duration
> UINT32_MAX
183 || data
->media_time
> INT32_MAX
184 || data
->media_time
< INT32_MIN
)
187 /* Remember to rewrite entries. */
188 if( file
->fragment
&& !file
->bs
->unseekable
)
189 elst
->pos
= file
->bs
->written
;
192 isom_bs_put_box_common( bs
, elst
);
193 lsmash_bs_put_be32( bs
, elst
->list
->entry_count
);
194 for( lsmash_entry_t
*entry
= elst
->list
->head
; entry
; entry
= entry
->next
)
196 isom_elst_entry_t
*data
= (isom_elst_entry_t
*)entry
->data
;
199 lsmash_bs_put_be64( bs
, data
->segment_duration
);
200 lsmash_bs_put_be64( bs
, data
->media_time
);
204 lsmash_bs_put_be32( bs
, LSMASH_MIN( data
->segment_duration
, UINT32_MAX
) );
205 lsmash_bs_put_be32( bs
, data
->media_time
< 0 ? (uint32_t)data
->media_time
: LSMASH_MIN( data
->media_time
, INT32_MAX
) );
207 lsmash_bs_put_be32( bs
, data
->media_rate
);
212 static int isom_write_edts( lsmash_bs_t
*bs
, isom_box_t
*box
)
214 isom_bs_put_box_common( bs
, box
);
218 static int isom_write_tref( lsmash_bs_t
*bs
, isom_box_t
*box
)
220 isom_bs_put_box_common( bs
, box
);
224 static int isom_write_track_reference_type( lsmash_bs_t
*bs
, isom_box_t
*box
)
226 isom_tref_type_t
*ref
= (isom_tref_type_t
*)box
;
227 isom_bs_put_box_common( bs
, ref
);
228 for( uint32_t i
= 0; i
< ref
->ref_count
; i
++ )
229 lsmash_bs_put_be32( bs
, ref
->track_ID
[i
] );
233 static int isom_write_mdhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
235 isom_mdhd_t
*mdhd
= (isom_mdhd_t
*)box
;
236 /* Check the version. */
237 if( (LSMASH_IS_EXISTING_BOX( mdhd
->file
) && !mdhd
->file
->undefined_64_ver
)
238 && (mdhd
->creation_time
> UINT32_MAX
239 || mdhd
->modification_time
> UINT32_MAX
240 || mdhd
->duration
> UINT32_MAX
) )
245 isom_bs_put_box_common( bs
, mdhd
);
248 lsmash_bs_put_be64( bs
, mdhd
->creation_time
);
249 lsmash_bs_put_be64( bs
, mdhd
->modification_time
);
250 lsmash_bs_put_be32( bs
, mdhd
->timescale
);
251 lsmash_bs_put_be64( bs
, mdhd
->duration
);
255 lsmash_bs_put_be32( bs
, LSMASH_MIN( mdhd
->creation_time
, UINT32_MAX
) );
256 lsmash_bs_put_be32( bs
, LSMASH_MIN( mdhd
->modification_time
, UINT32_MAX
) );
257 lsmash_bs_put_be32( bs
, mdhd
->timescale
);
258 lsmash_bs_put_be32( bs
, LSMASH_MIN( mdhd
->duration
, UINT32_MAX
) );
260 lsmash_bs_put_be16( bs
, mdhd
->language
);
261 lsmash_bs_put_be16( bs
, mdhd
->quality
);
265 static int isom_write_hdlr( lsmash_bs_t
*bs
, isom_box_t
*box
)
267 isom_hdlr_t
*hdlr
= (isom_hdlr_t
*)box
;
268 isom_bs_put_box_common( bs
, hdlr
);
269 lsmash_bs_put_be32( bs
, hdlr
->componentType
);
270 lsmash_bs_put_be32( bs
, hdlr
->componentSubtype
);
271 lsmash_bs_put_be32( bs
, hdlr
->componentManufacturer
);
272 lsmash_bs_put_be32( bs
, hdlr
->componentFlags
);
273 lsmash_bs_put_be32( bs
, hdlr
->componentFlagsMask
);
274 lsmash_bs_put_bytes( bs
, hdlr
->componentName_length
, hdlr
->componentName
);
278 static int isom_write_vmhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
280 isom_vmhd_t
*vmhd
= (isom_vmhd_t
*)box
;
281 isom_bs_put_box_common( bs
, vmhd
);
282 lsmash_bs_put_be16( bs
, vmhd
->graphicsmode
);
283 for( uint32_t i
= 0; i
< 3; i
++ )
284 lsmash_bs_put_be16( bs
, vmhd
->opcolor
[i
] );
288 static int isom_write_smhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
290 isom_smhd_t
*smhd
= (isom_smhd_t
*)box
;
291 isom_bs_put_box_common( bs
, smhd
);
292 lsmash_bs_put_be16( bs
, smhd
->balance
);
293 lsmash_bs_put_be16( bs
, smhd
->reserved
);
297 static int isom_write_hmhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
299 isom_hmhd_t
*hmhd
= (isom_hmhd_t
*)box
;
300 isom_bs_put_box_common( bs
, hmhd
);
301 lsmash_bs_put_be16( bs
, hmhd
->maxPDUsize
);
302 lsmash_bs_put_be16( bs
, hmhd
->avgPDUsize
);
303 lsmash_bs_put_be32( bs
, hmhd
->maxbitrate
);
304 lsmash_bs_put_be32( bs
, hmhd
->avgbitrate
);
305 lsmash_bs_put_be32( bs
, hmhd
->reserved
);
309 static int isom_write_nmhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
311 isom_nmhd_t
*nmhd
= (isom_nmhd_t
*)box
;
312 isom_bs_put_box_common( bs
, nmhd
);
316 static int isom_write_gmin( lsmash_bs_t
*bs
, isom_box_t
*box
)
318 isom_gmin_t
*gmin
= (isom_gmin_t
*)box
;
319 isom_bs_put_box_common( bs
, gmin
);
320 lsmash_bs_put_be16( bs
, gmin
->graphicsmode
);
321 for( uint32_t i
= 0; i
< 3; i
++ )
322 lsmash_bs_put_be16( bs
, gmin
->opcolor
[i
] );
323 lsmash_bs_put_be16( bs
, gmin
->balance
);
324 lsmash_bs_put_be16( bs
, gmin
->reserved
);
328 static int isom_write_text( lsmash_bs_t
*bs
, isom_box_t
*box
)
330 isom_text_t
*text
= (isom_text_t
*)box
;
331 isom_bs_put_box_common( bs
, text
);
332 for( uint32_t i
= 0; i
< 9; i
++ )
333 lsmash_bs_put_be32( bs
, text
->matrix
[i
] );
337 static int isom_write_gmhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
339 isom_bs_put_box_common( bs
, box
);
343 static int isom_write_dref( lsmash_bs_t
*bs
, isom_box_t
*box
)
345 isom_dref_t
*dref
= (isom_dref_t
*)box
;
346 isom_bs_put_box_common( bs
, dref
);
347 lsmash_bs_put_be32( bs
, dref
->list
.entry_count
);
351 static int isom_write_url( lsmash_bs_t
*bs
, isom_box_t
*box
)
353 isom_dref_entry_t
*url
= (isom_dref_entry_t
*)box
;
354 isom_bs_put_box_common( bs
, url
);
355 lsmash_bs_put_bytes( bs
, url
->location_length
, url
->location
);
359 static int isom_write_dinf( lsmash_bs_t
*bs
, isom_box_t
*box
)
361 isom_bs_put_box_common( bs
, box
);
365 static int isom_write_pasp( lsmash_bs_t
*bs
, isom_box_t
*box
)
367 isom_pasp_t
*pasp
= (isom_pasp_t
*)box
;
368 isom_bs_put_box_common( bs
, pasp
);
369 lsmash_bs_put_be32( bs
, pasp
->hSpacing
);
370 lsmash_bs_put_be32( bs
, pasp
->vSpacing
);
374 static int isom_write_clap( lsmash_bs_t
*bs
, isom_box_t
*box
)
376 isom_clap_t
*clap
= (isom_clap_t
*)box
;
377 isom_bs_put_box_common( bs
, clap
);
378 lsmash_bs_put_be32( bs
, clap
->cleanApertureWidthN
);
379 lsmash_bs_put_be32( bs
, clap
->cleanApertureWidthD
);
380 lsmash_bs_put_be32( bs
, clap
->cleanApertureHeightN
);
381 lsmash_bs_put_be32( bs
, clap
->cleanApertureHeightD
);
382 lsmash_bs_put_be32( bs
, clap
->horizOffN
);
383 lsmash_bs_put_be32( bs
, clap
->horizOffD
);
384 lsmash_bs_put_be32( bs
, clap
->vertOffN
);
385 lsmash_bs_put_be32( bs
, clap
->vertOffD
);
389 static int isom_write_colr( lsmash_bs_t
*bs
, isom_box_t
*box
)
391 isom_colr_t
*colr
= (isom_colr_t
*)box
;
392 if( colr
->color_parameter_type
!= ISOM_COLOR_PARAMETER_TYPE_NCLX
393 && colr
->color_parameter_type
!= QT_COLOR_PARAMETER_TYPE_NCLC
)
395 isom_bs_put_box_common( bs
, colr
);
396 lsmash_bs_put_be32( bs
, colr
->color_parameter_type
);
397 lsmash_bs_put_be16( bs
, colr
->primaries_index
);
398 lsmash_bs_put_be16( bs
, colr
->transfer_function_index
);
399 lsmash_bs_put_be16( bs
, colr
->matrix_index
);
400 if( colr
->color_parameter_type
== ISOM_COLOR_PARAMETER_TYPE_NCLX
)
401 lsmash_bs_put_byte( bs
, (colr
->full_range_flag
<< 7) | colr
->reserved
);
405 static int isom_write_gama( lsmash_bs_t
*bs
, isom_box_t
*box
)
407 isom_gama_t
*gama
= (isom_gama_t
*)box
;
410 /* Note: 'gama' box is superseded by 'colr' box.
411 * Therefore, writers of QTFF should never write both 'colr' and 'gama' box into an Image Description. */
412 if( isom_get_extension_box_format( &((isom_visual_entry_t
*)gama
->parent
)->extensions
, QT_BOX_TYPE_COLR
) )
414 isom_bs_put_box_common( bs
, gama
);
415 lsmash_bs_put_be32( bs
, gama
->level
);
419 static int isom_write_fiel( lsmash_bs_t
*bs
, isom_box_t
*box
)
421 isom_fiel_t
*fiel
= (isom_fiel_t
*)box
;
422 isom_bs_put_box_common( bs
, fiel
);
423 lsmash_bs_put_byte( bs
, fiel
->fields
);
424 lsmash_bs_put_byte( bs
, fiel
->detail
);
428 static int isom_write_clli( lsmash_bs_t
*bs
, isom_box_t
*box
)
430 isom_clli_t
*clli
= (isom_clli_t
*)box
;
431 isom_bs_put_box_common( bs
, clli
);
432 lsmash_bs_put_be16( bs
, clli
->max_content_light_level
);
433 lsmash_bs_put_be16( bs
, clli
->max_pic_average_light_level
);
437 static int isom_write_mdcv( lsmash_bs_t
*bs
, isom_box_t
*box
)
439 isom_mdcv_t
*mdcv
= (isom_mdcv_t
*)box
;
440 isom_bs_put_box_common( bs
, mdcv
);
441 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_g_x
);
442 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_g_y
);
443 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_b_x
);
444 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_b_y
);
445 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_r_x
);
446 lsmash_bs_put_be16( bs
, mdcv
->display_primaries_r_y
);
447 lsmash_bs_put_be16( bs
, mdcv
->white_point_x
);
448 lsmash_bs_put_be16( bs
, mdcv
->white_point_y
);
449 lsmash_bs_put_be32( bs
, mdcv
->max_display_mastering_luminance
);
450 lsmash_bs_put_be32( bs
, mdcv
->min_display_mastering_luminance
);
454 static int isom_write_cspc( lsmash_bs_t
*bs
, isom_box_t
*box
)
456 isom_cspc_t
*cspc
= (isom_cspc_t
*)box
;
457 isom_bs_put_box_common( bs
, cspc
);
458 lsmash_bs_put_be32( bs
, cspc
->pixel_format
);
462 static int isom_write_sgbt( lsmash_bs_t
*bs
, isom_box_t
*box
)
464 isom_sgbt_t
*sgbt
= (isom_sgbt_t
*)box
;
465 isom_bs_put_box_common( bs
, sgbt
);
466 lsmash_bs_put_byte( bs
, sgbt
->significantBits
);
470 static int isom_write_stsl( lsmash_bs_t
*bs
, isom_box_t
*box
)
472 isom_stsl_t
*stsl
= (isom_stsl_t
*)box
;
473 isom_bs_put_box_common( bs
, stsl
);
474 lsmash_bs_put_byte( bs
, stsl
->constraint_flag
);
475 lsmash_bs_put_byte( bs
, stsl
->scale_method
);
476 lsmash_bs_put_be16( bs
, stsl
->display_center_x
);
477 lsmash_bs_put_be16( bs
, stsl
->display_center_y
);
481 static int isom_write_esds( lsmash_bs_t
*bs
, isom_box_t
*box
)
483 isom_esds_t
*esds
= (isom_esds_t
*)box
;
484 isom_bs_put_box_common( bs
, esds
);
485 mp4sys_update_descriptor_size( esds
->ES
);
486 return mp4sys_write_descriptor( bs
, esds
->ES
);
489 static int isom_write_btrt( lsmash_bs_t
*bs
, isom_box_t
*box
)
491 isom_btrt_t
*btrt
= (isom_btrt_t
*)box
;
492 isom_bs_put_box_common( bs
, btrt
);
493 lsmash_bs_put_be32( bs
, btrt
->bufferSizeDB
);
494 lsmash_bs_put_be32( bs
, btrt
->maxBitrate
);
495 lsmash_bs_put_be32( bs
, btrt
->avgBitrate
);
499 static int isom_write_tims( lsmash_bs_t
*bs
, isom_box_t
*box
)
501 isom_tims_t
*tims
= (isom_tims_t
*)box
;
502 isom_bs_put_box_common( bs
, tims
);
503 lsmash_bs_put_be32( bs
, tims
->timescale
);
507 static int isom_write_tsro( lsmash_bs_t
*bs
, isom_box_t
*box
)
509 isom_tsro_t
*tsro
= (isom_tsro_t
*)box
;
510 isom_bs_put_box_common( bs
, tsro
);
511 lsmash_bs_put_be32( bs
, tsro
->offset
);
515 static int isom_write_tssy( lsmash_bs_t
*bs
, isom_box_t
*box
)
517 isom_tssy_t
*tssy
= (isom_tssy_t
*)box
;
518 isom_bs_put_box_common( bs
, tssy
);
520 data
= tssy
->reserved
<< 2;
521 data
|= tssy
->timestamp_sync
;
522 lsmash_bs_put_byte( bs
, data
);
526 static int isom_write_glbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
528 isom_glbl_t
*glbl
= (isom_glbl_t
*)box
;
529 isom_bs_put_box_common( bs
, glbl
);
530 if( glbl
->header_data
&& glbl
->header_size
)
531 lsmash_bs_put_bytes( bs
, glbl
->header_size
, glbl
->header_data
);
535 static int isom_write_frma( lsmash_bs_t
*bs
, isom_box_t
*box
)
537 isom_frma_t
*frma
= (isom_frma_t
*)box
;
538 isom_bs_put_box_common( bs
, frma
);
539 lsmash_bs_put_be32( bs
, frma
->data_format
);
543 static int isom_write_enda( lsmash_bs_t
*bs
, isom_box_t
*box
)
545 isom_enda_t
*enda
= (isom_enda_t
*)box
;
546 isom_bs_put_box_common( bs
, enda
);
547 lsmash_bs_put_be16( bs
, enda
->littleEndian
);
551 static int isom_write_mp4a( lsmash_bs_t
*bs
, isom_box_t
*box
)
553 isom_mp4a_t
*mp4a
= (isom_mp4a_t
*)box
;
554 isom_bs_put_box_common( bs
, mp4a
);
555 lsmash_bs_put_be32( bs
, mp4a
->unknown
);
559 static int isom_write_chan( lsmash_bs_t
*bs
, isom_box_t
*box
)
561 isom_chan_t
*chan
= (isom_chan_t
*)box
;
562 isom_bs_put_box_common( bs
, chan
);
563 lsmash_bs_put_be32( bs
, chan
->channelLayoutTag
);
564 lsmash_bs_put_be32( bs
, chan
->channelBitmap
);
565 lsmash_bs_put_be32( bs
, chan
->numberChannelDescriptions
);
566 if( chan
->channelDescriptions
)
567 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
569 isom_channel_description_t
*channelDescriptions
= (isom_channel_description_t
*)(&chan
->channelDescriptions
[i
]);
570 lsmash_bs_put_be32( bs
, channelDescriptions
->channelLabel
);
571 lsmash_bs_put_be32( bs
, channelDescriptions
->channelFlags
);
572 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[0] );
573 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[1] );
574 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[2] );
579 static int isom_write_terminator( lsmash_bs_t
*bs
, isom_box_t
*box
)
581 isom_bs_put_box_common( bs
, box
);
585 static int isom_write_wave( lsmash_bs_t
*bs
, isom_box_t
*box
)
587 isom_bs_put_box_common( bs
, box
);
591 static int isom_write_visual_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
593 isom_visual_entry_t
*data
= (isom_visual_entry_t
*)box
;
594 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
595 return LSMASH_ERR_NAMELESS
;
596 isom_bs_put_box_common( bs
, data
);
597 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
598 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
599 lsmash_bs_put_be16( bs
, data
->version
);
600 lsmash_bs_put_be16( bs
, data
->revision_level
);
601 lsmash_bs_put_be32( bs
, data
->vendor
);
602 lsmash_bs_put_be32( bs
, data
->temporalQuality
);
603 lsmash_bs_put_be32( bs
, data
->spatialQuality
);
604 lsmash_bs_put_be16( bs
, data
->width
);
605 lsmash_bs_put_be16( bs
, data
->height
);
606 lsmash_bs_put_be32( bs
, data
->horizresolution
);
607 lsmash_bs_put_be32( bs
, data
->vertresolution
);
608 lsmash_bs_put_be32( bs
, data
->dataSize
);
609 lsmash_bs_put_be16( bs
, data
->frame_count
);
610 lsmash_bs_put_bytes( bs
, 32, data
->compressorname
);
611 lsmash_bs_put_be16( bs
, data
->depth
);
612 lsmash_bs_put_be16( bs
, data
->color_table_ID
);
613 if( data
->color_table_ID
== 0 )
614 isom_bs_put_qt_color_table( bs
, &data
->color_table
);
618 static int isom_write_audio_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
620 isom_audio_entry_t
*data
= (isom_audio_entry_t
*)box
;
621 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
622 return LSMASH_ERR_NAMELESS
;
623 isom_bs_put_box_common( bs
, data
);
624 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
625 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
626 lsmash_bs_put_be16( bs
, data
->version
);
627 lsmash_bs_put_be16( bs
, data
->revision_level
);
628 lsmash_bs_put_be32( bs
, data
->vendor
);
629 lsmash_bs_put_be16( bs
, data
->channelcount
);
630 lsmash_bs_put_be16( bs
, data
->samplesize
);
631 lsmash_bs_put_be16( bs
, data
->compression_ID
);
632 lsmash_bs_put_be16( bs
, data
->packet_size
);
633 lsmash_bs_put_be32( bs
, data
->samplerate
);
634 if( data
->version
== 1 )
636 lsmash_bs_put_be32( bs
, data
->samplesPerPacket
);
637 lsmash_bs_put_be32( bs
, data
->bytesPerPacket
);
638 lsmash_bs_put_be32( bs
, data
->bytesPerFrame
);
639 lsmash_bs_put_be32( bs
, data
->bytesPerSample
);
641 else if( data
->version
== 2 )
643 lsmash_bs_put_be32( bs
, data
->sizeOfStructOnly
);
644 lsmash_bs_put_be64( bs
, data
->audioSampleRate
);
645 lsmash_bs_put_be32( bs
, data
->numAudioChannels
);
646 lsmash_bs_put_be32( bs
, data
->always7F000000
);
647 lsmash_bs_put_be32( bs
, data
->constBitsPerChannel
);
648 lsmash_bs_put_be32( bs
, data
->formatSpecificFlags
);
649 lsmash_bs_put_be32( bs
, data
->constBytesPerAudioPacket
);
650 lsmash_bs_put_be32( bs
, data
->constLPCMFramesPerAudioPacket
);
655 static int isom_write_hint_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
657 isom_hint_entry_t
*data
= (isom_hint_entry_t
*)box
;
658 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
659 return LSMASH_ERR_NAMELESS
;
660 isom_bs_put_box_common( bs
, data
);
661 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
662 lsmash_bs_put_be16( bs
, data
->hinttrackversion
);
663 lsmash_bs_put_be16( bs
, data
->highestcompatibleversion
);
664 lsmash_bs_put_be32( bs
, data
->maxpacketsize
);
669 static int isom_write_metadata_description( lsmash_bs_t
*bs
, lsmash_entry_t
*entry
)
671 isom_metadata_entry_t
*data
= (isom_metadata_entry_t
*)entry
->data
;
672 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
673 return LSMASH_ERR_NAMELESS
;
674 isom_bs_put_box_common( bs
, data
);
675 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
676 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
681 static int isom_write_qt_text_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
683 isom_qt_text_entry_t
*data
= (isom_qt_text_entry_t
*)box
;
684 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
685 return LSMASH_ERR_NAMELESS
;
686 isom_bs_put_box_common( bs
, data
);
687 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
688 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
689 lsmash_bs_put_be32( bs
, data
->displayFlags
);
690 lsmash_bs_put_be32( bs
, data
->textJustification
);
691 for( uint32_t i
= 0; i
< 3; i
++ )
692 lsmash_bs_put_be16( bs
, data
->bgColor
[i
] );
693 lsmash_bs_put_be16( bs
, data
->top
);
694 lsmash_bs_put_be16( bs
, data
->left
);
695 lsmash_bs_put_be16( bs
, data
->bottom
);
696 lsmash_bs_put_be16( bs
, data
->right
);
697 lsmash_bs_put_be32( bs
, data
->scrpStartChar
);
698 lsmash_bs_put_be16( bs
, data
->scrpHeight
);
699 lsmash_bs_put_be16( bs
, data
->scrpAscent
);
700 lsmash_bs_put_be16( bs
, data
->scrpFont
);
701 lsmash_bs_put_be16( bs
, data
->scrpFace
);
702 lsmash_bs_put_be16( bs
, data
->scrpSize
);
703 for( uint32_t i
= 0; i
< 3; i
++ )
704 lsmash_bs_put_be16( bs
, data
->scrpColor
[i
] );
705 lsmash_bs_put_byte( bs
, data
->font_name_length
);
706 if( data
->font_name
&& data
->font_name_length
)
707 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
711 static int isom_write_ftab( lsmash_bs_t
*bs
, isom_box_t
*box
)
713 isom_ftab_t
*ftab
= (isom_ftab_t
*)box
;
714 assert( ftab
->list
);
715 isom_bs_put_box_common( bs
, ftab
);
716 lsmash_bs_put_be16( bs
, ftab
->list
->entry_count
);
717 for( lsmash_entry_t
*entry
= ftab
->list
->head
; entry
; entry
= entry
->next
)
719 isom_font_record_t
*data
= (isom_font_record_t
*)entry
->data
;
721 return LSMASH_ERR_NAMELESS
;
722 lsmash_bs_put_be16( bs
, data
->font_ID
);
723 lsmash_bs_put_byte( bs
, data
->font_name_length
);
724 if( data
->font_name
&& data
->font_name_length
)
725 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
730 static int isom_write_tx3g_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
732 isom_tx3g_entry_t
*data
= (isom_tx3g_entry_t
*)box
;
733 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
734 return LSMASH_ERR_NAMELESS
;
735 isom_bs_put_box_common( bs
, data
);
736 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
737 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
738 lsmash_bs_put_be32( bs
, data
->displayFlags
);
739 lsmash_bs_put_byte( bs
, data
->horizontal_justification
);
740 lsmash_bs_put_byte( bs
, data
->vertical_justification
);
741 for( uint32_t i
= 0; i
< 4; i
++ )
742 lsmash_bs_put_byte( bs
, data
->background_color_rgba
[i
] );
743 lsmash_bs_put_be16( bs
, data
->top
);
744 lsmash_bs_put_be16( bs
, data
->left
);
745 lsmash_bs_put_be16( bs
, data
->bottom
);
746 lsmash_bs_put_be16( bs
, data
->right
);
747 lsmash_bs_put_be16( bs
, data
->startChar
);
748 lsmash_bs_put_be16( bs
, data
->endChar
);
749 lsmash_bs_put_be16( bs
, data
->font_ID
);
750 lsmash_bs_put_byte( bs
, data
->face_style_flags
);
751 lsmash_bs_put_byte( bs
, data
->font_size
);
752 for( uint32_t i
= 0; i
< 4; i
++ )
753 lsmash_bs_put_byte( bs
, data
->text_color_rgba
[i
] );
757 static int isom_write_stsd( lsmash_bs_t
*bs
, isom_box_t
*box
)
759 isom_stsd_t
*stsd
= (isom_stsd_t
*)box
;
760 isom_bs_put_box_common( bs
, stsd
);
761 lsmash_bs_put_be32( bs
, stsd
->list
.entry_count
);
765 static int isom_write_stts( lsmash_bs_t
*bs
, isom_box_t
*box
)
767 isom_stts_t
*stts
= (isom_stts_t
*)box
;
768 assert( stts
->list
);
769 isom_bs_put_box_common( bs
, stts
);
770 lsmash_bs_put_be32( bs
, stts
->list
->entry_count
);
771 for( lsmash_entry_t
*entry
= stts
->list
->head
; entry
; entry
= entry
->next
)
773 isom_stts_entry_t
*data
= (isom_stts_entry_t
*)entry
->data
;
775 return LSMASH_ERR_NAMELESS
;
776 lsmash_bs_put_be32( bs
, data
->sample_count
);
777 lsmash_bs_put_be32( bs
, data
->sample_delta
);
782 static int isom_write_ctts( lsmash_bs_t
*bs
, isom_box_t
*box
)
784 isom_ctts_t
*ctts
= (isom_ctts_t
*)box
;
785 assert( ctts
->list
);
786 isom_bs_put_box_common( bs
, ctts
);
787 lsmash_bs_put_be32( bs
, ctts
->list
->entry_count
);
788 for( lsmash_entry_t
*entry
= ctts
->list
->head
; entry
; entry
= entry
->next
)
790 isom_ctts_entry_t
*data
= (isom_ctts_entry_t
*)entry
->data
;
792 return LSMASH_ERR_NAMELESS
;
793 lsmash_bs_put_be32( bs
, data
->sample_count
);
794 lsmash_bs_put_be32( bs
, data
->sample_offset
);
799 static int isom_write_cslg( lsmash_bs_t
*bs
, isom_box_t
*box
)
801 isom_cslg_t
*cslg
= (isom_cslg_t
*)box
;
802 isom_bs_put_box_common( bs
, cslg
);
803 lsmash_bs_put_be32( bs
, cslg
->compositionToDTSShift
);
804 lsmash_bs_put_be32( bs
, cslg
->leastDecodeToDisplayDelta
);
805 lsmash_bs_put_be32( bs
, cslg
->greatestDecodeToDisplayDelta
);
806 lsmash_bs_put_be32( bs
, cslg
->compositionStartTime
);
807 lsmash_bs_put_be32( bs
, cslg
->compositionEndTime
);
811 static int isom_write_stsz( lsmash_bs_t
*bs
, isom_box_t
*box
)
813 isom_stsz_t
*stsz
= (isom_stsz_t
*)box
;
814 isom_bs_put_box_common( bs
, stsz
);
815 lsmash_bs_put_be32( bs
, stsz
->sample_size
);
816 lsmash_bs_put_be32( bs
, stsz
->sample_count
);
817 if( stsz
->sample_size
== 0 && stsz
->list
)
818 for( lsmash_entry_t
*entry
= stsz
->list
->head
; entry
; entry
= entry
->next
)
820 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
822 return LSMASH_ERR_NAMELESS
;
823 lsmash_bs_put_be32( bs
, data
->entry_size
);
828 static int isom_write_stz2( lsmash_bs_t
*bs
, isom_box_t
*box
)
830 isom_stz2_t
*stz2
= (isom_stz2_t
*)box
;
831 isom_bs_put_box_common( bs
, stz2
);
832 lsmash_bs_put_be32( bs
, (stz2
->reserved
<< 8) | stz2
->field_size
);
833 lsmash_bs_put_be32( bs
, stz2
->sample_count
);
834 if( stz2
->field_size
== 16 )
835 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
837 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
839 return LSMASH_ERR_NAMELESS
;
840 assert( data
->entry_size
<= 0xffff );
841 lsmash_bs_put_be16( bs
, data
->entry_size
);
843 else if( stz2
->field_size
== 8 )
844 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
846 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
848 return LSMASH_ERR_NAMELESS
;
849 assert( data
->entry_size
<= 0xff );
850 lsmash_bs_put_byte( bs
, data
->entry_size
);
852 else if( stz2
->field_size
== 4 )
854 isom_stsz_entry_t zero_padding
= { .entry_size
= 0 };
855 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
? entry
->next
->next
: entry
->next
)
857 isom_stsz_entry_t
*data_o
= (isom_stsz_entry_t
*)entry
->data
;
858 isom_stsz_entry_t
*data_e
= (isom_stsz_entry_t
*)(entry
->next
? entry
->next
->data
: &zero_padding
);
859 if( !data_o
|| !data_e
)
860 return LSMASH_ERR_NAMELESS
;
861 assert( data_o
->entry_size
<= 0xf && data_e
->entry_size
<= 0xf );
862 lsmash_bs_put_byte( bs
, (data_o
->entry_size
<< 4) | data_e
->entry_size
);
866 return LSMASH_ERR_NAMELESS
;
870 static int isom_write_stss( lsmash_bs_t
*bs
, isom_box_t
*box
)
872 isom_stss_t
*stss
= (isom_stss_t
*)box
;
873 assert( stss
->list
);
874 isom_bs_put_box_common( bs
, stss
);
875 lsmash_bs_put_be32( bs
, stss
->list
->entry_count
);
876 for( lsmash_entry_t
*entry
= stss
->list
->head
; entry
; entry
= entry
->next
)
878 isom_stss_entry_t
*data
= (isom_stss_entry_t
*)entry
->data
;
880 return LSMASH_ERR_NAMELESS
;
881 lsmash_bs_put_be32( bs
, data
->sample_number
);
886 static int isom_write_stps( lsmash_bs_t
*bs
, isom_box_t
*box
)
888 isom_stps_t
*stps
= (isom_stps_t
*)box
;
889 assert( stps
->list
);
890 isom_bs_put_box_common( bs
, stps
);
891 lsmash_bs_put_be32( bs
, stps
->list
->entry_count
);
892 for( lsmash_entry_t
*entry
= stps
->list
->head
; entry
; entry
= entry
->next
)
894 isom_stps_entry_t
*data
= (isom_stps_entry_t
*)entry
->data
;
896 return LSMASH_ERR_NAMELESS
;
897 lsmash_bs_put_be32( bs
, data
->sample_number
);
902 static int isom_write_sdtp( lsmash_bs_t
*bs
, isom_box_t
*box
)
904 isom_sdtp_t
*sdtp
= (isom_sdtp_t
*)box
;
905 assert( sdtp
->list
);
906 isom_bs_put_box_common( bs
, sdtp
);
907 for( lsmash_entry_t
*entry
= sdtp
->list
->head
; entry
; entry
= entry
->next
)
909 isom_sdtp_entry_t
*data
= (isom_sdtp_entry_t
*)entry
->data
;
911 return LSMASH_ERR_NAMELESS
;
912 uint8_t temp
= (data
->is_leading
<< 6)
913 | (data
->sample_depends_on
<< 4)
914 | (data
->sample_is_depended_on
<< 2)
915 | data
->sample_has_redundancy
;
916 lsmash_bs_put_byte( bs
, temp
);
921 static int isom_write_stsc( lsmash_bs_t
*bs
, isom_box_t
*box
)
923 isom_stsc_t
*stsc
= (isom_stsc_t
*)box
;
924 assert( stsc
->list
);
925 isom_bs_put_box_common( bs
, stsc
);
926 lsmash_bs_put_be32( bs
, stsc
->list
->entry_count
);
927 for( lsmash_entry_t
*entry
= stsc
->list
->head
; entry
; entry
= entry
->next
)
929 isom_stsc_entry_t
*data
= (isom_stsc_entry_t
*)entry
->data
;
931 return LSMASH_ERR_NAMELESS
;
932 lsmash_bs_put_be32( bs
, data
->first_chunk
);
933 lsmash_bs_put_be32( bs
, data
->samples_per_chunk
);
934 lsmash_bs_put_be32( bs
, data
->sample_description_index
);
939 static int isom_write_co64( lsmash_bs_t
*bs
, isom_box_t
*box
)
941 isom_stco_t
*co64
= (isom_stco_t
*)box
;
942 assert( co64
->list
);
943 isom_bs_put_box_common( bs
, co64
);
944 lsmash_bs_put_be32( bs
, co64
->list
->entry_count
);
945 for( lsmash_entry_t
*entry
= co64
->list
->head
; entry
; entry
= entry
->next
)
947 isom_co64_entry_t
*data
= (isom_co64_entry_t
*)entry
->data
;
949 return LSMASH_ERR_NAMELESS
;
950 lsmash_bs_put_be64( bs
, data
->chunk_offset
);
955 static int isom_write_stco( lsmash_bs_t
*bs
, isom_box_t
*box
)
957 isom_stco_t
*stco
= (isom_stco_t
*)box
;
958 if( stco
->large_presentation
)
959 return isom_write_co64( bs
, box
);
960 assert( stco
->list
);
961 isom_bs_put_box_common( bs
, stco
);
962 lsmash_bs_put_be32( bs
, stco
->list
->entry_count
);
963 for( lsmash_entry_t
*entry
= stco
->list
->head
; entry
; entry
= entry
->next
)
965 isom_stco_entry_t
*data
= (isom_stco_entry_t
*)entry
->data
;
967 return LSMASH_ERR_NAMELESS
;
968 lsmash_bs_put_be32( bs
, data
->chunk_offset
);
973 static int isom_write_sgpd( lsmash_bs_t
*bs
, isom_box_t
*box
)
975 isom_sgpd_t
*sgpd
= (isom_sgpd_t
*)box
;
976 assert( sgpd
->list
);
977 isom_bs_put_box_common( bs
, sgpd
);
978 lsmash_bs_put_be32( bs
, sgpd
->grouping_type
);
979 if( sgpd
->version
== 1 )
980 lsmash_bs_put_be32( bs
, sgpd
->default_length
);
981 lsmash_bs_put_be32( bs
, sgpd
->list
->entry_count
);
982 for( lsmash_entry_t
*entry
= sgpd
->list
->head
; entry
; entry
= entry
->next
)
985 return LSMASH_ERR_NAMELESS
;
986 switch( sgpd
->grouping_type
)
988 case ISOM_GROUP_TYPE_RAP
:
990 isom_rap_entry_t
*rap
= (isom_rap_entry_t
*)entry
->data
;
991 uint8_t temp
= (rap
->num_leading_samples_known
<< 7)
992 | rap
->num_leading_samples
;
993 lsmash_bs_put_byte( bs
, temp
);
996 case ISOM_GROUP_TYPE_ROLL
:
997 case ISOM_GROUP_TYPE_PROL
:
998 lsmash_bs_put_be16( bs
, ((isom_roll_entry_t
*)entry
->data
)->roll_distance
);
1001 /* We don't consider other grouping types currently. */
1002 // if( sgpd->version == 1 && !sgpd->default_length )
1003 // lsmash_bs_put_be32( bs, ((isom_sgpd_t *)entry->data)->description_length );
1010 static int isom_write_sbgp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1012 isom_sbgp_t
*sbgp
= (isom_sbgp_t
*)box
;
1013 assert( sbgp
->list
);
1014 isom_bs_put_box_common( bs
, sbgp
);
1015 lsmash_bs_put_be32( bs
, sbgp
->grouping_type
);
1016 if( sbgp
->version
== 1 )
1017 lsmash_bs_put_be32( bs
, sbgp
->grouping_type_parameter
);
1018 lsmash_bs_put_be32( bs
, sbgp
->list
->entry_count
);
1019 for( lsmash_entry_t
*entry
= sbgp
->list
->head
; entry
; entry
= entry
->next
)
1021 isom_group_assignment_entry_t
*data
= (isom_group_assignment_entry_t
*)entry
->data
;
1023 return LSMASH_ERR_NAMELESS
;
1024 lsmash_bs_put_be32( bs
, data
->sample_count
);
1025 lsmash_bs_put_be32( bs
, data
->group_description_index
);
1030 static int isom_write_stbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
1032 isom_bs_put_box_common( bs
, box
);
1036 static int isom_write_minf( lsmash_bs_t
*bs
, isom_box_t
*box
)
1038 isom_bs_put_box_common( bs
, box
);
1042 static int isom_write_mdia( lsmash_bs_t
*bs
, isom_box_t
*box
)
1044 isom_bs_put_box_common( bs
, box
);
1048 static int isom_write_chpl( lsmash_bs_t
*bs
, isom_box_t
*box
)
1050 isom_chpl_t
*chpl
= (isom_chpl_t
*)box
;
1051 assert( chpl
->list
);
1052 isom_bs_put_box_common( bs
, chpl
);
1053 if( chpl
->version
== 1 )
1055 lsmash_bs_put_byte( bs
, chpl
->unknown
);
1056 lsmash_bs_put_be32( bs
, chpl
->list
->entry_count
);
1058 else /* chpl->version == 0 */
1059 lsmash_bs_put_byte( bs
, (uint8_t)chpl
->list
->entry_count
);
1060 for( lsmash_entry_t
*entry
= chpl
->list
->head
; entry
; entry
= entry
->next
)
1062 isom_chpl_entry_t
*data
= (isom_chpl_entry_t
*)entry
->data
;
1064 return LSMASH_ERR_NAMELESS
;
1065 lsmash_bs_put_be64( bs
, data
->start_time
);
1066 lsmash_bs_put_byte( bs
, data
->chapter_name_length
);
1067 lsmash_bs_put_bytes( bs
, data
->chapter_name_length
, data
->chapter_name
);
1072 static int isom_write_mean( lsmash_bs_t
*bs
, isom_box_t
*box
)
1074 isom_mean_t
*mean
= (isom_mean_t
*)box
;
1075 isom_bs_put_box_common( bs
, mean
);
1076 if( mean
->meaning_string
&& mean
->meaning_string_length
)
1077 lsmash_bs_put_bytes( bs
, mean
->meaning_string_length
, mean
->meaning_string
);
1081 static int isom_write_name( lsmash_bs_t
*bs
, isom_box_t
*box
)
1083 isom_name_t
*name
= (isom_name_t
*)box
;
1084 isom_bs_put_box_common( bs
, name
);
1085 if( name
->name
&& name
->name_length
)
1086 lsmash_bs_put_bytes( bs
, name
->name_length
, name
->name
);
1090 static int isom_write_data( lsmash_bs_t
*bs
, isom_box_t
*box
)
1092 isom_data_t
*data
= (isom_data_t
*)box
;
1093 isom_bs_put_box_common( bs
, data
);
1094 lsmash_bs_put_be16( bs
, data
->reserved
);
1095 lsmash_bs_put_byte( bs
, data
->type_set_identifier
);
1096 lsmash_bs_put_byte( bs
, data
->type_code
);
1097 lsmash_bs_put_be32( bs
, data
->the_locale
);
1098 if( data
->value
&& data
->value_length
)
1099 lsmash_bs_put_bytes( bs
, data
->value_length
, data
->value
);
1103 static int isom_write_metaitem( lsmash_bs_t
*bs
, isom_box_t
*box
)
1105 isom_bs_put_box_common( bs
, box
);
1109 static int isom_write_ilst( lsmash_bs_t
*bs
, isom_box_t
*box
)
1111 isom_bs_put_box_common( bs
, box
);
1115 static int isom_write_meta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1117 isom_bs_put_box_common( bs
, box
);
1121 static int isom_write_cprt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1123 isom_cprt_t
*cprt
= (isom_cprt_t
*)box
;
1124 isom_bs_put_box_common( bs
, cprt
);
1125 lsmash_bs_put_be16( bs
, cprt
->language
);
1126 lsmash_bs_put_bytes( bs
, cprt
->notice_length
, cprt
->notice
);
1130 static int isom_write_udta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1132 isom_bs_put_box_common( bs
, box
);
1136 static int isom_write_hnti( lsmash_bs_t
*bs
, isom_box_t
*box
)
1138 isom_bs_put_box_common( bs
, box
);
1142 static int isom_write_rtp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1144 isom_rtp_t
*rtp
= (isom_rtp_t
*)box
;
1145 isom_bs_put_box_common( bs
, rtp
);
1146 lsmash_bs_put_be32( bs
, rtp
->descriptionformat
);
1147 lsmash_bs_put_bytes( bs
, rtp
->sdp_length
, rtp
->sdptext
);
1150 static int isom_write_sdp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1152 isom_sdp_t
*sdp
= (isom_sdp_t
*)box
;
1153 isom_bs_put_box_common( bs
, sdp
);
1154 lsmash_bs_put_bytes( bs
, sdp
->sdp_length
, sdp
->sdptext
);
1158 static int isom_write_trak( lsmash_bs_t
*bs
, isom_box_t
*box
)
1160 isom_bs_put_box_common( bs
, box
);
1164 static int isom_write_iods( lsmash_bs_t
*bs
, isom_box_t
*box
)
1166 isom_iods_t
*iods
= (isom_iods_t
*)box
;
1167 isom_bs_put_box_common( bs
, iods
);
1168 mp4sys_update_descriptor_size( iods
->OD
);
1169 return mp4sys_write_descriptor( bs
, iods
->OD
);
1172 static int isom_write_mvhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1174 isom_mvhd_t
*mvhd
= (isom_mvhd_t
*)box
;
1175 /* Check the version. */
1176 if( (LSMASH_IS_EXISTING_BOX( mvhd
->file
) && !mvhd
->file
->undefined_64_ver
)
1177 && (mvhd
->creation_time
> UINT32_MAX
1178 || mvhd
->modification_time
> UINT32_MAX
1179 || mvhd
->duration
> UINT32_MAX
) )
1184 isom_bs_put_box_common( bs
, mvhd
);
1187 lsmash_bs_put_be64( bs
, mvhd
->creation_time
);
1188 lsmash_bs_put_be64( bs
, mvhd
->modification_time
);
1189 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1190 lsmash_bs_put_be64( bs
, mvhd
->duration
);
1194 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->creation_time
, UINT32_MAX
) );
1195 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->modification_time
, UINT32_MAX
) );
1196 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1197 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->duration
, UINT32_MAX
) );
1199 lsmash_bs_put_be32( bs
, mvhd
->rate
);
1200 lsmash_bs_put_be16( bs
, mvhd
->volume
);
1201 lsmash_bs_put_be16( bs
, mvhd
->reserved
);
1202 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[0] );
1203 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[1] );
1204 for( int i
= 0; i
< 9; i
++ )
1205 lsmash_bs_put_be32( bs
, mvhd
->matrix
[i
] );
1206 lsmash_bs_put_be32( bs
, mvhd
->previewTime
);
1207 lsmash_bs_put_be32( bs
, mvhd
->previewDuration
);
1208 lsmash_bs_put_be32( bs
, mvhd
->posterTime
);
1209 lsmash_bs_put_be32( bs
, mvhd
->selectionTime
);
1210 lsmash_bs_put_be32( bs
, mvhd
->selectionDuration
);
1211 lsmash_bs_put_be32( bs
, mvhd
->currentTime
);
1212 lsmash_bs_put_be32( bs
, mvhd
->next_track_ID
);
1216 static void isom_bs_put_sample_flags( lsmash_bs_t
*bs
, isom_sample_flags_t
*flags
)
1218 uint32_t temp
= (flags
->reserved
<< 28)
1219 | (flags
->is_leading
<< 26)
1220 | (flags
->sample_depends_on
<< 24)
1221 | (flags
->sample_is_depended_on
<< 22)
1222 | (flags
->sample_has_redundancy
<< 20)
1223 | (flags
->sample_padding_value
<< 17)
1224 | (flags
->sample_is_non_sync_sample
<< 16)
1225 | flags
->sample_degradation_priority
;
1226 lsmash_bs_put_be32( bs
, temp
);
1229 static int isom_write_mehd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1231 if( box
->manager
& LSMASH_PLACEHOLDER
)
1233 /* Movie Extends Header Box is not written immediately.
1234 * It's done after finishing all movie fragments.
1235 * The following will be overwritten by Movie Extends Header Box.
1236 * We use version 1 Movie Extends Header Box since it causes extra 4 bytes region
1237 * we cannot replace with empty Free Space Box as we place version 0 one. */
1238 box
->pos
= box
->file
->bs
->written
;
1239 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ 12 );
1240 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_FREE
.fourcc
);
1241 lsmash_bs_put_be32( bs
, 0 );
1242 lsmash_bs_put_be64( bs
, 0 );
1246 isom_mehd_t
*mehd
= (isom_mehd_t
*)box
;
1247 //mehd->version = mehd->fragment_duration > UINT32_MAX ? 1 : 0;
1248 isom_bs_put_box_common( bs
, mehd
);
1249 if( mehd
->version
== 1 )
1250 lsmash_bs_put_be64( bs
, mehd
->fragment_duration
);
1252 lsmash_bs_put_be32( bs
, LSMASH_MIN( mehd
->fragment_duration
, UINT32_MAX
) );
1257 static int isom_write_trex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1259 isom_trex_t
*trex
= (isom_trex_t
*)box
;
1260 isom_bs_put_box_common( bs
, trex
);
1261 lsmash_bs_put_be32( bs
, trex
->track_ID
);
1262 lsmash_bs_put_be32( bs
, trex
->default_sample_description_index
);
1263 lsmash_bs_put_be32( bs
, trex
->default_sample_duration
);
1264 lsmash_bs_put_be32( bs
, trex
->default_sample_size
);
1265 isom_bs_put_sample_flags( bs
, &trex
->default_sample_flags
);
1269 static int isom_write_mvex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1271 isom_bs_put_box_common( bs
, box
);
1275 static int isom_write_mfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1277 isom_mfhd_t
*mfhd
= (isom_mfhd_t
*)box
;
1278 isom_bs_put_box_common( bs
, mfhd
);
1279 lsmash_bs_put_be32( bs
, mfhd
->sequence_number
);
1283 static int isom_write_tfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1285 isom_tfhd_t
*tfhd
= (isom_tfhd_t
*)box
;
1286 isom_bs_put_box_common( bs
, tfhd
);
1287 lsmash_bs_put_be32( bs
, tfhd
->track_ID
);
1288 if( tfhd
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) lsmash_bs_put_be64( bs
, tfhd
->base_data_offset
);
1289 if( tfhd
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->sample_description_index
);
1290 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_duration
);
1291 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_size
);
1292 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &tfhd
->default_sample_flags
);
1296 static int isom_write_tfdt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1298 isom_tfdt_t
*tfdt
= (isom_tfdt_t
*)box
;
1299 /* Check the version. */
1300 tfdt
->version
= tfdt
->baseMediaDecodeTime
> UINT32_MAX
? 1 : 0;
1302 isom_bs_put_box_common( bs
, tfdt
);
1303 if( tfdt
->version
== 1 )
1304 lsmash_bs_put_be64( bs
, tfdt
->baseMediaDecodeTime
);
1306 lsmash_bs_put_be32( bs
, tfdt
->baseMediaDecodeTime
);
1310 static int isom_write_trun( lsmash_bs_t
*bs
, isom_box_t
*box
)
1312 isom_trun_t
*trun
= (isom_trun_t
*)box
;
1313 isom_bs_put_box_common( bs
, trun
);
1314 lsmash_bs_put_be32( bs
, trun
->sample_count
);
1315 if( trun
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, trun
->data_offset
);
1316 if( trun
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &trun
->first_sample_flags
);
1317 if( trun
->optional
)
1318 for( lsmash_entry_t
*entry
= trun
->optional
->head
; entry
; entry
= entry
->next
)
1320 isom_trun_optional_row_t
*data
= (isom_trun_optional_row_t
*)entry
->data
;
1322 return LSMASH_ERR_NAMELESS
;
1323 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_duration
);
1324 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_size
);
1325 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &data
->sample_flags
);
1326 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_composition_time_offset
);
1331 static int isom_write_traf( lsmash_bs_t
*bs
, isom_box_t
*box
)
1333 isom_bs_put_box_common( bs
, box
);
1337 static int isom_write_moof( lsmash_bs_t
*bs
, isom_box_t
*box
)
1339 isom_bs_put_box_common( bs
, box
);
1343 static int isom_write_tfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1345 isom_tfra_t
*tfra
= (isom_tfra_t
*)box
;
1346 isom_bs_put_box_common( bs
, tfra
);
1347 uint32_t temp
= (tfra
->reserved
<< 6)
1348 | (tfra
->length_size_of_traf_num
<< 4)
1349 | (tfra
->length_size_of_trun_num
<< 2)
1350 | tfra
->length_size_of_sample_num
;
1351 lsmash_bs_put_be32( bs
, tfra
->track_ID
);
1352 lsmash_bs_put_be32( bs
, temp
);
1353 lsmash_bs_put_be32( bs
, tfra
->number_of_entry
);
1356 void (*bs_put_funcs
[5])( lsmash_bs_t
*, uint64_t ) =
1358 lsmash_bs_put_byte_from_64
,
1359 lsmash_bs_put_be16_from_64
,
1360 lsmash_bs_put_be24_from_64
,
1361 lsmash_bs_put_be32_from_64
,
1364 void (*bs_put_time
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1365 void (*bs_put_moof_offset
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1366 void (*bs_put_traf_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_traf_num
];
1367 void (*bs_put_trun_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_trun_num
];
1368 void (*bs_put_sample_number
)( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_sample_num
];
1369 for( lsmash_entry_t
*entry
= tfra
->list
->head
; entry
; entry
= entry
->next
)
1371 isom_tfra_location_time_entry_t
*data
= (isom_tfra_location_time_entry_t
*)entry
->data
;
1373 return LSMASH_ERR_NAMELESS
;
1374 bs_put_time ( bs
, data
->time
);
1375 bs_put_moof_offset ( bs
, data
->moof_offset
);
1376 bs_put_traf_number ( bs
, data
->traf_number
);
1377 bs_put_trun_number ( bs
, data
->trun_number
);
1378 bs_put_sample_number( bs
, data
->sample_number
);
1384 static int isom_write_mfro( lsmash_bs_t
*bs
, isom_box_t
*box
)
1386 isom_mfro_t
*mfro
= (isom_mfro_t
*)box
;
1387 isom_bs_put_box_common( bs
, mfro
);
1388 lsmash_bs_put_be32( bs
, mfro
->length
); /* determined at isom_write_mfra(). */
1392 static int isom_write_mfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1394 isom_mfra_t
*mfra
= (isom_mfra_t
*)box
;
1396 mfra
->mfro
->length
= mfra
->size
;
1397 isom_bs_put_box_common( bs
, mfra
);
1401 static int isom_write_mdat( lsmash_bs_t
*bs
, isom_box_t
*box
)
1403 isom_mdat_t
*mdat
= (isom_mdat_t
*)box
;
1404 lsmash_file_t
*file
= mdat
->file
;
1405 /* If any fragment, write the Media Data Box all at once. */
1406 if( file
->fragment
)
1408 /* Write the size and type fields of the Media Data Box. */
1409 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ file
->fragment
->pool_size
;
1410 if( mdat
->size
> UINT32_MAX
)
1411 mdat
->size
+= 8; /* large_size */
1412 isom_bs_put_box_common( bs
, mdat
);
1413 /* Write the samples in the current movie fragment. */
1414 for( lsmash_entry_t
*entry
= file
->fragment
->pool
->head
; entry
; entry
= entry
->next
)
1416 isom_sample_pool_t
*pool
= (isom_sample_pool_t
*)entry
->data
;
1418 return LSMASH_ERR_NAMELESS
;
1419 lsmash_bs_put_bytes( bs
, pool
->size
, pool
->data
);
1421 mdat
->media_size
= file
->fragment
->pool_size
;
1424 if( mdat
->manager
& LSMASH_PLACEHOLDER
)
1426 /* Write an incomplete Media Data Box.
1427 * Braindead implementation might check box order and return an error if an expected box does not come the
1428 * next. Placement of eight 0x00 byte string as a simple large_size placeholder passes such silly box order
1429 * checks. This placement is more compatible than placement of a Free Space Box ('free' or 'skip') or a
1430 * Placeholder Atom ('wide') as a large_size placeholder since Media Data Box can store any data and any
1431 * implementation surely do not check what contents are stored in it until taking samples out according to
1432 * chunk offsets, and the placeholder is placed before any chunk offset thus it won't be touched. */
1433 mdat
->pos
= bs
->offset
;
1434 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1435 mdat
->manager
|= LSMASH_INCOMPLETE_BOX
;
1436 mdat
->manager
&= ~LSMASH_PLACEHOLDER
;
1437 isom_bs_put_box_common( bs
, mdat
);
1438 if( mdat
->size
<= UINT32_MAX
)
1439 lsmash_bs_put_be64( bs
, 0x0000000000000000 );
1440 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8;
1443 assert( !(mdat
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_PLACEHOLDER
)) );
1444 uint64_t actual_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->media_size
;
1445 uint64_t reserved_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1446 if( actual_size
< reserved_size
)
1448 /* Write padding zero bytes until end of this box.
1449 * This code path is invoked when the size of a Media Data Box was reserved. */
1450 mdat
->size
= reserved_size
;
1451 int err
= lsmash_bs_flush_buffer( bs
);
1454 uint64_t padding_size
= reserved_size
- actual_size
;
1455 static const uint8_t zero_bytes
[64] = { 0 };
1456 while( padding_size
> sizeof(zero_bytes
) )
1458 if( (err
= lsmash_bs_write_data( bs
, zero_bytes
, sizeof(zero_bytes
) )) < 0 )
1460 padding_size
-= sizeof(zero_bytes
);
1462 return lsmash_bs_write_data( bs
, zero_bytes
, padding_size
);
1464 if( !bs
->unseekable
)
1466 /* Write the actual size. */
1467 uint64_t current_pos
= bs
->offset
;
1468 mdat
->size
= actual_size
;
1469 lsmash_bs_write_seek( bs
, mdat
->pos
, SEEK_SET
);
1470 isom_bs_put_box_common( bs
, mdat
);
1471 /* isom_write_box() also calls lsmash_bs_flush_buffer() but it must do nothing. */
1472 int ret
= lsmash_bs_flush_buffer( bs
);
1473 lsmash_bs_write_seek( bs
, current_pos
, SEEK_SET
);
1476 return LSMASH_ERR_NAMELESS
;
1479 static int isom_write_ftyp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1481 isom_ftyp_t
*ftyp
= (isom_ftyp_t
*)box
;
1482 if( ftyp
->brand_count
== 0 )
1484 isom_bs_put_box_common( bs
, ftyp
);
1485 lsmash_bs_put_be32( bs
, ftyp
->major_brand
);
1486 lsmash_bs_put_be32( bs
, ftyp
->minor_version
);
1487 for( uint32_t i
= 0; i
< ftyp
->brand_count
; i
++ )
1488 lsmash_bs_put_be32( bs
, ftyp
->compatible_brands
[i
] );
1492 static int isom_write_moov( lsmash_bs_t
*bs
, isom_box_t
*box
)
1494 isom_bs_put_box_common( bs
, box
);
1498 static int isom_write_free( lsmash_bs_t
*bs
, isom_box_t
*box
)
1500 isom_free_t
*skip
= (isom_free_t
*)box
;
1501 isom_bs_put_box_common( bs
, skip
);
1502 if( skip
->data
&& skip
->length
)
1503 lsmash_bs_put_bytes( bs
, skip
->length
, skip
->data
);
1507 static int isom_write_sidx( lsmash_bs_t
*bs
, isom_box_t
*box
)
1509 isom_sidx_t
*sidx
= (isom_sidx_t
*)box
;
1510 /* Check the version. */
1511 if( sidx
->earliest_presentation_time
> UINT32_MAX
1512 || sidx
->first_offset
> UINT32_MAX
)
1517 isom_bs_put_box_common( bs
, sidx
);
1518 lsmash_bs_put_be32( bs
, sidx
->reference_ID
);
1519 lsmash_bs_put_be32( bs
, sidx
->timescale
);
1520 if( sidx
->version
== 0 )
1522 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->earliest_presentation_time
, UINT32_MAX
) );
1523 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->first_offset
, UINT32_MAX
) );
1527 lsmash_bs_put_be64( bs
, sidx
->earliest_presentation_time
);
1528 lsmash_bs_put_be64( bs
, sidx
->first_offset
);
1530 lsmash_bs_put_be16( bs
, sidx
->reserved
);
1531 lsmash_bs_put_be16( bs
, sidx
->reference_count
);
1532 for( lsmash_entry_t
*entry
= sidx
->list
->head
; entry
; entry
= entry
->next
)
1534 isom_sidx_referenced_item_t
*data
= (isom_sidx_referenced_item_t
*)entry
->data
;
1536 return LSMASH_ERR_NAMELESS
;
1538 temp32
= (data
->reference_type
<< 31)
1539 | data
->reference_size
;
1540 lsmash_bs_put_be32( bs
, temp32
);
1541 lsmash_bs_put_be32( bs
, data
->subsegment_duration
);
1542 temp32
= (data
->starts_with_SAP
<< 31)
1543 | (data
->SAP_type
<< 28)
1544 | data
->SAP_delta_time
;
1545 lsmash_bs_put_be32( bs
, temp32
);
1550 int isom_write_box( lsmash_bs_t
*bs
, isom_box_t
*box
)
1553 /* Don't write any incomplete or already written box to a file. */
1554 if( LSMASH_IS_NON_EXISTING_BOX( box
)
1556 || (bs
->stream
&& (box
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_WRITTEN_BOX
))) )
1558 int ret
= box
->write( bs
, box
);
1563 if( (ret
= lsmash_bs_flush_buffer( bs
)) < 0 )
1565 /* Don't write any child box if this box is a placeholder or an incomplete box. */
1566 if( box
->manager
& (LSMASH_PLACEHOLDER
| LSMASH_INCOMPLETE_BOX
) )
1569 box
->manager
|= LSMASH_WRITTEN_BOX
;
1571 return isom_write_children( bs
, box
);
1574 void isom_set_box_writer( isom_box_t
*box
)
1576 if( box
->manager
& LSMASH_BINARY_CODED_BOX
)
1578 box
->write
= isom_write_binary_coded_box
;
1581 else if( box
->manager
& LSMASH_UNKNOWN_BOX
)
1583 box
->write
= isom_write_unknown_box
;
1586 assert( LSMASH_IS_EXISTING_BOX( box
->parent
) );
1587 isom_box_t
*parent
= box
->parent
;
1588 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1590 /* OK, this box is a sample entry.
1591 * Here, determine the suitable sample entry writer by media type if possible. */
1592 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
1594 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
1595 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
1596 box
->write
= isom_write_visual_description
;
1597 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
1598 box
->write
= isom_write_audio_description
;
1599 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_HINT_TRACK
)
1600 box
->write
= isom_write_hint_description
;
1601 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
1603 if( lsmash_check_box_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1604 box
->write
= isom_write_qt_text_description
;
1605 else if( lsmash_check_box_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1606 box
->write
= isom_write_tx3g_description
;
1611 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1613 if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_FRMA
) ) box
->write
= isom_write_frma
;
1614 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ENDA
) ) box
->write
= isom_write_enda
;
1615 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_MP4A
) ) box
->write
= isom_write_mp4a
;
1616 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ESDS
) ) box
->write
= isom_write_esds
;
1617 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CHAN
) ) box
->write
= isom_write_chan
;
1618 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_TERMINATOR
) ) box
->write
= isom_write_terminator
;
1619 else box
->write
= NULL
;
1622 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
1624 box
->write
= isom_write_track_reference_type
;
1627 static struct box_writer_table_tag
1629 lsmash_box_type_t type
;
1630 isom_extension_writer_t writer_func
;
1631 } box_writer_table
[128] = { { LSMASH_BOX_TYPE_INITIALIZER
, NULL
} };
1632 if( !box_writer_table
[0].writer_func
)
1634 /* Initialize the table. */
1636 #define ADD_BOX_WRITER_TABLE_ELEMENT( type, reader_func ) \
1637 box_writer_table[i++] = (struct box_writer_table_tag){ type, reader_func }
1638 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, isom_write_ftyp
);
1639 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, isom_write_ftyp
);
1640 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, isom_write_sidx
);
1641 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, isom_write_moov
);
1642 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, isom_write_mvhd
);
1643 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, isom_write_iods
);
1644 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, isom_write_ctab
);
1645 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, isom_write_esds
);
1646 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, isom_write_trak
);
1647 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, isom_write_tkhd
);
1648 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, isom_write_tapt
);
1649 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, isom_write_clef
);
1650 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, isom_write_prof
);
1651 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, isom_write_enof
);
1652 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, isom_write_edts
);
1653 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, isom_write_elst
);
1654 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, isom_write_tref
);
1655 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, isom_write_mdia
);
1656 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, isom_write_mdhd
);
1657 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, isom_write_hdlr
);
1658 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, isom_write_minf
);
1659 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, isom_write_vmhd
);
1660 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, isom_write_smhd
);
1661 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, isom_write_hmhd
);
1662 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, isom_write_nmhd
);
1663 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, isom_write_gmhd
);
1664 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, isom_write_gmin
);
1665 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, isom_write_text
);
1666 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, isom_write_dinf
);
1667 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, isom_write_dref
);
1668 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL
, isom_write_url
);
1669 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, isom_write_stbl
);
1670 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, isom_write_stsd
);
1671 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, isom_write_btrt
);
1672 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TIMS
, isom_write_tims
);
1673 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSRO
, isom_write_tsro
);
1674 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSSY
, isom_write_tssy
);
1675 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, isom_write_colr
);
1676 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_COLR
, isom_write_colr
);
1677 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, isom_write_clap
);
1678 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, isom_write_pasp
);
1679 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, isom_write_glbl
);
1680 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, isom_write_gama
);
1681 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, isom_write_fiel
);
1682 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLLI
, isom_write_clli
);
1683 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MDCV
, isom_write_mdcv
);
1684 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, isom_write_cspc
);
1685 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, isom_write_sgbt
);
1686 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, isom_write_stsl
);
1687 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, isom_write_wave
);
1688 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MP4A
, isom_write_mp4a
);
1689 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, isom_write_chan
);
1690 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, isom_write_ftab
);
1691 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, isom_write_stts
);
1692 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, isom_write_ctts
);
1693 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, isom_write_cslg
);
1694 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, isom_write_stss
);
1695 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, isom_write_stps
);
1696 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, isom_write_sdtp
);
1697 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, isom_write_stsc
);
1698 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, isom_write_stsz
);
1699 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, isom_write_stz2
);
1700 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, isom_write_stco
);
1701 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, isom_write_stco
);
1702 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, isom_write_sgpd
);
1703 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, isom_write_sbgp
);
1704 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, isom_write_udta
);
1705 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HNTI
, isom_write_hnti
);
1706 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_RTP
, isom_write_rtp
);
1707 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDP
, isom_write_sdp
);
1708 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, isom_write_chpl
);
1709 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, isom_write_mvex
);
1710 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, isom_write_mehd
);
1711 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, isom_write_trex
);
1712 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, isom_write_moof
);
1713 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, isom_write_mfhd
);
1714 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, isom_write_traf
);
1715 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, isom_write_tfhd
);
1716 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, isom_write_tfdt
);
1717 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, isom_write_trun
);
1718 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, isom_write_mdat
);
1719 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, isom_write_free
);
1720 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, isom_write_free
);
1721 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_META
, isom_write_meta
);
1722 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_META
, isom_write_meta
);
1723 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST
, isom_write_ilst
);
1724 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ILST
, isom_write_ilst
);
1725 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, isom_write_mfra
);
1726 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, isom_write_tfra
);
1727 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, isom_write_mfro
);
1728 ADD_BOX_WRITER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
);
1729 #undef ADD_BOX_WRITER_TABLE_ELEMENT
1731 for( int i
= 0; box_writer_table
[i
].writer_func
; i
++ )
1732 if( lsmash_check_box_type_identical( box
->type
, box_writer_table
[i
].type
) )
1734 box
->write
= box_writer_table
[i
].writer_func
;
1737 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
1738 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
1740 box
->write
= isom_write_metaitem
;
1743 if( lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_ILST
) )
1745 if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_MEAN
) )
1746 box
->write
= isom_write_mean
;
1747 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_NAME
) )
1748 box
->write
= isom_write_name
;
1749 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_DATA
) )
1750 box
->write
= isom_write_data
;
1754 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_CPRT
) )
1756 /* Avoid confusing udta.cprt with ilst.cprt. */
1757 box
->write
= isom_write_cprt
;
1760 box
->write
= isom_write_unknown_box
;