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_tims( lsmash_bs_t
*bs
, isom_box_t
*box
)
475 isom_tims_t
*tims
= (isom_tims_t
*)box
;
476 isom_bs_put_box_common( bs
, tims
);
477 lsmash_bs_put_be32( bs
, tims
->timescale
);
481 static int isom_write_tsro( lsmash_bs_t
*bs
, isom_box_t
*box
)
483 isom_tsro_t
*tsro
= (isom_tsro_t
*)box
;
484 isom_bs_put_box_common( bs
, tsro
);
485 lsmash_bs_put_be32( bs
, tsro
->offset
);
489 static int isom_write_tssy( lsmash_bs_t
*bs
, isom_box_t
*box
)
491 isom_tssy_t
*tssy
= (isom_tssy_t
*)box
;
492 isom_bs_put_box_common( bs
, tssy
);
494 data
= tssy
->reserved
<< 2;
495 data
|= tssy
->timestamp_sync
;
496 lsmash_bs_put_byte( bs
, data
);
500 static int isom_write_glbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
502 isom_glbl_t
*glbl
= (isom_glbl_t
*)box
;
503 isom_bs_put_box_common( bs
, glbl
);
504 if( glbl
->header_data
&& glbl
->header_size
)
505 lsmash_bs_put_bytes( bs
, glbl
->header_size
, glbl
->header_data
);
509 static int isom_write_frma( lsmash_bs_t
*bs
, isom_box_t
*box
)
511 isom_frma_t
*frma
= (isom_frma_t
*)box
;
512 isom_bs_put_box_common( bs
, frma
);
513 lsmash_bs_put_be32( bs
, frma
->data_format
);
517 static int isom_write_enda( lsmash_bs_t
*bs
, isom_box_t
*box
)
519 isom_enda_t
*enda
= (isom_enda_t
*)box
;
520 isom_bs_put_box_common( bs
, enda
);
521 lsmash_bs_put_be16( bs
, enda
->littleEndian
);
525 static int isom_write_mp4a( lsmash_bs_t
*bs
, isom_box_t
*box
)
527 isom_mp4a_t
*mp4a
= (isom_mp4a_t
*)box
;
528 isom_bs_put_box_common( bs
, mp4a
);
529 lsmash_bs_put_be32( bs
, mp4a
->unknown
);
533 static int isom_write_chan( lsmash_bs_t
*bs
, isom_box_t
*box
)
535 isom_chan_t
*chan
= (isom_chan_t
*)box
;
536 isom_bs_put_box_common( bs
, chan
);
537 lsmash_bs_put_be32( bs
, chan
->channelLayoutTag
);
538 lsmash_bs_put_be32( bs
, chan
->channelBitmap
);
539 lsmash_bs_put_be32( bs
, chan
->numberChannelDescriptions
);
540 if( chan
->channelDescriptions
)
541 for( uint32_t i
= 0; i
< chan
->numberChannelDescriptions
; i
++ )
543 isom_channel_description_t
*channelDescriptions
= (isom_channel_description_t
*)(&chan
->channelDescriptions
[i
]);
544 lsmash_bs_put_be32( bs
, channelDescriptions
->channelLabel
);
545 lsmash_bs_put_be32( bs
, channelDescriptions
->channelFlags
);
546 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[0] );
547 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[1] );
548 lsmash_bs_put_be32( bs
, channelDescriptions
->coordinates
[2] );
553 static int isom_write_terminator( lsmash_bs_t
*bs
, isom_box_t
*box
)
555 isom_bs_put_box_common( bs
, box
);
559 static int isom_write_wave( lsmash_bs_t
*bs
, isom_box_t
*box
)
561 isom_bs_put_box_common( bs
, box
);
565 static int isom_write_visual_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
567 isom_visual_entry_t
*data
= (isom_visual_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_be32( bs
, data
->temporalQuality
);
577 lsmash_bs_put_be32( bs
, data
->spatialQuality
);
578 lsmash_bs_put_be16( bs
, data
->width
);
579 lsmash_bs_put_be16( bs
, data
->height
);
580 lsmash_bs_put_be32( bs
, data
->horizresolution
);
581 lsmash_bs_put_be32( bs
, data
->vertresolution
);
582 lsmash_bs_put_be32( bs
, data
->dataSize
);
583 lsmash_bs_put_be16( bs
, data
->frame_count
);
584 lsmash_bs_put_bytes( bs
, 32, data
->compressorname
);
585 lsmash_bs_put_be16( bs
, data
->depth
);
586 lsmash_bs_put_be16( bs
, data
->color_table_ID
);
587 if( data
->color_table_ID
== 0 )
588 isom_bs_put_qt_color_table( bs
, &data
->color_table
);
592 static int isom_write_audio_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
594 isom_audio_entry_t
*data
= (isom_audio_entry_t
*)box
;
595 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
596 return LSMASH_ERR_NAMELESS
;
597 isom_bs_put_box_common( bs
, data
);
598 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
599 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
600 lsmash_bs_put_be16( bs
, data
->version
);
601 lsmash_bs_put_be16( bs
, data
->revision_level
);
602 lsmash_bs_put_be32( bs
, data
->vendor
);
603 lsmash_bs_put_be16( bs
, data
->channelcount
);
604 lsmash_bs_put_be16( bs
, data
->samplesize
);
605 lsmash_bs_put_be16( bs
, data
->compression_ID
);
606 lsmash_bs_put_be16( bs
, data
->packet_size
);
607 lsmash_bs_put_be32( bs
, data
->samplerate
);
608 if( data
->version
== 1 )
610 lsmash_bs_put_be32( bs
, data
->samplesPerPacket
);
611 lsmash_bs_put_be32( bs
, data
->bytesPerPacket
);
612 lsmash_bs_put_be32( bs
, data
->bytesPerFrame
);
613 lsmash_bs_put_be32( bs
, data
->bytesPerSample
);
615 else if( data
->version
== 2 )
617 lsmash_bs_put_be32( bs
, data
->sizeOfStructOnly
);
618 lsmash_bs_put_be64( bs
, data
->audioSampleRate
);
619 lsmash_bs_put_be32( bs
, data
->numAudioChannels
);
620 lsmash_bs_put_be32( bs
, data
->always7F000000
);
621 lsmash_bs_put_be32( bs
, data
->constBitsPerChannel
);
622 lsmash_bs_put_be32( bs
, data
->formatSpecificFlags
);
623 lsmash_bs_put_be32( bs
, data
->constBytesPerAudioPacket
);
624 lsmash_bs_put_be32( bs
, data
->constLPCMFramesPerAudioPacket
);
629 static int isom_write_hint_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
631 isom_hint_entry_t
*data
= (isom_hint_entry_t
*)box
;
632 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
633 return LSMASH_ERR_NAMELESS
;
634 isom_bs_put_box_common( bs
, data
);
635 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
636 lsmash_bs_put_be16( bs
, data
->hinttrackversion
);
637 lsmash_bs_put_be16( bs
, data
->highestcompatibleversion
);
638 lsmash_bs_put_be32( bs
, data
->maxpacketsize
);
643 static int isom_write_metadata_description( lsmash_bs_t
*bs
, lsmash_entry_t
*entry
)
645 isom_metadata_entry_t
*data
= (isom_metadata_entry_t
*)entry
->data
;
646 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
647 return LSMASH_ERR_NAMELESS
;
648 isom_bs_put_box_common( bs
, data
);
649 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
650 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
655 static int isom_write_qt_text_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
657 isom_qt_text_entry_t
*data
= (isom_qt_text_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
->data_reference_index
);
663 lsmash_bs_put_be32( bs
, data
->displayFlags
);
664 lsmash_bs_put_be32( bs
, data
->textJustification
);
665 for( uint32_t i
= 0; i
< 3; i
++ )
666 lsmash_bs_put_be16( bs
, data
->bgColor
[i
] );
667 lsmash_bs_put_be16( bs
, data
->top
);
668 lsmash_bs_put_be16( bs
, data
->left
);
669 lsmash_bs_put_be16( bs
, data
->bottom
);
670 lsmash_bs_put_be16( bs
, data
->right
);
671 lsmash_bs_put_be32( bs
, data
->scrpStartChar
);
672 lsmash_bs_put_be16( bs
, data
->scrpHeight
);
673 lsmash_bs_put_be16( bs
, data
->scrpAscent
);
674 lsmash_bs_put_be16( bs
, data
->scrpFont
);
675 lsmash_bs_put_be16( bs
, data
->scrpFace
);
676 lsmash_bs_put_be16( bs
, data
->scrpSize
);
677 for( uint32_t i
= 0; i
< 3; i
++ )
678 lsmash_bs_put_be16( bs
, data
->scrpColor
[i
] );
679 lsmash_bs_put_byte( bs
, data
->font_name_length
);
680 if( data
->font_name
&& data
->font_name_length
)
681 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
685 static int isom_write_ftab( lsmash_bs_t
*bs
, isom_box_t
*box
)
687 isom_ftab_t
*ftab
= (isom_ftab_t
*)box
;
688 assert( ftab
->list
);
689 isom_bs_put_box_common( bs
, ftab
);
690 lsmash_bs_put_be16( bs
, ftab
->list
->entry_count
);
691 for( lsmash_entry_t
*entry
= ftab
->list
->head
; entry
; entry
= entry
->next
)
693 isom_font_record_t
*data
= (isom_font_record_t
*)entry
->data
;
695 return LSMASH_ERR_NAMELESS
;
696 lsmash_bs_put_be16( bs
, data
->font_ID
);
697 lsmash_bs_put_byte( bs
, data
->font_name_length
);
698 if( data
->font_name
&& data
->font_name_length
)
699 lsmash_bs_put_bytes( bs
, data
->font_name_length
, data
->font_name
);
704 static int isom_write_tx3g_description( lsmash_bs_t
*bs
, isom_box_t
*box
)
706 isom_tx3g_entry_t
*data
= (isom_tx3g_entry_t
*)box
;
707 if( LSMASH_IS_NON_EXISTING_BOX( data
) )
708 return LSMASH_ERR_NAMELESS
;
709 isom_bs_put_box_common( bs
, data
);
710 lsmash_bs_put_bytes( bs
, 6, data
->reserved
);
711 lsmash_bs_put_be16( bs
, data
->data_reference_index
);
712 lsmash_bs_put_be32( bs
, data
->displayFlags
);
713 lsmash_bs_put_byte( bs
, data
->horizontal_justification
);
714 lsmash_bs_put_byte( bs
, data
->vertical_justification
);
715 for( uint32_t i
= 0; i
< 4; i
++ )
716 lsmash_bs_put_byte( bs
, data
->background_color_rgba
[i
] );
717 lsmash_bs_put_be16( bs
, data
->top
);
718 lsmash_bs_put_be16( bs
, data
->left
);
719 lsmash_bs_put_be16( bs
, data
->bottom
);
720 lsmash_bs_put_be16( bs
, data
->right
);
721 lsmash_bs_put_be16( bs
, data
->startChar
);
722 lsmash_bs_put_be16( bs
, data
->endChar
);
723 lsmash_bs_put_be16( bs
, data
->font_ID
);
724 lsmash_bs_put_byte( bs
, data
->face_style_flags
);
725 lsmash_bs_put_byte( bs
, data
->font_size
);
726 for( uint32_t i
= 0; i
< 4; i
++ )
727 lsmash_bs_put_byte( bs
, data
->text_color_rgba
[i
] );
731 static int isom_write_stsd( lsmash_bs_t
*bs
, isom_box_t
*box
)
733 isom_stsd_t
*stsd
= (isom_stsd_t
*)box
;
734 isom_bs_put_box_common( bs
, stsd
);
735 lsmash_bs_put_be32( bs
, stsd
->list
.entry_count
);
739 static int isom_write_stts( lsmash_bs_t
*bs
, isom_box_t
*box
)
741 isom_stts_t
*stts
= (isom_stts_t
*)box
;
742 assert( stts
->list
);
743 isom_bs_put_box_common( bs
, stts
);
744 lsmash_bs_put_be32( bs
, stts
->list
->entry_count
);
745 for( lsmash_entry_t
*entry
= stts
->list
->head
; entry
; entry
= entry
->next
)
747 isom_stts_entry_t
*data
= (isom_stts_entry_t
*)entry
->data
;
749 return LSMASH_ERR_NAMELESS
;
750 lsmash_bs_put_be32( bs
, data
->sample_count
);
751 lsmash_bs_put_be32( bs
, data
->sample_delta
);
756 static int isom_write_ctts( lsmash_bs_t
*bs
, isom_box_t
*box
)
758 isom_ctts_t
*ctts
= (isom_ctts_t
*)box
;
759 assert( ctts
->list
);
760 isom_bs_put_box_common( bs
, ctts
);
761 lsmash_bs_put_be32( bs
, ctts
->list
->entry_count
);
762 for( lsmash_entry_t
*entry
= ctts
->list
->head
; entry
; entry
= entry
->next
)
764 isom_ctts_entry_t
*data
= (isom_ctts_entry_t
*)entry
->data
;
766 return LSMASH_ERR_NAMELESS
;
767 lsmash_bs_put_be32( bs
, data
->sample_count
);
768 lsmash_bs_put_be32( bs
, data
->sample_offset
);
773 static int isom_write_cslg( lsmash_bs_t
*bs
, isom_box_t
*box
)
775 isom_cslg_t
*cslg
= (isom_cslg_t
*)box
;
776 isom_bs_put_box_common( bs
, cslg
);
777 lsmash_bs_put_be32( bs
, cslg
->compositionToDTSShift
);
778 lsmash_bs_put_be32( bs
, cslg
->leastDecodeToDisplayDelta
);
779 lsmash_bs_put_be32( bs
, cslg
->greatestDecodeToDisplayDelta
);
780 lsmash_bs_put_be32( bs
, cslg
->compositionStartTime
);
781 lsmash_bs_put_be32( bs
, cslg
->compositionEndTime
);
785 static int isom_write_stsz( lsmash_bs_t
*bs
, isom_box_t
*box
)
787 isom_stsz_t
*stsz
= (isom_stsz_t
*)box
;
788 isom_bs_put_box_common( bs
, stsz
);
789 lsmash_bs_put_be32( bs
, stsz
->sample_size
);
790 lsmash_bs_put_be32( bs
, stsz
->sample_count
);
791 if( stsz
->sample_size
== 0 && stsz
->list
)
792 for( lsmash_entry_t
*entry
= stsz
->list
->head
; entry
; entry
= entry
->next
)
794 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
796 return LSMASH_ERR_NAMELESS
;
797 lsmash_bs_put_be32( bs
, data
->entry_size
);
802 static int isom_write_stz2( lsmash_bs_t
*bs
, isom_box_t
*box
)
804 isom_stz2_t
*stz2
= (isom_stz2_t
*)box
;
805 isom_bs_put_box_common( bs
, stz2
);
806 lsmash_bs_put_be32( bs
, (stz2
->reserved
<< 8) | stz2
->field_size
);
807 lsmash_bs_put_be32( bs
, stz2
->sample_count
);
808 if( stz2
->field_size
== 16 )
809 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
811 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
813 return LSMASH_ERR_NAMELESS
;
814 assert( data
->entry_size
<= 0xffff );
815 lsmash_bs_put_be16( bs
, data
->entry_size
);
817 else if( stz2
->field_size
== 8 )
818 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
)
820 isom_stsz_entry_t
*data
= (isom_stsz_entry_t
*)entry
->data
;
822 return LSMASH_ERR_NAMELESS
;
823 assert( data
->entry_size
<= 0xff );
824 lsmash_bs_put_byte( bs
, data
->entry_size
);
826 else if( stz2
->field_size
== 4 )
828 isom_stsz_entry_t zero_padding
= { .entry_size
= 0 };
829 for( lsmash_entry_t
*entry
= stz2
->list
->head
; entry
; entry
= entry
->next
? entry
->next
->next
: entry
->next
)
831 isom_stsz_entry_t
*data_o
= (isom_stsz_entry_t
*)entry
->data
;
832 isom_stsz_entry_t
*data_e
= (isom_stsz_entry_t
*)(entry
->next
? entry
->next
->data
: &zero_padding
);
833 if( !data_o
|| !data_e
)
834 return LSMASH_ERR_NAMELESS
;
835 assert( data_o
->entry_size
<= 0xf && data_e
->entry_size
<= 0xf );
836 lsmash_bs_put_byte( bs
, (data_o
->entry_size
<< 4) | data_e
->entry_size
);
840 return LSMASH_ERR_NAMELESS
;
844 static int isom_write_stss( lsmash_bs_t
*bs
, isom_box_t
*box
)
846 isom_stss_t
*stss
= (isom_stss_t
*)box
;
847 assert( stss
->list
);
848 isom_bs_put_box_common( bs
, stss
);
849 lsmash_bs_put_be32( bs
, stss
->list
->entry_count
);
850 for( lsmash_entry_t
*entry
= stss
->list
->head
; entry
; entry
= entry
->next
)
852 isom_stss_entry_t
*data
= (isom_stss_entry_t
*)entry
->data
;
854 return LSMASH_ERR_NAMELESS
;
855 lsmash_bs_put_be32( bs
, data
->sample_number
);
860 static int isom_write_stps( lsmash_bs_t
*bs
, isom_box_t
*box
)
862 isom_stps_t
*stps
= (isom_stps_t
*)box
;
863 assert( stps
->list
);
864 isom_bs_put_box_common( bs
, stps
);
865 lsmash_bs_put_be32( bs
, stps
->list
->entry_count
);
866 for( lsmash_entry_t
*entry
= stps
->list
->head
; entry
; entry
= entry
->next
)
868 isom_stps_entry_t
*data
= (isom_stps_entry_t
*)entry
->data
;
870 return LSMASH_ERR_NAMELESS
;
871 lsmash_bs_put_be32( bs
, data
->sample_number
);
876 static int isom_write_sdtp( lsmash_bs_t
*bs
, isom_box_t
*box
)
878 isom_sdtp_t
*sdtp
= (isom_sdtp_t
*)box
;
879 assert( sdtp
->list
);
880 isom_bs_put_box_common( bs
, sdtp
);
881 for( lsmash_entry_t
*entry
= sdtp
->list
->head
; entry
; entry
= entry
->next
)
883 isom_sdtp_entry_t
*data
= (isom_sdtp_entry_t
*)entry
->data
;
885 return LSMASH_ERR_NAMELESS
;
886 uint8_t temp
= (data
->is_leading
<< 6)
887 | (data
->sample_depends_on
<< 4)
888 | (data
->sample_is_depended_on
<< 2)
889 | data
->sample_has_redundancy
;
890 lsmash_bs_put_byte( bs
, temp
);
895 static int isom_write_stsc( lsmash_bs_t
*bs
, isom_box_t
*box
)
897 isom_stsc_t
*stsc
= (isom_stsc_t
*)box
;
898 assert( stsc
->list
);
899 isom_bs_put_box_common( bs
, stsc
);
900 lsmash_bs_put_be32( bs
, stsc
->list
->entry_count
);
901 for( lsmash_entry_t
*entry
= stsc
->list
->head
; entry
; entry
= entry
->next
)
903 isom_stsc_entry_t
*data
= (isom_stsc_entry_t
*)entry
->data
;
905 return LSMASH_ERR_NAMELESS
;
906 lsmash_bs_put_be32( bs
, data
->first_chunk
);
907 lsmash_bs_put_be32( bs
, data
->samples_per_chunk
);
908 lsmash_bs_put_be32( bs
, data
->sample_description_index
);
913 static int isom_write_co64( lsmash_bs_t
*bs
, isom_box_t
*box
)
915 isom_stco_t
*co64
= (isom_stco_t
*)box
;
916 assert( co64
->list
);
917 isom_bs_put_box_common( bs
, co64
);
918 lsmash_bs_put_be32( bs
, co64
->list
->entry_count
);
919 for( lsmash_entry_t
*entry
= co64
->list
->head
; entry
; entry
= entry
->next
)
921 isom_co64_entry_t
*data
= (isom_co64_entry_t
*)entry
->data
;
923 return LSMASH_ERR_NAMELESS
;
924 lsmash_bs_put_be64( bs
, data
->chunk_offset
);
929 static int isom_write_stco( lsmash_bs_t
*bs
, isom_box_t
*box
)
931 isom_stco_t
*stco
= (isom_stco_t
*)box
;
932 if( stco
->large_presentation
)
933 return isom_write_co64( bs
, box
);
934 assert( stco
->list
);
935 isom_bs_put_box_common( bs
, stco
);
936 lsmash_bs_put_be32( bs
, stco
->list
->entry_count
);
937 for( lsmash_entry_t
*entry
= stco
->list
->head
; entry
; entry
= entry
->next
)
939 isom_stco_entry_t
*data
= (isom_stco_entry_t
*)entry
->data
;
941 return LSMASH_ERR_NAMELESS
;
942 lsmash_bs_put_be32( bs
, data
->chunk_offset
);
947 static int isom_write_sgpd( lsmash_bs_t
*bs
, isom_box_t
*box
)
949 isom_sgpd_t
*sgpd
= (isom_sgpd_t
*)box
;
950 assert( sgpd
->list
);
951 isom_bs_put_box_common( bs
, sgpd
);
952 lsmash_bs_put_be32( bs
, sgpd
->grouping_type
);
953 if( sgpd
->version
== 1 )
954 lsmash_bs_put_be32( bs
, sgpd
->default_length
);
955 lsmash_bs_put_be32( bs
, sgpd
->list
->entry_count
);
956 for( lsmash_entry_t
*entry
= sgpd
->list
->head
; entry
; entry
= entry
->next
)
959 return LSMASH_ERR_NAMELESS
;
960 switch( sgpd
->grouping_type
)
962 case ISOM_GROUP_TYPE_RAP
:
964 isom_rap_entry_t
*rap
= (isom_rap_entry_t
*)entry
->data
;
965 uint8_t temp
= (rap
->num_leading_samples_known
<< 7)
966 | rap
->num_leading_samples
;
967 lsmash_bs_put_byte( bs
, temp
);
970 case ISOM_GROUP_TYPE_ROLL
:
971 case ISOM_GROUP_TYPE_PROL
:
972 lsmash_bs_put_be16( bs
, ((isom_roll_entry_t
*)entry
->data
)->roll_distance
);
975 /* We don't consider other grouping types currently. */
976 // if( sgpd->version == 1 && !sgpd->default_length )
977 // lsmash_bs_put_be32( bs, ((isom_sgpd_t *)entry->data)->description_length );
984 static int isom_write_sbgp( lsmash_bs_t
*bs
, isom_box_t
*box
)
986 isom_sbgp_t
*sbgp
= (isom_sbgp_t
*)box
;
987 assert( sbgp
->list
);
988 isom_bs_put_box_common( bs
, sbgp
);
989 lsmash_bs_put_be32( bs
, sbgp
->grouping_type
);
990 if( sbgp
->version
== 1 )
991 lsmash_bs_put_be32( bs
, sbgp
->grouping_type_parameter
);
992 lsmash_bs_put_be32( bs
, sbgp
->list
->entry_count
);
993 for( lsmash_entry_t
*entry
= sbgp
->list
->head
; entry
; entry
= entry
->next
)
995 isom_group_assignment_entry_t
*data
= (isom_group_assignment_entry_t
*)entry
->data
;
997 return LSMASH_ERR_NAMELESS
;
998 lsmash_bs_put_be32( bs
, data
->sample_count
);
999 lsmash_bs_put_be32( bs
, data
->group_description_index
);
1004 static int isom_write_stbl( lsmash_bs_t
*bs
, isom_box_t
*box
)
1006 isom_bs_put_box_common( bs
, box
);
1010 static int isom_write_minf( lsmash_bs_t
*bs
, isom_box_t
*box
)
1012 isom_bs_put_box_common( bs
, box
);
1016 static int isom_write_mdia( lsmash_bs_t
*bs
, isom_box_t
*box
)
1018 isom_bs_put_box_common( bs
, box
);
1022 static int isom_write_chpl( lsmash_bs_t
*bs
, isom_box_t
*box
)
1024 isom_chpl_t
*chpl
= (isom_chpl_t
*)box
;
1025 assert( chpl
->list
);
1026 isom_bs_put_box_common( bs
, chpl
);
1027 if( chpl
->version
== 1 )
1029 lsmash_bs_put_byte( bs
, chpl
->unknown
);
1030 lsmash_bs_put_be32( bs
, chpl
->list
->entry_count
);
1032 else /* chpl->version == 0 */
1033 lsmash_bs_put_byte( bs
, (uint8_t)chpl
->list
->entry_count
);
1034 for( lsmash_entry_t
*entry
= chpl
->list
->head
; entry
; entry
= entry
->next
)
1036 isom_chpl_entry_t
*data
= (isom_chpl_entry_t
*)entry
->data
;
1038 return LSMASH_ERR_NAMELESS
;
1039 lsmash_bs_put_be64( bs
, data
->start_time
);
1040 lsmash_bs_put_byte( bs
, data
->chapter_name_length
);
1041 lsmash_bs_put_bytes( bs
, data
->chapter_name_length
, data
->chapter_name
);
1046 static int isom_write_mean( lsmash_bs_t
*bs
, isom_box_t
*box
)
1048 isom_mean_t
*mean
= (isom_mean_t
*)box
;
1049 isom_bs_put_box_common( bs
, mean
);
1050 if( mean
->meaning_string
&& mean
->meaning_string_length
)
1051 lsmash_bs_put_bytes( bs
, mean
->meaning_string_length
, mean
->meaning_string
);
1055 static int isom_write_name( lsmash_bs_t
*bs
, isom_box_t
*box
)
1057 isom_name_t
*name
= (isom_name_t
*)box
;
1058 isom_bs_put_box_common( bs
, name
);
1059 if( name
->name
&& name
->name_length
)
1060 lsmash_bs_put_bytes( bs
, name
->name_length
, name
->name
);
1064 static int isom_write_data( lsmash_bs_t
*bs
, isom_box_t
*box
)
1066 isom_data_t
*data
= (isom_data_t
*)box
;
1067 isom_bs_put_box_common( bs
, data
);
1068 lsmash_bs_put_be16( bs
, data
->reserved
);
1069 lsmash_bs_put_byte( bs
, data
->type_set_identifier
);
1070 lsmash_bs_put_byte( bs
, data
->type_code
);
1071 lsmash_bs_put_be32( bs
, data
->the_locale
);
1072 if( data
->value
&& data
->value_length
)
1073 lsmash_bs_put_bytes( bs
, data
->value_length
, data
->value
);
1077 static int isom_write_metaitem( lsmash_bs_t
*bs
, isom_box_t
*box
)
1079 isom_bs_put_box_common( bs
, box
);
1083 static int isom_write_ilst( lsmash_bs_t
*bs
, isom_box_t
*box
)
1085 isom_bs_put_box_common( bs
, box
);
1089 static int isom_write_meta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1091 isom_bs_put_box_common( bs
, box
);
1095 static int isom_write_cprt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1097 isom_cprt_t
*cprt
= (isom_cprt_t
*)box
;
1098 isom_bs_put_box_common( bs
, cprt
);
1099 lsmash_bs_put_be16( bs
, cprt
->language
);
1100 lsmash_bs_put_bytes( bs
, cprt
->notice_length
, cprt
->notice
);
1104 static int isom_write_udta( lsmash_bs_t
*bs
, isom_box_t
*box
)
1106 isom_bs_put_box_common( bs
, box
);
1110 static int isom_write_hnti( lsmash_bs_t
*bs
, isom_box_t
*box
)
1112 isom_bs_put_box_common( bs
, box
);
1116 static int isom_write_rtp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1118 isom_rtp_t
*rtp
= (isom_rtp_t
*)box
;
1119 isom_bs_put_box_common( bs
, rtp
);
1120 lsmash_bs_put_be32( bs
, rtp
->descriptionformat
);
1121 lsmash_bs_put_bytes( bs
, rtp
->sdp_length
, rtp
->sdptext
);
1124 static int isom_write_sdp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1126 isom_sdp_t
*sdp
= (isom_sdp_t
*)box
;
1127 isom_bs_put_box_common( bs
, sdp
);
1128 lsmash_bs_put_bytes( bs
, sdp
->sdp_length
, sdp
->sdptext
);
1132 static int isom_write_trak( lsmash_bs_t
*bs
, isom_box_t
*box
)
1134 isom_bs_put_box_common( bs
, box
);
1138 static int isom_write_iods( lsmash_bs_t
*bs
, isom_box_t
*box
)
1140 isom_iods_t
*iods
= (isom_iods_t
*)box
;
1141 isom_bs_put_box_common( bs
, iods
);
1142 mp4sys_update_descriptor_size( iods
->OD
);
1143 return mp4sys_write_descriptor( bs
, iods
->OD
);
1146 static int isom_write_mvhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1148 isom_mvhd_t
*mvhd
= (isom_mvhd_t
*)box
;
1149 /* Check the version. */
1150 if( (LSMASH_IS_EXISTING_BOX( mvhd
->file
) && !mvhd
->file
->undefined_64_ver
)
1151 && (mvhd
->creation_time
> UINT32_MAX
1152 || mvhd
->modification_time
> UINT32_MAX
1153 || mvhd
->duration
> UINT32_MAX
) )
1158 isom_bs_put_box_common( bs
, mvhd
);
1161 lsmash_bs_put_be64( bs
, mvhd
->creation_time
);
1162 lsmash_bs_put_be64( bs
, mvhd
->modification_time
);
1163 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1164 lsmash_bs_put_be64( bs
, mvhd
->duration
);
1168 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->creation_time
, UINT32_MAX
) );
1169 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->modification_time
, UINT32_MAX
) );
1170 lsmash_bs_put_be32( bs
, mvhd
->timescale
);
1171 lsmash_bs_put_be32( bs
, LSMASH_MIN( mvhd
->duration
, UINT32_MAX
) );
1173 lsmash_bs_put_be32( bs
, mvhd
->rate
);
1174 lsmash_bs_put_be16( bs
, mvhd
->volume
);
1175 lsmash_bs_put_be16( bs
, mvhd
->reserved
);
1176 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[0] );
1177 lsmash_bs_put_be32( bs
, mvhd
->preferredLong
[1] );
1178 for( int i
= 0; i
< 9; i
++ )
1179 lsmash_bs_put_be32( bs
, mvhd
->matrix
[i
] );
1180 lsmash_bs_put_be32( bs
, mvhd
->previewTime
);
1181 lsmash_bs_put_be32( bs
, mvhd
->previewDuration
);
1182 lsmash_bs_put_be32( bs
, mvhd
->posterTime
);
1183 lsmash_bs_put_be32( bs
, mvhd
->selectionTime
);
1184 lsmash_bs_put_be32( bs
, mvhd
->selectionDuration
);
1185 lsmash_bs_put_be32( bs
, mvhd
->currentTime
);
1186 lsmash_bs_put_be32( bs
, mvhd
->next_track_ID
);
1190 static void isom_bs_put_sample_flags( lsmash_bs_t
*bs
, isom_sample_flags_t
*flags
)
1192 uint32_t temp
= (flags
->reserved
<< 28)
1193 | (flags
->is_leading
<< 26)
1194 | (flags
->sample_depends_on
<< 24)
1195 | (flags
->sample_is_depended_on
<< 22)
1196 | (flags
->sample_has_redundancy
<< 20)
1197 | (flags
->sample_padding_value
<< 17)
1198 | (flags
->sample_is_non_sync_sample
<< 16)
1199 | flags
->sample_degradation_priority
;
1200 lsmash_bs_put_be32( bs
, temp
);
1203 static int isom_write_mehd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1205 if( box
->manager
& LSMASH_PLACEHOLDER
)
1207 /* Movie Extends Header Box is not written immediately.
1208 * It's done after finishing all movie fragments.
1209 * The following will be overwritten by Movie Extends Header Box.
1210 * We use version 1 Movie Extends Header Box since it causes extra 4 bytes region
1211 * we cannot replace with empty Free Space Box as we place version 0 one. */
1212 box
->pos
= box
->file
->bs
->written
;
1213 lsmash_bs_put_be32( bs
, ISOM_BASEBOX_COMMON_SIZE
+ 12 );
1214 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_FREE
.fourcc
);
1215 lsmash_bs_put_be32( bs
, 0 );
1216 lsmash_bs_put_be64( bs
, 0 );
1220 isom_mehd_t
*mehd
= (isom_mehd_t
*)box
;
1221 //mehd->version = mehd->fragment_duration > UINT32_MAX ? 1 : 0;
1222 isom_bs_put_box_common( bs
, mehd
);
1223 if( mehd
->version
== 1 )
1224 lsmash_bs_put_be64( bs
, mehd
->fragment_duration
);
1226 lsmash_bs_put_be32( bs
, LSMASH_MIN( mehd
->fragment_duration
, UINT32_MAX
) );
1231 static int isom_write_trex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1233 isom_trex_t
*trex
= (isom_trex_t
*)box
;
1234 isom_bs_put_box_common( bs
, trex
);
1235 lsmash_bs_put_be32( bs
, trex
->track_ID
);
1236 lsmash_bs_put_be32( bs
, trex
->default_sample_description_index
);
1237 lsmash_bs_put_be32( bs
, trex
->default_sample_duration
);
1238 lsmash_bs_put_be32( bs
, trex
->default_sample_size
);
1239 isom_bs_put_sample_flags( bs
, &trex
->default_sample_flags
);
1243 static int isom_write_mvex( lsmash_bs_t
*bs
, isom_box_t
*box
)
1245 isom_bs_put_box_common( bs
, box
);
1249 static int isom_write_mfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1251 isom_mfhd_t
*mfhd
= (isom_mfhd_t
*)box
;
1252 isom_bs_put_box_common( bs
, mfhd
);
1253 lsmash_bs_put_be32( bs
, mfhd
->sequence_number
);
1257 static int isom_write_tfhd( lsmash_bs_t
*bs
, isom_box_t
*box
)
1259 isom_tfhd_t
*tfhd
= (isom_tfhd_t
*)box
;
1260 isom_bs_put_box_common( bs
, tfhd
);
1261 lsmash_bs_put_be32( bs
, tfhd
->track_ID
);
1262 if( tfhd
->flags
& ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT
) lsmash_bs_put_be64( bs
, tfhd
->base_data_offset
);
1263 if( tfhd
->flags
& ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->sample_description_index
);
1264 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_duration
);
1265 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, tfhd
->default_sample_size
);
1266 if( tfhd
->flags
& ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &tfhd
->default_sample_flags
);
1270 static int isom_write_tfdt( lsmash_bs_t
*bs
, isom_box_t
*box
)
1272 isom_tfdt_t
*tfdt
= (isom_tfdt_t
*)box
;
1273 /* Check the version. */
1274 tfdt
->version
= tfdt
->baseMediaDecodeTime
> UINT32_MAX
? 1 : 0;
1276 isom_bs_put_box_common( bs
, tfdt
);
1277 if( tfdt
->version
== 1 )
1278 lsmash_bs_put_be64( bs
, tfdt
->baseMediaDecodeTime
);
1280 lsmash_bs_put_be32( bs
, tfdt
->baseMediaDecodeTime
);
1284 static int isom_write_trun( lsmash_bs_t
*bs
, isom_box_t
*box
)
1286 isom_trun_t
*trun
= (isom_trun_t
*)box
;
1287 isom_bs_put_box_common( bs
, trun
);
1288 lsmash_bs_put_be32( bs
, trun
->sample_count
);
1289 if( trun
->flags
& ISOM_TR_FLAGS_DATA_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, trun
->data_offset
);
1290 if( trun
->flags
& ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &trun
->first_sample_flags
);
1291 if( trun
->optional
)
1292 for( lsmash_entry_t
*entry
= trun
->optional
->head
; entry
; entry
= entry
->next
)
1294 isom_trun_optional_row_t
*data
= (isom_trun_optional_row_t
*)entry
->data
;
1296 return LSMASH_ERR_NAMELESS
;
1297 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_duration
);
1298 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_size
);
1299 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT
) isom_bs_put_sample_flags( bs
, &data
->sample_flags
);
1300 if( trun
->flags
& ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT
) lsmash_bs_put_be32( bs
, data
->sample_composition_time_offset
);
1305 static int isom_write_traf( lsmash_bs_t
*bs
, isom_box_t
*box
)
1307 isom_bs_put_box_common( bs
, box
);
1311 static int isom_write_moof( lsmash_bs_t
*bs
, isom_box_t
*box
)
1313 isom_bs_put_box_common( bs
, box
);
1317 static int isom_write_tfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1319 isom_tfra_t
*tfra
= (isom_tfra_t
*)box
;
1320 isom_bs_put_box_common( bs
, tfra
);
1321 uint32_t temp
= (tfra
->reserved
<< 6)
1322 | (tfra
->length_size_of_traf_num
<< 4)
1323 | (tfra
->length_size_of_trun_num
<< 2)
1324 | tfra
->length_size_of_sample_num
;
1325 lsmash_bs_put_be32( bs
, tfra
->track_ID
);
1326 lsmash_bs_put_be32( bs
, temp
);
1327 lsmash_bs_put_be32( bs
, tfra
->number_of_entry
);
1330 void (*bs_put_funcs
[5])( lsmash_bs_t
*, uint64_t ) =
1332 lsmash_bs_put_byte_from_64
,
1333 lsmash_bs_put_be16_from_64
,
1334 lsmash_bs_put_be24_from_64
,
1335 lsmash_bs_put_be32_from_64
,
1338 void (*bs_put_time
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1339 void (*bs_put_moof_offset
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->version
== 1 ? 4 : 3 ];
1340 void (*bs_put_traf_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_traf_num
];
1341 void (*bs_put_trun_number
) ( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_trun_num
];
1342 void (*bs_put_sample_number
)( lsmash_bs_t
*, uint64_t ) = bs_put_funcs
[ tfra
->length_size_of_sample_num
];
1343 for( lsmash_entry_t
*entry
= tfra
->list
->head
; entry
; entry
= entry
->next
)
1345 isom_tfra_location_time_entry_t
*data
= (isom_tfra_location_time_entry_t
*)entry
->data
;
1347 return LSMASH_ERR_NAMELESS
;
1348 bs_put_time ( bs
, data
->time
);
1349 bs_put_moof_offset ( bs
, data
->moof_offset
);
1350 bs_put_traf_number ( bs
, data
->traf_number
);
1351 bs_put_trun_number ( bs
, data
->trun_number
);
1352 bs_put_sample_number( bs
, data
->sample_number
);
1358 static int isom_write_mfro( lsmash_bs_t
*bs
, isom_box_t
*box
)
1360 isom_mfro_t
*mfro
= (isom_mfro_t
*)box
;
1361 isom_bs_put_box_common( bs
, mfro
);
1362 lsmash_bs_put_be32( bs
, mfro
->length
); /* determined at isom_write_mfra(). */
1366 static int isom_write_mfra( lsmash_bs_t
*bs
, isom_box_t
*box
)
1368 isom_mfra_t
*mfra
= (isom_mfra_t
*)box
;
1370 mfra
->mfro
->length
= mfra
->size
;
1371 isom_bs_put_box_common( bs
, mfra
);
1375 static int isom_write_mdat( lsmash_bs_t
*bs
, isom_box_t
*box
)
1377 isom_mdat_t
*mdat
= (isom_mdat_t
*)box
;
1378 lsmash_file_t
*file
= mdat
->file
;
1379 /* If any fragment, write the Media Data Box all at once. */
1380 if( file
->fragment
)
1382 /* Write the size and type fields of the Media Data Box. */
1383 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ file
->fragment
->pool_size
;
1384 if( mdat
->size
> UINT32_MAX
)
1385 mdat
->size
+= 8; /* large_size */
1386 isom_bs_put_box_common( bs
, mdat
);
1387 /* Write the samples in the current movie fragment. */
1388 for( lsmash_entry_t
*entry
= file
->fragment
->pool
->head
; entry
; entry
= entry
->next
)
1390 isom_sample_pool_t
*pool
= (isom_sample_pool_t
*)entry
->data
;
1392 return LSMASH_ERR_NAMELESS
;
1393 lsmash_bs_put_bytes( bs
, pool
->size
, pool
->data
);
1395 mdat
->media_size
= file
->fragment
->pool_size
;
1398 if( mdat
->manager
& LSMASH_PLACEHOLDER
)
1400 /* Write an incomplete Media Data Box.
1401 * Braindead implementation might check box order and return an error if an expected box does not come the
1402 * next. Placement of eight 0x00 byte string as a simple large_size placeholder passes such silly box order
1403 * checks. This placement is more compatible than placement of a Free Space Box ('free' or 'skip') or a
1404 * Placeholder Atom ('wide') as a large_size placeholder since Media Data Box can store any data and any
1405 * implementation surely do not check what contents are stored in it until taking samples out according to
1406 * chunk offsets, and the placeholder is placed before any chunk offset thus it won't be touched. */
1407 mdat
->pos
= bs
->offset
;
1408 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1409 mdat
->manager
|= LSMASH_INCOMPLETE_BOX
;
1410 mdat
->manager
&= ~LSMASH_PLACEHOLDER
;
1411 isom_bs_put_box_common( bs
, mdat
);
1412 if( mdat
->size
<= UINT32_MAX
)
1413 lsmash_bs_put_be64( bs
, 0x0000000000000000 );
1414 mdat
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8;
1417 assert( !(mdat
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_PLACEHOLDER
)) );
1418 uint64_t actual_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->media_size
;
1419 uint64_t reserved_size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + mdat
->reserved_size
;
1420 if( actual_size
< reserved_size
)
1422 /* Write padding zero bytes until end of this box.
1423 * This code path is invoked when the size of a Media Data Box was reserved. */
1424 mdat
->size
= reserved_size
;
1425 int err
= lsmash_bs_flush_buffer( bs
);
1428 uint64_t padding_size
= reserved_size
- actual_size
;
1429 static const uint8_t zero_bytes
[64] = { 0 };
1430 while( padding_size
> sizeof(zero_bytes
) )
1432 if( (err
= lsmash_bs_write_data( bs
, zero_bytes
, sizeof(zero_bytes
) )) < 0 )
1434 padding_size
-= sizeof(zero_bytes
);
1436 return lsmash_bs_write_data( bs
, zero_bytes
, padding_size
);
1438 if( !bs
->unseekable
)
1440 /* Write the actual size. */
1441 uint64_t current_pos
= bs
->offset
;
1442 mdat
->size
= actual_size
;
1443 lsmash_bs_write_seek( bs
, mdat
->pos
, SEEK_SET
);
1444 isom_bs_put_box_common( bs
, mdat
);
1445 /* isom_write_box() also calls lsmash_bs_flush_buffer() but it must do nothing. */
1446 int ret
= lsmash_bs_flush_buffer( bs
);
1447 lsmash_bs_write_seek( bs
, current_pos
, SEEK_SET
);
1450 return LSMASH_ERR_NAMELESS
;
1453 static int isom_write_ftyp( lsmash_bs_t
*bs
, isom_box_t
*box
)
1455 isom_ftyp_t
*ftyp
= (isom_ftyp_t
*)box
;
1456 if( ftyp
->brand_count
== 0 )
1458 isom_bs_put_box_common( bs
, ftyp
);
1459 lsmash_bs_put_be32( bs
, ftyp
->major_brand
);
1460 lsmash_bs_put_be32( bs
, ftyp
->minor_version
);
1461 for( uint32_t i
= 0; i
< ftyp
->brand_count
; i
++ )
1462 lsmash_bs_put_be32( bs
, ftyp
->compatible_brands
[i
] );
1466 static int isom_write_moov( lsmash_bs_t
*bs
, isom_box_t
*box
)
1468 isom_bs_put_box_common( bs
, box
);
1472 static int isom_write_free( lsmash_bs_t
*bs
, isom_box_t
*box
)
1474 isom_free_t
*skip
= (isom_free_t
*)box
;
1475 isom_bs_put_box_common( bs
, skip
);
1476 if( skip
->data
&& skip
->length
)
1477 lsmash_bs_put_bytes( bs
, skip
->length
, skip
->data
);
1481 static int isom_write_sidx( lsmash_bs_t
*bs
, isom_box_t
*box
)
1483 isom_sidx_t
*sidx
= (isom_sidx_t
*)box
;
1484 /* Check the version. */
1485 if( sidx
->earliest_presentation_time
> UINT32_MAX
1486 || sidx
->first_offset
> UINT32_MAX
)
1491 isom_bs_put_box_common( bs
, sidx
);
1492 lsmash_bs_put_be32( bs
, sidx
->reference_ID
);
1493 lsmash_bs_put_be32( bs
, sidx
->timescale
);
1494 if( sidx
->version
== 0 )
1496 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->earliest_presentation_time
, UINT32_MAX
) );
1497 lsmash_bs_put_be32( bs
, LSMASH_MIN( sidx
->first_offset
, UINT32_MAX
) );
1501 lsmash_bs_put_be64( bs
, sidx
->earliest_presentation_time
);
1502 lsmash_bs_put_be64( bs
, sidx
->first_offset
);
1504 lsmash_bs_put_be16( bs
, sidx
->reserved
);
1505 lsmash_bs_put_be16( bs
, sidx
->reference_count
);
1506 for( lsmash_entry_t
*entry
= sidx
->list
->head
; entry
; entry
= entry
->next
)
1508 isom_sidx_referenced_item_t
*data
= (isom_sidx_referenced_item_t
*)entry
->data
;
1510 return LSMASH_ERR_NAMELESS
;
1512 temp32
= (data
->reference_type
<< 31)
1513 | data
->reference_size
;
1514 lsmash_bs_put_be32( bs
, temp32
);
1515 lsmash_bs_put_be32( bs
, data
->subsegment_duration
);
1516 temp32
= (data
->starts_with_SAP
<< 31)
1517 | (data
->SAP_type
<< 28)
1518 | data
->SAP_delta_time
;
1519 lsmash_bs_put_be32( bs
, temp32
);
1524 int isom_write_box( lsmash_bs_t
*bs
, isom_box_t
*box
)
1527 /* Don't write any incomplete or already written box to a file. */
1528 if( LSMASH_IS_NON_EXISTING_BOX( box
)
1530 || (bs
->stream
&& (box
->manager
& (LSMASH_INCOMPLETE_BOX
| LSMASH_WRITTEN_BOX
))) )
1532 int ret
= box
->write( bs
, box
);
1537 if( (ret
= lsmash_bs_flush_buffer( bs
)) < 0 )
1539 /* Don't write any child box if this box is a placeholder or an incomplete box. */
1540 if( box
->manager
& (LSMASH_PLACEHOLDER
| LSMASH_INCOMPLETE_BOX
) )
1543 box
->manager
|= LSMASH_WRITTEN_BOX
;
1545 return isom_write_children( bs
, box
);
1548 void isom_set_box_writer( isom_box_t
*box
)
1550 if( box
->manager
& LSMASH_BINARY_CODED_BOX
)
1552 box
->write
= isom_write_binary_coded_box
;
1555 else if( box
->manager
& LSMASH_UNKNOWN_BOX
)
1557 box
->write
= isom_write_unknown_box
;
1560 assert( LSMASH_IS_EXISTING_BOX( box
->parent
) );
1561 isom_box_t
*parent
= box
->parent
;
1562 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_STSD
) )
1564 /* OK, this box is a sample entry.
1565 * Here, determine the suitable sample entry writer by media type if possible. */
1566 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t
*)parent
) )
1568 lsmash_media_type media_type
= isom_get_media_type_from_stsd( (isom_stsd_t
*)parent
);
1569 if( media_type
== ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK
)
1570 box
->write
= isom_write_visual_description
;
1571 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK
)
1572 box
->write
= isom_write_audio_description
;
1573 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_HINT_TRACK
)
1574 box
->write
= isom_write_hint_description
;
1575 else if( media_type
== ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK
)
1577 if( lsmash_check_box_type_identical( box
->type
, QT_CODEC_TYPE_TEXT_TEXT
) )
1578 box
->write
= isom_write_qt_text_description
;
1579 else if( lsmash_check_box_type_identical( box
->type
, ISOM_CODEC_TYPE_TX3G_TEXT
) )
1580 box
->write
= isom_write_tx3g_description
;
1585 if( lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_WAVE
) )
1587 if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_FRMA
) ) box
->write
= isom_write_frma
;
1588 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ENDA
) ) box
->write
= isom_write_enda
;
1589 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_MP4A
) ) box
->write
= isom_write_mp4a
;
1590 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_ESDS
) ) box
->write
= isom_write_esds
;
1591 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_CHAN
) ) box
->write
= isom_write_chan
;
1592 else if( lsmash_check_box_type_identical( box
->type
, QT_BOX_TYPE_TERMINATOR
) ) box
->write
= isom_write_terminator
;
1593 else box
->write
= NULL
;
1596 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_TREF
) )
1598 box
->write
= isom_write_track_reference_type
;
1601 static struct box_writer_table_tag
1603 lsmash_box_type_t type
;
1604 isom_extension_writer_t writer_func
;
1605 } box_writer_table
[128] = { { LSMASH_BOX_TYPE_INITIALIZER
, NULL
} };
1606 if( !box_writer_table
[0].writer_func
)
1608 /* Initialize the table. */
1610 #define ADD_BOX_WRITER_TABLE_ELEMENT( type, reader_func ) \
1611 box_writer_table[i++] = (struct box_writer_table_tag){ type, reader_func }
1612 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP
, isom_write_ftyp
);
1613 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP
, isom_write_ftyp
);
1614 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX
, isom_write_sidx
);
1615 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV
, isom_write_moov
);
1616 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD
, isom_write_mvhd
);
1617 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS
, isom_write_iods
);
1618 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB
, isom_write_ctab
);
1619 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS
, isom_write_esds
);
1620 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK
, isom_write_trak
);
1621 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD
, isom_write_tkhd
);
1622 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT
, isom_write_tapt
);
1623 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF
, isom_write_clef
);
1624 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_PROF
, isom_write_prof
);
1625 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF
, isom_write_enof
);
1626 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS
, isom_write_edts
);
1627 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST
, isom_write_elst
);
1628 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF
, isom_write_tref
);
1629 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA
, isom_write_mdia
);
1630 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD
, isom_write_mdhd
);
1631 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR
, isom_write_hdlr
);
1632 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF
, isom_write_minf
);
1633 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD
, isom_write_vmhd
);
1634 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD
, isom_write_smhd
);
1635 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD
, isom_write_hmhd
);
1636 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD
, isom_write_nmhd
);
1637 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD
, isom_write_gmhd
);
1638 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN
, isom_write_gmin
);
1639 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT
, isom_write_text
);
1640 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF
, isom_write_dinf
);
1641 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF
, isom_write_dref
);
1642 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL
, isom_write_url
);
1643 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL
, isom_write_stbl
);
1644 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD
, isom_write_stsd
);
1645 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT
, isom_write_btrt
);
1646 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TIMS
, isom_write_tims
);
1647 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSRO
, isom_write_tsro
);
1648 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSSY
, isom_write_tssy
);
1649 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR
, isom_write_colr
);
1650 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_COLR
, isom_write_colr
);
1651 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP
, isom_write_clap
);
1652 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP
, isom_write_pasp
);
1653 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL
, isom_write_glbl
);
1654 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA
, isom_write_gama
);
1655 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL
, isom_write_fiel
);
1656 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC
, isom_write_cspc
);
1657 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT
, isom_write_sgbt
);
1658 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL
, isom_write_stsl
);
1659 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE
, isom_write_wave
);
1660 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MP4A
, isom_write_mp4a
);
1661 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN
, isom_write_chan
);
1662 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB
, isom_write_ftab
);
1663 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS
, isom_write_stts
);
1664 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS
, isom_write_ctts
);
1665 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG
, isom_write_cslg
);
1666 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS
, isom_write_stss
);
1667 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_STPS
, isom_write_stps
);
1668 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP
, isom_write_sdtp
);
1669 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC
, isom_write_stsc
);
1670 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ
, isom_write_stsz
);
1671 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2
, isom_write_stz2
);
1672 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO
, isom_write_stco
);
1673 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64
, isom_write_stco
);
1674 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD
, isom_write_sgpd
);
1675 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP
, isom_write_sbgp
);
1676 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA
, isom_write_udta
);
1677 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HNTI
, isom_write_hnti
);
1678 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_RTP
, isom_write_rtp
);
1679 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDP
, isom_write_sdp
);
1680 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL
, isom_write_chpl
);
1681 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX
, isom_write_mvex
);
1682 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD
, isom_write_mehd
);
1683 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX
, isom_write_trex
);
1684 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF
, isom_write_moof
);
1685 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD
, isom_write_mfhd
);
1686 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF
, isom_write_traf
);
1687 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD
, isom_write_tfhd
);
1688 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT
, isom_write_tfdt
);
1689 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN
, isom_write_trun
);
1690 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT
, isom_write_mdat
);
1691 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE
, isom_write_free
);
1692 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP
, isom_write_free
);
1693 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_META
, isom_write_meta
);
1694 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_META
, isom_write_meta
);
1695 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST
, isom_write_ilst
);
1696 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ILST
, isom_write_ilst
);
1697 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA
, isom_write_mfra
);
1698 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA
, isom_write_tfra
);
1699 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO
, isom_write_mfro
);
1700 ADD_BOX_WRITER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED
, NULL
);
1701 #undef ADD_BOX_WRITER_TABLE_ELEMENT
1703 for( int i
= 0; box_writer_table
[i
].writer_func
; i
++ )
1704 if( lsmash_check_box_type_identical( box
->type
, box_writer_table
[i
].type
) )
1706 box
->write
= box_writer_table
[i
].writer_func
;
1709 if( lsmash_check_box_type_identical( parent
->type
, ISOM_BOX_TYPE_ILST
)
1710 || lsmash_check_box_type_identical( parent
->type
, QT_BOX_TYPE_ILST
) )
1712 box
->write
= isom_write_metaitem
;
1715 if( lsmash_check_box_type_identical( parent
->parent
->type
, ISOM_BOX_TYPE_ILST
) )
1717 if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_MEAN
) )
1718 box
->write
= isom_write_mean
;
1719 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_NAME
) )
1720 box
->write
= isom_write_name
;
1721 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_DATA
) )
1722 box
->write
= isom_write_data
;
1726 else if( lsmash_check_box_type_identical( box
->type
, ISOM_BOX_TYPE_CPRT
) )
1728 /* Avoid confusing udta.cprt with ilst.cprt. */
1729 box
->write
= isom_write_cprt
;
1732 box
->write
= isom_write_unknown_box
;