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_cspc( lsmash_bs_t
*bs
, isom_box_t
*box
)
430 isom_cspc_t
*cspc
= (isom_cspc_t
*)box
;
431 isom_bs_put_box_common( bs
, cspc
);
432 lsmash_bs_put_be32( bs
, cspc
->pixel_format
);
436 static int isom_write_sgbt( lsmash_bs_t
*bs
, isom_box_t
*box
)
438 isom_sgbt_t
*sgbt
= (isom_sgbt_t
*)box
;
439 isom_bs_put_box_common( bs
, sgbt
);
440 lsmash_bs_put_byte( bs
, sgbt
->significantBits
);
444 static int isom_write_stsl( lsmash_bs_t
*bs
, isom_box_t
*box
)
446 isom_stsl_t
*stsl
= (isom_stsl_t
*)box
;
447 isom_bs_put_box_common( bs
, stsl
);
448 lsmash_bs_put_byte( bs
, stsl
->constraint_flag
);
449 lsmash_bs_put_byte( bs
, stsl
->scale_method
);
450 lsmash_bs_put_be16( bs
, stsl
->display_center_x
);
451 lsmash_bs_put_be16( bs
, stsl
->display_center_y
);
455 static int isom_write_esds( lsmash_bs_t
*bs
, isom_box_t
*box
)
457 isom_esds_t
*esds
= (isom_esds_t
*)box
;
458 isom_bs_put_box_common( bs
, esds
);
459 mp4sys_update_descriptor_size( esds
->ES
);
460 return mp4sys_write_descriptor( bs
, esds
->ES
);
463 static int isom_write_btrt( lsmash_bs_t
*bs
, isom_box_t
*box
)
465 isom_btrt_t
*btrt
= (isom_btrt_t
*)box
;
466 isom_bs_put_box_common( bs
, btrt
);
467 lsmash_bs_put_be32( bs
, btrt
->bufferSizeDB
);
468 lsmash_bs_put_be32( bs
, btrt
->maxBitrate
);
469 lsmash_bs_put_be32( bs
, btrt
->avgBitrate
);
473 static int isom_write_glbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
475 isom_glbl_t
*glbl
= (isom_glbl_t
*)box
;
476 isom_bs_put_box_common( bs
, glbl
);
477 if( glbl
->header_data
&& glbl
->header_size
)
478 lsmash_bs_put_bytes( bs
, glbl
->header_size
, glbl
->header_data
);
482 static int isom_write_frma( lsmash_bs_t
*bs
, isom_box_t
*box
)
484 isom_frma_t
*frma
= (isom_frma_t
*)box
;
485 isom_bs_put_box_common( bs
, frma
);
486 lsmash_bs_put_be32( bs
, frma
->data_format
);
490 static int isom_write_enda( lsmash_bs_t
*bs
, isom_box_t
*box
)
492 isom_enda_t
*enda
= (isom_enda_t
*)box
;
493 isom_bs_put_box_common( bs
, enda
);
494 lsmash_bs_put_be16( bs
, enda
->littleEndian
);
498 static int isom_write_mp4a( lsmash_bs_t
*bs
, isom_box_t
*box
)
500 isom_mp4a_t
*mp4a
= (isom_mp4a_t
*)box
;
501 isom_bs_put_box_common( bs
, mp4a
);
502 lsmash_bs_put_be32( bs
, mp4a
->unknown
);
506 static int isom_write_chan( lsmash_bs_t
*bs
, isom_box_t
*box
)
508 isom_chan_t
*chan
= (isom_chan_t
*)box
;
509 isom_bs_put_box_common( bs
, chan
);
510 lsmash_bs_put_be32( bs
, chan
->channelLayoutTag
);
511 lsmash_bs_put_be32( bs
, chan
->channelBitmap
);
512 lsmash_bs_put_be32( bs
, chan
->numberChannelDescriptions
);
513 if( chan
->channelDescriptions
)
514 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
516 isom_channel_description_t
*channelDescriptions
= (isom_channel_description_t
*)(&chan
->channelDescriptions
[i
]);
517 lsmash_bs_put_be32( bs
, channelDescriptions
->channelLabel
);
518 lsmash_bs_put_be32( bs
, channelDescriptions
->channelFlags
);
519 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[0] );
520 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[1] );
521 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[2] );
526 static int isom_write_terminator( lsmash_bs_t
*bs
, isom_box_t
*box
)
528 isom_bs_put_box_common( bs
, box
);
532 static int isom_write_wave( lsmash_bs_t
*bs
, isom_box_t
*box
)
534 isom_bs_put_box_common( bs
, box
);
538 static int isom_write_visual_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
540 isom_visual_entry_t
*data
= (isom_visual_entry_t
*)box
;
541 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
542 return LSMASH_ERR_NAMELESS
;
543 isom_bs_put_box_common( bs
, data
);
544 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
545 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
546 lsmash_bs_put_be16( bs
, data
->version
);
547 lsmash_bs_put_be16( bs
, data
->revision_level
);
548 lsmash_bs_put_be32( bs
, data
->vendor
);
549 lsmash_bs_put_be32( bs
, data
->temporalQuality
);
550 lsmash_bs_put_be32( bs
, data
->spatialQuality
);
551 lsmash_bs_put_be16( bs
, data
->width
);
552 lsmash_bs_put_be16( bs
, data
->height
);
553 lsmash_bs_put_be32( bs
, data
->horizresolution
);
554 lsmash_bs_put_be32( bs
, data
->vertresolution
);
555 lsmash_bs_put_be32( bs
, data
->dataSize
);
556 lsmash_bs_put_be16( bs
, data
->frame_count
);
557 lsmash_bs_put_bytes( bs
, 32, data
->compressorname
);
558 lsmash_bs_put_be16( bs
, data
->depth
);
559 lsmash_bs_put_be16( bs
, data
->color_table_ID
);
560 if( data
->color_table_ID
== 0 )
561 isom_bs_put_qt_color_table( bs
, &data
->color_table
);
565 static int isom_write_audio_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
567 isom_audio_entry_t
*data
= (isom_audio_entry_t
*)box
;
568 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
569 return LSMASH_ERR_NAMELESS
;
570 isom_bs_put_box_common( bs
, data
);
571 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
572 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
573 lsmash_bs_put_be16( bs
, data
->version
);
574 lsmash_bs_put_be16( bs
, data
->revision_level
);
575 lsmash_bs_put_be32( bs
, data
->vendor
);
576 lsmash_bs_put_be16( bs
, data
->channelcount
);
577 lsmash_bs_put_be16( bs
, data
->samplesize
);
578 lsmash_bs_put_be16( bs
, data
->compression_ID
);
579 lsmash_bs_put_be16( bs
, data
->packet_size
);
580 lsmash_bs_put_be32( bs
, data
->samplerate
);
581 if( data
->version
== 1 )
583 lsmash_bs_put_be32( bs
, data
->samplesPerPacket
);
584 lsmash_bs_put_be32( bs
, data
->bytesPerPacket
);
585 lsmash_bs_put_be32( bs
, data
->bytesPerFrame
);
586 lsmash_bs_put_be32( bs
, data
->bytesPerSample
);
588 else if( data
->version
== 2 )
590 lsmash_bs_put_be32( bs
, data
->sizeOfStructOnly
);
591 lsmash_bs_put_be64( bs
, data
->audioSampleRate
);
592 lsmash_bs_put_be32( bs
, data
->numAudioChannels
);
593 lsmash_bs_put_be32( bs
, data
->always7F000000
);
594 lsmash_bs_put_be32( bs
, data
->constBitsPerChannel
);
595 lsmash_bs_put_be32( bs
, data
->formatSpecificFlags
);
596 lsmash_bs_put_be32( bs
, data
->constBytesPerAudioPacket
);
597 lsmash_bs_put_be32( bs
, data
->constLPCMFramesPerAudioPacket
);
603 static int isom_write_hint_description( lsmash_bs_t
*bs
, lsmash_entry_t
*entry
)
605 isom_hint_entry_t
*data
= (isom_hint_entry_t
*)entry
->data
;
606 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
607 return LSMASH_ERR_NAMELESS
;
608 isom_bs_put_box_common( bs
, data
);
609 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
610 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
611 if( data
->data
&& data
->data_length
)
612 lsmash_bs_put_bytes( bs
, data
->data_length
, data
->data
);
616 static int isom_write_metadata_description( lsmash_bs_t
*bs
, lsmash_entry_t
*entry
)
618 isom_metadata_entry_t
*data
= (isom_metadata_entry_t
*)entry
->data
;
619 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
620 return LSMASH_ERR_NAMELESS
;
621 isom_bs_put_box_common( bs
, data
);
622 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
623 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
628 static int isom_write_qt_text_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
630 isom_qt_text_entry_t
*data
= (isom_qt_text_entry_t
*)box
;
631 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
632 return LSMASH_ERR_NAMELESS
;
633 isom_bs_put_box_common( bs
, data
);
634 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
635 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
636 lsmash_bs_put_be32( bs
, data
->displayFlags
);
637 lsmash_bs_put_be32( bs
, data
->textJustification
);
638 for( uint32_t i
= 0; i
< 3; i
++ )
639 lsmash_bs_put_be16( bs
, data
->bgColor
[i
] );
640 lsmash_bs_put_be16( bs
, data
->top
);
641 lsmash_bs_put_be16( bs
, data
->left
);
642 lsmash_bs_put_be16( bs
, data
->bottom
);
643 lsmash_bs_put_be16( bs
, data
->right
);
644 lsmash_bs_put_be32( bs
, data
->scrpStartChar
);
645 lsmash_bs_put_be16( bs
, data
->scrpHeight
);
646 lsmash_bs_put_be16( bs
, data
->scrpAscent
);
647 lsmash_bs_put_be16( bs
, data
->scrpFont
);
648 lsmash_bs_put_be16( bs
, data
->scrpFace
);
649 lsmash_bs_put_be16( bs
, data
->scrpSize
);
650 for( uint32_t i
= 0; i
< 3; i
++ )
651 lsmash_bs_put_be16( bs
, data
->scrpColor
[i
] );
652 lsmash_bs_put_byte( bs
, data
->font_name_length
);
653 if( data
->font_name
&& data
->font_name_length
)
654 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
658 static int isom_write_ftab( lsmash_bs_t
*bs
, isom_box_t
*box
)
660 isom_ftab_t
*ftab
= (isom_ftab_t
*)box
;
661 assert( ftab
->list
);
662 isom_bs_put_box_common( bs
, ftab
);
663 lsmash_bs_put_be16( bs
, ftab
->list
->entry_count
);
664 for( lsmash_entry_t
*entry
= ftab
->list
->head
; entry
; entry
= entry
->next
)
666 isom_font_record_t
*data
= (isom_font_record_t
*)entry
->data
;
668 return LSMASH_ERR_NAMELESS
;
669 lsmash_bs_put_be16( bs
, data
->font_ID
);
670 lsmash_bs_put_byte( bs
, data
->font_name_length
);
671 if( data
->font_name
&& data
->font_name_length
)
672 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
677 static int isom_write_tx3g_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
679 isom_tx3g_entry_t
*data
= (isom_tx3g_entry_t
*)box
;
680 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
681 return LSMASH_ERR_NAMELESS
;
682 isom_bs_put_box_common( bs
, data
);
683 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
684 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
685 lsmash_bs_put_be32( bs
, data
->displayFlags
);
686 lsmash_bs_put_byte( bs
, data
->horizontal_justification
);
687 lsmash_bs_put_byte( bs
, data
->vertical_justification
);
688 for( uint32_t i
= 0; i
< 4; i
++ )
689 lsmash_bs_put_byte( bs
, data
->background_color_rgba
[i
] );
690 lsmash_bs_put_be16( bs
, data
->top
);
691 lsmash_bs_put_be16( bs
, data
->left
);
692 lsmash_bs_put_be16( bs
, data
->bottom
);
693 lsmash_bs_put_be16( bs
, data
->right
);
694 lsmash_bs_put_be16( bs
, data
->startChar
);
695 lsmash_bs_put_be16( bs
, data
->endChar
);
696 lsmash_bs_put_be16( bs
, data
->font_ID
);
697 lsmash_bs_put_byte( bs
, data
->face_style_flags
);
698 lsmash_bs_put_byte( bs
, data
->font_size
);
699 for( uint32_t i
= 0; i
< 4; i
++ )
700 lsmash_bs_put_byte( bs
, data
->text_color_rgba
[i
] );
704 static int isom_write_stsd( lsmash_bs_t
*bs
, isom_box_t
*box
)
706 isom_stsd_t
*stsd
= (isom_stsd_t
*)box
;
707 isom_bs_put_box_common( bs
, stsd
);
708 lsmash_bs_put_be32( bs
, stsd
->list
.entry_count
);
712 static int isom_write_stts( lsmash_bs_t
*bs
, isom_box_t
*box
)
714 isom_stts_t
*stts
= (isom_stts_t
*)box
;
715 assert( stts
->list
);
716 isom_bs_put_box_common( bs
, stts
);
717 lsmash_bs_put_be32( bs
, stts
->list
->entry_count
);
718 for( lsmash_entry_t
*entry
= stts
->list
->head
; entry
; entry
= entry
->next
)
720 isom_stts_entry_t
*data
= (isom_stts_entry_t
*)entry
->data
;
722 return LSMASH_ERR_NAMELESS
;
723 lsmash_bs_put_be32( bs
, data
->sample_count
);
724 lsmash_bs_put_be32( bs
, data
->sample_delta
);
729 static int isom_write_ctts( lsmash_bs_t
*bs
, isom_box_t
*box
)
731 isom_ctts_t
*ctts
= (isom_ctts_t
*)box
;
732 assert( ctts
->list
);
733 isom_bs_put_box_common( bs
, ctts
);
734 lsmash_bs_put_be32( bs
, ctts
->list
->entry_count
);
735 for( lsmash_entry_t
*entry
= ctts
->list
->head
; entry
; entry
= entry
->next
)
737 isom_ctts_entry_t
*data
= (isom_ctts_entry_t
*)entry
->data
;
739 return LSMASH_ERR_NAMELESS
;
740 lsmash_bs_put_be32( bs
, data
->sample_count
);
741 lsmash_bs_put_be32( bs
, data
->sample_offset
);
746 static int isom_write_cslg( lsmash_bs_t
*bs
, isom_box_t
*box
)
748 isom_cslg_t
*cslg
= (isom_cslg_t
*)box
;
749 isom_bs_put_box_common( bs
, cslg
);
750 lsmash_bs_put_be32( bs
, cslg
->compositionToDTSShift
);
751 lsmash_bs_put_be32( bs
, cslg
->leastDecodeToDisplayDelta
);
752 lsmash_bs_put_be32( bs
, cslg
->greatestDecodeToDisplayDelta
);
753 lsmash_bs_put_be32( bs
, cslg
->compositionStartTime
);
754 lsmash_bs_put_be32( bs
, cslg
->compositionEndTime
);
758 static int isom_write_stsz( lsmash_bs_t
*bs
, isom_box_t
*box
)
760 isom_stsz_t
*stsz
= (isom_stsz_t
*)box
;
761 isom_bs_put_box_common( bs
, stsz
);
762 lsmash_bs_put_be32( bs
, stsz
->sample_size
);
763 lsmash_bs_put_be32( bs
, stsz
->sample_count
);
764 if( stsz
->sample_size
== 0 && stsz
->list
)
765 for( lsmash_entry_t
*entry
= stsz
->list
->head
; entry
; entry
= entry
->next
)
767 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
769 return LSMASH_ERR_NAMELESS
;
770 lsmash_bs_put_be32( bs
, data
->entry_size
);
775 static int isom_write_stz2( lsmash_bs_t
*bs
, isom_box_t
*box
)
777 isom_stz2_t
*stz2
= (isom_stz2_t
*)box
;
778 isom_bs_put_box_common( bs
, stz2
);
779 lsmash_bs_put_be32( bs
, (stz2
->reserved
<< 8) | stz2
->field_size
);
780 lsmash_bs_put_be32( bs
, stz2
->sample_count
);
781 if( stz2
->field_size
== 16 )
782 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
784 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
786 return LSMASH_ERR_NAMELESS
;
787 assert( data
->entry_size
<= 0xffff );
788 lsmash_bs_put_be16( bs
, data
->entry_size
);
790 else if( stz2
->field_size
== 8 )
791 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
793 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
795 return LSMASH_ERR_NAMELESS
;
796 assert( data
->entry_size
<= 0xff );
797 lsmash_bs_put_byte( bs
, data
->entry_size
);
799 else if( stz2
->field_size
== 4 )
801 isom_stsz_entry_t zero_padding
= { .entry_size
= 0 };
802 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
? entry
->next
->next
: entry
->next
)
804 isom_stsz_entry_t
*data_o
= (isom_stsz_entry_t
*)entry
->data
;
805 isom_stsz_entry_t
*data_e
= (isom_stsz_entry_t
*)(entry
->next
? entry
->next
->data
: &zero_padding
);
806 if( !data_o
|| !data_e
)
807 return LSMASH_ERR_NAMELESS
;
808 assert( data_o
->entry_size
<= 0xf && data_e
->entry_size
<= 0xf );
809 lsmash_bs_put_byte( bs
, (data_o
->entry_size
<< 4) | data_e
->entry_size
);
813 return LSMASH_ERR_NAMELESS
;
817 static int isom_write_stss( lsmash_bs_t
*bs
, isom_box_t
*box
)
819 isom_stss_t
*stss
= (isom_stss_t
*)box
;
820 assert( stss
->list
);
821 isom_bs_put_box_common( bs
, stss
);
822 lsmash_bs_put_be32( bs
, stss
->list
->entry_count
);
823 for( lsmash_entry_t
*entry
= stss
->list
->head
; entry
; entry
= entry
->next
)
825 isom_stss_entry_t
*data
= (isom_stss_entry_t
*)entry
->data
;
827 return LSMASH_ERR_NAMELESS
;
828 lsmash_bs_put_be32( bs
, data
->sample_number
);
833 static int isom_write_stps( lsmash_bs_t
*bs
, isom_box_t
*box
)
835 isom_stps_t
*stps
= (isom_stps_t
*)box
;
836 assert( stps
->list
);
837 isom_bs_put_box_common( bs
, stps
);
838 lsmash_bs_put_be32( bs
, stps
->list
->entry_count
);
839 for( lsmash_entry_t
*entry
= stps
->list
->head
; entry
; entry
= entry
->next
)
841 isom_stps_entry_t
*data
= (isom_stps_entry_t
*)entry
->data
;
843 return LSMASH_ERR_NAMELESS
;
844 lsmash_bs_put_be32( bs
, data
->sample_number
);
849 static int isom_write_sdtp( lsmash_bs_t
*bs
, isom_box_t
*box
)
851 isom_sdtp_t
*sdtp
= (isom_sdtp_t
*)box
;
852 assert( sdtp
->list
);
853 isom_bs_put_box_common( bs
, sdtp
);
854 for( lsmash_entry_t
*entry
= sdtp
->list
->head
; entry
; entry
= entry
->next
)
856 isom_sdtp_entry_t
*data
= (isom_sdtp_entry_t
*)entry
->data
;
858 return LSMASH_ERR_NAMELESS
;
859 uint8_t temp
= (data
->is_leading
<< 6)
860 | (data
->sample_depends_on
<< 4)
861 | (data
->sample_is_depended_on
<< 2)
862 | data
->sample_has_redundancy
;
863 lsmash_bs_put_byte( bs
, temp
);
868 static int isom_write_stsc( lsmash_bs_t
*bs
, isom_box_t
*box
)
870 isom_stsc_t
*stsc
= (isom_stsc_t
*)box
;
871 assert( stsc
->list
);
872 isom_bs_put_box_common( bs
, stsc
);
873 lsmash_bs_put_be32( bs
, stsc
->list
->entry_count
);
874 for( lsmash_entry_t
*entry
= stsc
->list
->head
; entry
; entry
= entry
->next
)
876 isom_stsc_entry_t
*data
= (isom_stsc_entry_t
*)entry
->data
;
878 return LSMASH_ERR_NAMELESS
;
879 lsmash_bs_put_be32( bs
, data
->first_chunk
);
880 lsmash_bs_put_be32( bs
, data
->samples_per_chunk
);
881 lsmash_bs_put_be32( bs
, data
->sample_description_index
);
886 static int isom_write_co64( lsmash_bs_t
*bs
, isom_box_t
*box
)
888 isom_stco_t
*co64
= (isom_stco_t
*)box
;
889 assert( co64
->list
);
890 isom_bs_put_box_common( bs
, co64
);
891 lsmash_bs_put_be32( bs
, co64
->list
->entry_count
);
892 for( lsmash_entry_t
*entry
= co64
->list
->head
; entry
; entry
= entry
->next
)
894 isom_co64_entry_t
*data
= (isom_co64_entry_t
*)entry
->data
;
896 return LSMASH_ERR_NAMELESS
;
897 lsmash_bs_put_be64( bs
, data
->chunk_offset
);
902 static int isom_write_stco( lsmash_bs_t
*bs
, isom_box_t
*box
)
904 isom_stco_t
*stco
= (isom_stco_t
*)box
;
905 if( stco
->large_presentation
)
906 return isom_write_co64( bs
, box
);
907 assert( stco
->list
);
908 isom_bs_put_box_common( bs
, stco
);
909 lsmash_bs_put_be32( bs
, stco
->list
->entry_count
);
910 for( lsmash_entry_t
*entry
= stco
->list
->head
; entry
; entry
= entry
->next
)
912 isom_stco_entry_t
*data
= (isom_stco_entry_t
*)entry
->data
;
914 return LSMASH_ERR_NAMELESS
;
915 lsmash_bs_put_be32( bs
, data
->chunk_offset
);
920 static int isom_write_sgpd( lsmash_bs_t
*bs
, isom_box_t
*box
)
922 isom_sgpd_t
*sgpd
= (isom_sgpd_t
*)box
;
923 assert( sgpd
->list
);
924 isom_bs_put_box_common( bs
, sgpd
);
925 lsmash_bs_put_be32( bs
, sgpd
->grouping_type
);
926 if( sgpd
->version
== 1 )
927 lsmash_bs_put_be32( bs
, sgpd
->default_length
);
928 lsmash_bs_put_be32( bs
, sgpd
->list
->entry_count
);
929 for( lsmash_entry_t
*entry
= sgpd
->list
->head
; entry
; entry
= entry
->next
)
932 return LSMASH_ERR_NAMELESS
;
933 switch( sgpd
->grouping_type
)
935 case ISOM_GROUP_TYPE_RAP
:
937 isom_rap_entry_t
*rap
= (isom_rap_entry_t
*)entry
->data
;
938 uint8_t temp
= (rap
->num_leading_samples_known
<< 7)
939 | rap
->num_leading_samples
;
940 lsmash_bs_put_byte( bs
, temp
);
943 case ISOM_GROUP_TYPE_ROLL
:
944 case ISOM_GROUP_TYPE_PROL
:
945 lsmash_bs_put_be16( bs
, ((isom_roll_entry_t
*)entry
->data
)->roll_distance
);
948 /* We don't consider other grouping types currently. */
949 // if( sgpd->version == 1 && !sgpd->default_length )
950 // lsmash_bs_put_be32( bs, ((isom_sgpd_t *)entry->data)->description_length );
957 static int isom_write_sbgp( lsmash_bs_t
*bs
, isom_box_t
*box
)
959 isom_sbgp_t
*sbgp
= (isom_sbgp_t
*)box
;
960 assert( sbgp
->list
);
961 isom_bs_put_box_common( bs
, sbgp
);
962 lsmash_bs_put_be32( bs
, sbgp
->grouping_type
);
963 if( sbgp
->version
== 1 )
964 lsmash_bs_put_be32( bs
, sbgp
->grouping_type_parameter
);
965 lsmash_bs_put_be32( bs
, sbgp
->list
->entry_count
);
966 for( lsmash_entry_t
*entry
= sbgp
->list
->head
; entry
; entry
= entry
->next
)
968 isom_group_assignment_entry_t
*data
= (isom_group_assignment_entry_t
*)entry
->data
;
970 return LSMASH_ERR_NAMELESS
;
971 lsmash_bs_put_be32( bs
, data
->sample_count
);
972 lsmash_bs_put_be32( bs
, data
->group_description_index
);
977 static int isom_write_stbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
979 isom_bs_put_box_common( bs
, box
);
983 static int isom_write_minf( lsmash_bs_t
*bs
, isom_box_t
*box
)
985 isom_bs_put_box_common( bs
, box
);
989 static int isom_write_mdia( lsmash_bs_t
*bs
, isom_box_t
*box
)
991 isom_bs_put_box_common( bs
, box
);
995 static int isom_write_chpl( lsmash_bs_t
*bs
, isom_box_t
*box
)
997 isom_chpl_t
*chpl
= (isom_chpl_t
*)box
;
998 assert( chpl
->list
);
999 isom_bs_put_box_common( bs
, chpl
);
1000 if( chpl
->version
== 1 )
1002 lsmash_bs_put_byte( bs
, chpl
->unknown
);
1003 lsmash_bs_put_be32( bs
, chpl
->list
->entry_count
);
1005 else /* chpl->version == 0 */
1006 lsmash_bs_put_byte( bs
, (uint8_t)chpl
->list
->entry_count
);
1007 for( lsmash_entry_t
*entry
= chpl
->list
->head
; entry
; entry
= entry
->next
)
1009 isom_chpl_entry_t
*data
= (isom_chpl_entry_t
*)entry
->data
;
1011 return LSMASH_ERR_NAMELESS
;
1012 lsmash_bs_put_be64( bs
, data
->start_time
);
1013 lsmash_bs_put_byte( bs
, data
->chapter_name_length
);
1014 lsmash_bs_put_bytes( bs
, data
->chapter_name_length
, data
->chapter_name
);
1019 static int isom_write_mean( lsmash_bs_t
*bs
, isom_box_t
*box
)
1021 isom_mean_t
*mean
= (isom_mean_t
*)box
;
1022 isom_bs_put_box_common( bs
, mean
);
1023 if( mean
->meaning_string
&& mean
->meaning_string_length
)
1024 lsmash_bs_put_bytes( bs
, mean
->meaning_string_length
, mean
->meaning_string
);
1028 static int isom_write_name( lsmash_bs_t
*bs
, isom_box_t
*box
)
1030 isom_name_t
*name
= (isom_name_t
*)box
;
1031 isom_bs_put_box_common( bs
, name
);
1032 if( name
->name
&& name
->name_length
)
1033 lsmash_bs_put_bytes( bs
, name
->name_length
, name
->name
);
1037 static int isom_write_data( lsmash_bs_t
*bs
, isom_box_t
*box
)
1039 isom_data_t
*data
= (isom_data_t
*)box
;
1040 isom_bs_put_box_common( bs
, data
);
1041 lsmash_bs_put_be16( bs
, data
->reserved
);
1042 lsmash_bs_put_byte( bs
, data
->type_set_identifier
);
1043 lsmash_bs_put_byte( bs
, data
->type_code
);
1044 lsmash_bs_put_be32( bs
, data
->the_locale
);
1045 if( data
->value
&& data
->value_length
)
1046 lsmash_bs_put_bytes( bs
, data
->value_length
, data
->value
);
1050 static int isom_write_metaitem( lsmash_bs_t
*bs
, isom_box_t
*box
)
1052 isom_bs_put_box_common( bs
, box
);
1056 static int isom_write_ilst( lsmash_bs_t
*bs
, isom_box_t
*box
)
1058 isom_bs_put_box_common( bs
, box
);
1062 static int isom_write_meta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1064 isom_bs_put_box_common( bs
, box
);
1068 static int isom_write_cprt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1070 isom_cprt_t
*cprt
= (isom_cprt_t
*)box
;
1071 isom_bs_put_box_common( bs
, cprt
);
1072 lsmash_bs_put_be16( bs
, cprt
->language
);
1073 lsmash_bs_put_bytes( bs
, cprt
->notice_length
, cprt
->notice
);
1077 static int isom_write_udta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1079 isom_bs_put_box_common( bs
, box
);
1083 static int isom_write_trak( lsmash_bs_t
*bs
, isom_box_t
*box
)
1085 isom_bs_put_box_common( bs
, box
);
1089 static int isom_write_iods( lsmash_bs_t
*bs
, isom_box_t
*box
)
1091 isom_iods_t
*iods
= (isom_iods_t
*)box
;
1092 isom_bs_put_box_common( bs
, iods
);
1093 mp4sys_update_descriptor_size( iods
->OD
);
1094 return mp4sys_write_descriptor( bs
, iods
->OD
);
1097 static int isom_write_mvhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1099 isom_mvhd_t
*mvhd
= (isom_mvhd_t
*)box
;
1100 /* Check the version. */
1101 if( (LSMASH_IS_EXISTING_BOX( mvhd
->file
) && !mvhd
->file
->undefined_64_ver
)
1102 && (mvhd
->creation_time
> UINT32_MAX
1103 || mvhd
->modification_time
> UINT32_MAX
1104 || mvhd
->duration
> UINT32_MAX
) )
1109 isom_bs_put_box_common( bs
, mvhd
);
1112 lsmash_bs_put_be64( bs
, mvhd
->creation_time
);
1113 lsmash_bs_put_be64( bs
, mvhd
->modification_time
);
1114 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1115 lsmash_bs_put_be64( bs
, mvhd
->duration
);
1119 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->creation_time
, UINT32_MAX
) );
1120 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->modification_time
, UINT32_MAX
) );
1121 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1122 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->duration
, UINT32_MAX
) );
1124 lsmash_bs_put_be32( bs
, mvhd
->rate
);
1125 lsmash_bs_put_be16( bs
, mvhd
->volume
);
1126 lsmash_bs_put_be16( bs
, mvhd
->reserved
);
1127 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[0] );
1128 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[1] );
1129 for( int i
= 0; i
< 9; i
++ )
1130 lsmash_bs_put_be32( bs
, mvhd
->matrix
[i
] );
1131 lsmash_bs_put_be32( bs
, mvhd
->previewTime
);
1132 lsmash_bs_put_be32( bs
, mvhd
->previewDuration
);
1133 lsmash_bs_put_be32( bs
, mvhd
->posterTime
);
1134 lsmash_bs_put_be32( bs
, mvhd
->selectionTime
);
1135 lsmash_bs_put_be32( bs
, mvhd
->selectionDuration
);
1136 lsmash_bs_put_be32( bs
, mvhd
->currentTime
);
1137 lsmash_bs_put_be32( bs
, mvhd
->next_track_ID
);
1141 static void isom_bs_put_sample_flags( lsmash_bs_t
*bs
, isom_sample_flags_t
*flags
)
1143 uint32_t temp
= (flags
->reserved
<< 28)
1144 | (flags
->is_leading
<< 26)
1145 | (flags
->sample_depends_on
<< 24)
1146 | (flags
->sample_is_depended_on
<< 22)
1147 | (flags
->sample_has_redundancy
<< 20)
1148 | (flags
->sample_padding_value
<< 17)
1149 | (flags
->sample_is_non_sync_sample
<< 16)
1150 | flags
->sample_degradation_priority
;
1151 lsmash_bs_put_be32( bs
, temp
);
1154 static int isom_write_mehd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1156 if( box
->manager
& LSMASH_PLACEHOLDER
)
1158 /* Movie Extends Header Box is not written immediately.
1159 * It's done after finishing all movie fragments.
1160 * The following will be overwritten by Movie Extends Header Box.
1161 * We use version 1 Movie Extends Header Box since it causes extra 4 bytes region
1162 * we cannot replace with empty Free Space Box as we place version 0 one. */
1163 box
->pos
= box
->file
->bs
->written
;
1164 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ 12 );
1165 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_FREE
.fourcc
);
1166 lsmash_bs_put_be32( bs
, 0 );
1167 lsmash_bs_put_be64( bs
, 0 );
1171 isom_mehd_t
*mehd
= (isom_mehd_t
*)box
;
1172 //mehd->version = mehd->fragment_duration > UINT32_MAX ? 1 : 0;
1173 isom_bs_put_box_common( bs
, mehd
);
1174 if( mehd
->version
== 1 )
1175 lsmash_bs_put_be64( bs
, mehd
->fragment_duration
);
1177 lsmash_bs_put_be32( bs
, LSMASH_MIN( mehd
->fragment_duration
, UINT32_MAX
) );
1182 static int isom_write_trex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1184 isom_trex_t
*trex
= (isom_trex_t
*)box
;
1185 isom_bs_put_box_common( bs
, trex
);
1186 lsmash_bs_put_be32( bs
, trex
->track_ID
);
1187 lsmash_bs_put_be32( bs
, trex
->default_sample_description_index
);
1188 lsmash_bs_put_be32( bs
, trex
->default_sample_duration
);
1189 lsmash_bs_put_be32( bs
, trex
->default_sample_size
);
1190 isom_bs_put_sample_flags( bs
, &trex
->default_sample_flags
);
1194 static int isom_write_mvex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1196 isom_bs_put_box_common( bs
, box
);
1200 static int isom_write_mfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1202 isom_mfhd_t
*mfhd
= (isom_mfhd_t
*)box
;
1203 isom_bs_put_box_common( bs
, mfhd
);
1204 lsmash_bs_put_be32( bs
, mfhd
->sequence_number
);
1208 static int isom_write_tfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1210 isom_tfhd_t
*tfhd
= (isom_tfhd_t
*)box
;
1211 isom_bs_put_box_common( bs
, tfhd
);
1212 lsmash_bs_put_be32( bs
, tfhd
->track_ID
);
1213 if( tfhd
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) lsmash_bs_put_be64( bs
, tfhd
->base_data_offset
);
1214 if( tfhd
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->sample_description_index
);
1215 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_duration
);
1216 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_size
);
1217 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &tfhd
->default_sample_flags
);
1221 static int isom_write_tfdt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1223 isom_tfdt_t
*tfdt
= (isom_tfdt_t
*)box
;
1224 /* Check the version. */
1225 tfdt
->version
= tfdt
->baseMediaDecodeTime
> UINT32_MAX
? 1 : 0;
1227 isom_bs_put_box_common( bs
, tfdt
);
1228 if( tfdt
->version
== 1 )
1229 lsmash_bs_put_be64( bs
, tfdt
->baseMediaDecodeTime
);
1231 lsmash_bs_put_be32( bs
, tfdt
->baseMediaDecodeTime
);
1235 static int isom_write_trun( lsmash_bs_t
*bs
, isom_box_t
*box
)
1237 isom_trun_t
*trun
= (isom_trun_t
*)box
;
1238 isom_bs_put_box_common( bs
, trun
);
1239 lsmash_bs_put_be32( bs
, trun
->sample_count
);
1240 if( trun
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, trun
->data_offset
);
1241 if( trun
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &trun
->first_sample_flags
);
1242 if( trun
->optional
)
1243 for( lsmash_entry_t
*entry
= trun
->optional
->head
; entry
; entry
= entry
->next
)
1245 isom_trun_optional_row_t
*data
= (isom_trun_optional_row_t
*)entry
->data
;
1247 return LSMASH_ERR_NAMELESS
;
1248 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_duration
);
1249 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_size
);
1250 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &data
->sample_flags
);
1251 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_composition_time_offset
);
1256 static int isom_write_traf( lsmash_bs_t
*bs
, isom_box_t
*box
)
1258 isom_bs_put_box_common( bs
, box
);
1262 static int isom_write_moof( lsmash_bs_t
*bs
, isom_box_t
*box
)
1264 isom_bs_put_box_common( bs
, box
);
1268 static int isom_write_tfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1270 isom_tfra_t
*tfra
= (isom_tfra_t
*)box
;
1271 isom_bs_put_box_common( bs
, tfra
);
1272 uint32_t temp
= (tfra
->reserved
<< 6)
1273 | (tfra
->length_size_of_traf_num
<< 4)
1274 | (tfra
->length_size_of_trun_num
<< 2)
1275 | tfra
->length_size_of_sample_num
;
1276 lsmash_bs_put_be32( bs
, tfra
->track_ID
);
1277 lsmash_bs_put_be32( bs
, temp
);
1278 lsmash_bs_put_be32( bs
, tfra
->number_of_entry
);
1281 void (*bs_put_funcs
[5])( lsmash_bs_t
*, uint64_t ) =
1283 lsmash_bs_put_byte_from_64
,
1284 lsmash_bs_put_be16_from_64
,
1285 lsmash_bs_put_be24_from_64
,
1286 lsmash_bs_put_be32_from_64
,
1289 void (*bs_put_time
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1290 void (*bs_put_moof_offset
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1291 void (*bs_put_traf_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_traf_num
];
1292 void (*bs_put_trun_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_trun_num
];
1293 void (*bs_put_sample_number
)( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_sample_num
];
1294 for( lsmash_entry_t
*entry
= tfra
->list
->head
; entry
; entry
= entry
->next
)
1296 isom_tfra_location_time_entry_t
*data
= (isom_tfra_location_time_entry_t
*)entry
->data
;
1298 return LSMASH_ERR_NAMELESS
;
1299 bs_put_time ( bs
, data
->time
);
1300 bs_put_moof_offset ( bs
, data
->moof_offset
);
1301 bs_put_traf_number ( bs
, data
->traf_number
);
1302 bs_put_trun_number ( bs
, data
->trun_number
);
1303 bs_put_sample_number( bs
, data
->sample_number
);
1309 static int isom_write_mfro( lsmash_bs_t
*bs
, isom_box_t
*box
)
1311 isom_mfro_t
*mfro
= (isom_mfro_t
*)box
;
1312 isom_bs_put_box_common( bs
, mfro
);
1313 lsmash_bs_put_be32( bs
, mfro
->length
); /* determined at isom_write_mfra(). */
1317 static int isom_write_mfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1319 isom_mfra_t
*mfra
= (isom_mfra_t
*)box
;
1321 mfra
->mfro
->length
= mfra
->size
;
1322 isom_bs_put_box_common( bs
, mfra
);
1326 static int isom_write_mdat( lsmash_bs_t
*bs
, isom_box_t
*box
)
1328 isom_mdat_t
*mdat
= (isom_mdat_t
*)box
;
1329 lsmash_file_t
*file
= mdat
->file
;
1330 /* If any fragment, write the Media Data Box all at once. */
1331 if( file
->fragment
)
1333 /* Write the size and type fields of the Media Data Box. */
1334 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ file
->fragment
->pool_size
;
1335 if( mdat
->size
> UINT32_MAX
)
1336 mdat
->size
+= 8; /* large_size */
1337 isom_bs_put_box_common( bs
, mdat
);
1338 /* Write the samples in the current movie fragment. */
1339 for( lsmash_entry_t
*entry
= file
->fragment
->pool
->head
; entry
; entry
= entry
->next
)
1341 isom_sample_pool_t
*pool
= (isom_sample_pool_t
*)entry
->data
;
1343 return LSMASH_ERR_NAMELESS
;
1344 lsmash_bs_put_bytes( bs
, pool
->size
, pool
->data
);
1346 mdat
->media_size
= file
->fragment
->pool_size
;
1349 if( mdat
->manager
& LSMASH_PLACEHOLDER
)
1351 /* Write an incomplete Media Data Box.
1352 * Braindead implementation might check box order and return an error if an expected box does not come the
1353 * next. Placement of eight 0x00 byte string as a simple large_size placeholder passes such silly box order
1354 * checks. This placement is more compatible than placement of a Free Space Box ('free' or 'skip') or a
1355 * Placeholder Atom ('wide') as a large_size placeholder since Media Data Box can store any data and any
1356 * implementation surely do not check what contents are stored in it until taking samples out according to
1357 * chunk offsets, and the placeholder is placed before any chunk offset thus it won't be touched. */
1358 mdat
->pos
= bs
->offset
;
1359 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1360 mdat
->manager
|= LSMASH_INCOMPLETE_BOX
;
1361 mdat
->manager
&= ~LSMASH_PLACEHOLDER
;
1362 isom_bs_put_box_common( bs
, mdat
);
1363 if( mdat
->size
<= UINT32_MAX
)
1364 lsmash_bs_put_be64( bs
, 0x0000000000000000 );
1365 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8;
1368 assert( !(mdat
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_PLACEHOLDER
)) );
1369 uint64_t actual_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->media_size
;
1370 uint64_t reserved_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1371 if( actual_size
< reserved_size
)
1373 /* Write padding zero bytes until end of this box.
1374 * This code path is invoked when the size of a Media Data Box was reserved. */
1375 mdat
->size
= reserved_size
;
1376 int err
= lsmash_bs_flush_buffer( bs
);
1379 uint64_t padding_size
= reserved_size
- actual_size
;
1380 static const uint8_t zero_bytes
[64] = { 0 };
1381 while( padding_size
> sizeof(zero_bytes
) )
1383 if( (err
= lsmash_bs_write_data( bs
, zero_bytes
, sizeof(zero_bytes
) )) < 0 )
1385 padding_size
-= sizeof(zero_bytes
);
1387 return lsmash_bs_write_data( bs
, zero_bytes
, padding_size
);
1389 if( !bs
->unseekable
)
1391 /* Write the actual size. */
1392 uint64_t current_pos
= bs
->offset
;
1393 mdat
->size
= actual_size
;
1394 lsmash_bs_write_seek( bs
, mdat
->pos
, SEEK_SET
);
1395 isom_bs_put_box_common( bs
, mdat
);
1396 /* isom_write_box() also calls lsmash_bs_flush_buffer() but it must do nothing. */
1397 int ret
= lsmash_bs_flush_buffer( bs
);
1398 lsmash_bs_write_seek( bs
, current_pos
, SEEK_SET
);
1401 return LSMASH_ERR_NAMELESS
;
1404 static int isom_write_ftyp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1406 isom_ftyp_t
*ftyp
= (isom_ftyp_t
*)box
;
1407 if( ftyp
->brand_count
== 0 )
1409 isom_bs_put_box_common( bs
, ftyp
);
1410 lsmash_bs_put_be32( bs
, ftyp
->major_brand
);
1411 lsmash_bs_put_be32( bs
, ftyp
->minor_version
);
1412 for( uint32_t i
= 0; i
< ftyp
->brand_count
; i
++ )
1413 lsmash_bs_put_be32( bs
, ftyp
->compatible_brands
[i
] );
1417 static int isom_write_moov( lsmash_bs_t
*bs
, isom_box_t
*box
)
1419 isom_bs_put_box_common( bs
, box
);
1423 static int isom_write_free( lsmash_bs_t
*bs
, isom_box_t
*box
)
1425 isom_free_t
*skip
= (isom_free_t
*)box
;
1426 isom_bs_put_box_common( bs
, skip
);
1427 if( skip
->data
&& skip
->length
)
1428 lsmash_bs_put_bytes( bs
, skip
->length
, skip
->data
);
1432 static int isom_write_sidx( lsmash_bs_t
*bs
, isom_box_t
*box
)
1434 isom_sidx_t
*sidx
= (isom_sidx_t
*)box
;
1435 /* Check the version. */
1436 if( sidx
->earliest_presentation_time
> UINT32_MAX
1437 || sidx
->first_offset
> UINT32_MAX
)
1442 isom_bs_put_box_common( bs
, sidx
);
1443 lsmash_bs_put_be32( bs
, sidx
->reference_ID
);
1444 lsmash_bs_put_be32( bs
, sidx
->timescale
);
1445 if( sidx
->version
== 0 )
1447 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->earliest_presentation_time
, UINT32_MAX
) );
1448 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->first_offset
, UINT32_MAX
) );
1452 lsmash_bs_put_be64( bs
, sidx
->earliest_presentation_time
);
1453 lsmash_bs_put_be64( bs
, sidx
->first_offset
);
1455 lsmash_bs_put_be16( bs
, sidx
->reserved
);
1456 lsmash_bs_put_be16( bs
, sidx
->reference_count
);
1457 for( lsmash_entry_t
*entry
= sidx
->list
->head
; entry
; entry
= entry
->next
)
1459 isom_sidx_referenced_item_t
*data
= (isom_sidx_referenced_item_t
*)entry
->data
;
1461 return LSMASH_ERR_NAMELESS
;
1463 temp32
= (data
->reference_type
<< 31)
1464 | data
->reference_size
;
1465 lsmash_bs_put_be32( bs
, temp32
);
1466 lsmash_bs_put_be32( bs
, data
->subsegment_duration
);
1467 temp32
= (data
->starts_with_SAP
<< 31)
1468 | (data
->SAP_type
<< 28)
1469 | data
->SAP_delta_time
;
1470 lsmash_bs_put_be32( bs
, temp32
);
1475 int isom_write_box( lsmash_bs_t
*bs
, isom_box_t
*box
)
1478 /* Don't write any incomplete or already written box to a file. */
1479 if( LSMASH_IS_NON_EXISTING_BOX( box
)
1481 || (bs
->stream
&& (box
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_WRITTEN_BOX
))) )
1483 int ret
= box
->write( bs
, box
);
1488 if( (ret
= lsmash_bs_flush_buffer( bs
)) < 0 )
1490 /* Don't write any child box if this box is a placeholder or an incomplete box. */
1491 if( box
->manager
& (LSMASH_PLACEHOLDER
| LSMASH_INCOMPLETE_BOX
) )
1494 box
->manager
|= LSMASH_WRITTEN_BOX
;
1496 return isom_write_children( bs
, box
);
1499 void isom_set_box_writer( isom_box_t
*box
)
1501 if( box
->manager
& LSMASH_BINARY_CODED_BOX
)
1503 box
->write
= isom_write_binary_coded_box
;
1506 else if( box
->manager
& LSMASH_UNKNOWN_BOX
)
1508 box
->write
= isom_write_unknown_box
;
1511 assert( LSMASH_IS_EXISTING_BOX( box
->parent
) );
1512 isom_box_t
*parent
= box
->parent
;
1513 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1515 /* OK, this box is a sample entry.
1516 * Here, determine the suitable sample entry writer by media type if possible. */
1517 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
1519 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
1520 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
1521 box
->write
= isom_write_visual_description
;
1522 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
1523 box
->write
= isom_write_audio_description
;
1524 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
1526 if( lsmash_check_box_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1527 box
->write
= isom_write_qt_text_description
;
1528 else if( lsmash_check_box_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1529 box
->write
= isom_write_tx3g_description
;
1534 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1536 if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_FRMA
) ) box
->write
= isom_write_frma
;
1537 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ENDA
) ) box
->write
= isom_write_enda
;
1538 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_MP4A
) ) box
->write
= isom_write_mp4a
;
1539 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ESDS
) ) box
->write
= isom_write_esds
;
1540 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CHAN
) ) box
->write
= isom_write_chan
;
1541 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_TERMINATOR
) ) box
->write
= isom_write_terminator
;
1542 else box
->write
= NULL
;
1545 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
1547 box
->write
= isom_write_track_reference_type
;
1550 static struct box_writer_table_tag
1552 lsmash_box_type_t type
;
1553 isom_extension_writer_t writer_func
;
1554 } box_writer_table
[128] = { { LSMASH_BOX_TYPE_INITIALIZER
, NULL
} };
1555 if( !box_writer_table
[0].writer_func
)
1557 /* Initialize the table. */
1559 #define ADD_BOX_WRITER_TABLE_ELEMENT( type, reader_func ) \
1560 box_writer_table[i++] = (struct box_writer_table_tag){ type, reader_func }
1561 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, isom_write_ftyp
);
1562 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, isom_write_ftyp
);
1563 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, isom_write_sidx
);
1564 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, isom_write_moov
);
1565 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, isom_write_mvhd
);
1566 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, isom_write_iods
);
1567 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, isom_write_ctab
);
1568 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, isom_write_esds
);
1569 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, isom_write_trak
);
1570 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, isom_write_tkhd
);
1571 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, isom_write_tapt
);
1572 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, isom_write_clef
);
1573 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, isom_write_prof
);
1574 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, isom_write_enof
);
1575 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, isom_write_edts
);
1576 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, isom_write_elst
);
1577 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, isom_write_tref
);
1578 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, isom_write_mdia
);
1579 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, isom_write_mdhd
);
1580 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, isom_write_hdlr
);
1581 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, isom_write_minf
);
1582 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, isom_write_vmhd
);
1583 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, isom_write_smhd
);
1584 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, isom_write_hmhd
);
1585 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, isom_write_nmhd
);
1586 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, isom_write_gmhd
);
1587 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, isom_write_gmin
);
1588 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, isom_write_text
);
1589 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, isom_write_dinf
);
1590 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, isom_write_dref
);
1591 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL
, isom_write_url
);
1592 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, isom_write_stbl
);
1593 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, isom_write_stsd
);
1594 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, isom_write_btrt
);
1595 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, isom_write_colr
);
1596 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_COLR
, isom_write_colr
);
1597 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, isom_write_clap
);
1598 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, isom_write_pasp
);
1599 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, isom_write_glbl
);
1600 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, isom_write_gama
);
1601 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, isom_write_fiel
);
1602 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, isom_write_cspc
);
1603 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, isom_write_sgbt
);
1604 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, isom_write_stsl
);
1605 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, isom_write_wave
);
1606 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MP4A
, isom_write_mp4a
);
1607 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, isom_write_chan
);
1608 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, isom_write_ftab
);
1609 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, isom_write_stts
);
1610 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, isom_write_ctts
);
1611 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, isom_write_cslg
);
1612 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, isom_write_stss
);
1613 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, isom_write_stps
);
1614 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, isom_write_sdtp
);
1615 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, isom_write_stsc
);
1616 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, isom_write_stsz
);
1617 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, isom_write_stz2
);
1618 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, isom_write_stco
);
1619 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, isom_write_stco
);
1620 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, isom_write_sgpd
);
1621 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, isom_write_sbgp
);
1622 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, isom_write_udta
);
1623 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, isom_write_chpl
);
1624 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, isom_write_mvex
);
1625 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, isom_write_mehd
);
1626 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, isom_write_trex
);
1627 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, isom_write_moof
);
1628 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, isom_write_mfhd
);
1629 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, isom_write_traf
);
1630 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, isom_write_tfhd
);
1631 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, isom_write_tfdt
);
1632 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, isom_write_trun
);
1633 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, isom_write_mdat
);
1634 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, isom_write_free
);
1635 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, isom_write_free
);
1636 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_META
, isom_write_meta
);
1637 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_META
, isom_write_meta
);
1638 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST
, isom_write_ilst
);
1639 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ILST
, isom_write_ilst
);
1640 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, isom_write_mfra
);
1641 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, isom_write_tfra
);
1642 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, isom_write_mfro
);
1643 ADD_BOX_WRITER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
);
1644 #undef ADD_BOX_WRITER_TABLE_ELEMENT
1646 for( int i
= 0; box_writer_table
[i
].writer_func
; i
++ )
1647 if( lsmash_check_box_type_identical( box
->type
, box_writer_table
[i
].type
) )
1649 box
->write
= box_writer_table
[i
].writer_func
;
1652 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
1653 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
1655 box
->write
= isom_write_metaitem
;
1658 if( lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_ILST
) )
1660 if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_MEAN
) )
1661 box
->write
= isom_write_mean
;
1662 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_NAME
) )
1663 box
->write
= isom_write_name
;
1664 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_DATA
) )
1665 box
->write
= isom_write_data
;
1669 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_CPRT
) )
1671 /* Avoid confusing udta.cprt with ilst.cprt. */
1672 box
->write
= isom_write_cprt
;
1675 box
->write
= isom_write_unknown_box
;