AMR importer: Apply refined bytestream reader.
[L-SMASH.git] / core / write.c
blob28f9049fd760fc0796bdc1d6d4a4674fcf739e49
1 /*****************************************************************************
2 * write.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2014 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 */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <inttypes.h>
29 #include "box.h"
30 #include "write.h"
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( !child )
42 continue;
43 int ret = isom_write_box( bs, child );
44 if( ret < 0 )
45 return ret;
47 return 0;
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 );
53 return 0;
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 );
63 return 0;
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;
72 if( 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 );
87 return 0;
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( (tkhd->file && !tkhd->file->undefined_64_ver)
95 && (tkhd->creation_time > UINT32_MAX
96 || tkhd->modification_time > UINT32_MAX
97 || tkhd->duration > UINT32_MAX) )
98 tkhd->version = 1;
99 else
100 tkhd->version = 0;
101 /* Write. */
102 isom_bs_put_box_common( bs, tkhd );
103 if( tkhd->version )
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 );
111 else
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 );
129 return 0;
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 );
138 return 0;
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 );
147 return 0;
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 );
156 return 0;
159 static int isom_write_tapt( lsmash_bs_t *bs, isom_box_t *box )
161 isom_bs_put_box_common( bs, box );
162 return 0;
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 )
170 return 0;
171 /* Check the version. */
172 elst->version = 0;
173 if( elst->file && !elst->file->undefined_64_ver )
174 for( lsmash_entry_t *entry = elst->list->head; entry; entry = entry->next )
176 isom_elst_entry_t *data = (isom_elst_entry_t *)entry->data;
177 if( !data )
178 return -1;
179 if( data->segment_duration > UINT32_MAX
180 || data->media_time > INT32_MAX
181 || data->media_time < INT32_MIN )
182 elst->version = 1;
184 /* Remember to rewrite entries. */
185 if( elst->file->fragment && !elst->file->bs->unseekable )
186 elst->pos = elst->file->bs->written;
187 /* Write. */
188 isom_bs_put_box_common( bs, elst );
189 lsmash_bs_put_be32( bs, elst->list->entry_count );
190 for( lsmash_entry_t *entry = elst->list->head; entry; entry = entry->next )
192 isom_elst_entry_t *data = (isom_elst_entry_t *)entry->data;
193 if( elst->version )
195 lsmash_bs_put_be64( bs, data->segment_duration );
196 lsmash_bs_put_be64( bs, data->media_time );
198 else
200 lsmash_bs_put_be32( bs, LSMASH_MIN( data->segment_duration, UINT32_MAX ) );
201 lsmash_bs_put_be32( bs, data->media_time < 0 ? (uint32_t)data->media_time : LSMASH_MIN( data->media_time, INT32_MAX ) );
203 lsmash_bs_put_be32( bs, data->media_rate );
205 return 0;
208 static int isom_write_edts( lsmash_bs_t *bs, isom_box_t *box )
210 isom_bs_put_box_common( bs, box );
211 return 0;
214 static int isom_write_tref( lsmash_bs_t *bs, isom_box_t *box )
216 isom_bs_put_box_common( bs, box );
217 return 0;
220 static int isom_write_track_reference_type( lsmash_bs_t *bs, isom_box_t *box )
222 isom_tref_type_t *ref = (isom_tref_type_t *)box;
223 isom_bs_put_box_common( bs, ref );
224 for( uint32_t i = 0; i < ref->ref_count; i++ )
225 lsmash_bs_put_be32( bs, ref->track_ID[i] );
226 return 0;
229 static int isom_write_mdhd( lsmash_bs_t *bs, isom_box_t *box )
231 isom_mdhd_t *mdhd = (isom_mdhd_t *)box;
232 /* Check the version. */
233 if( (mdhd->file && !mdhd->file->undefined_64_ver)
234 && (mdhd->creation_time > UINT32_MAX
235 || mdhd->modification_time > UINT32_MAX
236 || mdhd->duration > UINT32_MAX) )
237 mdhd->version = 1;
238 else
239 mdhd->version = 0;
240 /* Write. */
241 isom_bs_put_box_common( bs, mdhd );
242 if( mdhd->version )
244 lsmash_bs_put_be64( bs, mdhd->creation_time );
245 lsmash_bs_put_be64( bs, mdhd->modification_time );
246 lsmash_bs_put_be32( bs, mdhd->timescale );
247 lsmash_bs_put_be64( bs, mdhd->duration );
249 else
251 lsmash_bs_put_be32( bs, LSMASH_MIN( mdhd->creation_time, UINT32_MAX ) );
252 lsmash_bs_put_be32( bs, LSMASH_MIN( mdhd->modification_time, UINT32_MAX ) );
253 lsmash_bs_put_be32( bs, mdhd->timescale );
254 lsmash_bs_put_be32( bs, LSMASH_MIN( mdhd->duration, UINT32_MAX ) );
256 lsmash_bs_put_be16( bs, mdhd->language );
257 lsmash_bs_put_be16( bs, mdhd->quality );
258 return 0;
261 static int isom_write_hdlr( lsmash_bs_t *bs, isom_box_t *box )
263 isom_hdlr_t *hdlr = (isom_hdlr_t *)box;
264 isom_bs_put_box_common( bs, hdlr );
265 lsmash_bs_put_be32( bs, hdlr->componentType );
266 lsmash_bs_put_be32( bs, hdlr->componentSubtype );
267 lsmash_bs_put_be32( bs, hdlr->componentManufacturer );
268 lsmash_bs_put_be32( bs, hdlr->componentFlags );
269 lsmash_bs_put_be32( bs, hdlr->componentFlagsMask );
270 lsmash_bs_put_bytes( bs, hdlr->componentName_length, hdlr->componentName );
271 return 0;
274 static int isom_write_vmhd( lsmash_bs_t *bs, isom_box_t *box )
276 isom_vmhd_t *vmhd = (isom_vmhd_t *)box;
277 isom_bs_put_box_common( bs, vmhd );
278 lsmash_bs_put_be16( bs, vmhd->graphicsmode );
279 for( uint32_t i = 0; i < 3; i++ )
280 lsmash_bs_put_be16( bs, vmhd->opcolor[i] );
281 return 0;
284 static int isom_write_smhd( lsmash_bs_t *bs, isom_box_t *box )
286 isom_smhd_t *smhd = (isom_smhd_t *)box;
287 isom_bs_put_box_common( bs, smhd );
288 lsmash_bs_put_be16( bs, smhd->balance );
289 lsmash_bs_put_be16( bs, smhd->reserved );
290 return 0;
293 static int isom_write_hmhd( lsmash_bs_t *bs, isom_box_t *box )
295 isom_hmhd_t *hmhd = (isom_hmhd_t *)box;
296 isom_bs_put_box_common( bs, hmhd );
297 lsmash_bs_put_be16( bs, hmhd->maxPDUsize );
298 lsmash_bs_put_be16( bs, hmhd->avgPDUsize );
299 lsmash_bs_put_be32( bs, hmhd->maxbitrate );
300 lsmash_bs_put_be32( bs, hmhd->avgbitrate );
301 lsmash_bs_put_be32( bs, hmhd->reserved );
302 return 0;
305 static int isom_write_nmhd( lsmash_bs_t *bs, isom_box_t *box )
307 isom_nmhd_t *nmhd = (isom_nmhd_t *)box;
308 isom_bs_put_box_common( bs, nmhd );
309 return 0;
312 static int isom_write_gmin( lsmash_bs_t *bs, isom_box_t *box )
314 isom_gmin_t *gmin = (isom_gmin_t *)box;
315 isom_bs_put_box_common( bs, gmin );
316 lsmash_bs_put_be16( bs, gmin->graphicsmode );
317 for( uint32_t i = 0; i < 3; i++ )
318 lsmash_bs_put_be16( bs, gmin->opcolor[i] );
319 lsmash_bs_put_be16( bs, gmin->balance );
320 lsmash_bs_put_be16( bs, gmin->reserved );
321 return 0;
324 static int isom_write_text( lsmash_bs_t *bs, isom_box_t *box )
326 isom_text_t *text = (isom_text_t *)box;
327 isom_bs_put_box_common( bs, text );
328 for( uint32_t i = 0; i < 9; i++ )
329 lsmash_bs_put_be32( bs, text->matrix[i] );
330 return 0;
333 static int isom_write_gmhd( lsmash_bs_t *bs, isom_box_t *box )
335 isom_bs_put_box_common( bs, box );
336 return 0;
339 static int isom_write_dref( lsmash_bs_t *bs, isom_box_t *box )
341 isom_dref_t *dref = (isom_dref_t *)box;
342 isom_bs_put_box_common( bs, dref );
343 lsmash_bs_put_be32( bs, dref->list.entry_count );
344 return 0;
347 static int isom_write_url( lsmash_bs_t *bs, isom_box_t *box )
349 isom_dref_entry_t *url = (isom_dref_entry_t *)box;
350 isom_bs_put_box_common( bs, url );
351 lsmash_bs_put_bytes( bs, url->location_length, url->location );
352 return 0;
355 static int isom_write_dinf( lsmash_bs_t *bs, isom_box_t *box )
357 isom_bs_put_box_common( bs, box );
358 return 0;
361 static int isom_write_pasp( lsmash_bs_t *bs, isom_box_t *box )
363 isom_pasp_t *pasp = (isom_pasp_t *)box;
364 isom_bs_put_box_common( bs, pasp );
365 lsmash_bs_put_be32( bs, pasp->hSpacing );
366 lsmash_bs_put_be32( bs, pasp->vSpacing );
367 return 0;
370 static int isom_write_clap( lsmash_bs_t *bs, isom_box_t *box )
372 isom_clap_t *clap = (isom_clap_t *)box;
373 isom_bs_put_box_common( bs, clap );
374 lsmash_bs_put_be32( bs, clap->cleanApertureWidthN );
375 lsmash_bs_put_be32( bs, clap->cleanApertureWidthD );
376 lsmash_bs_put_be32( bs, clap->cleanApertureHeightN );
377 lsmash_bs_put_be32( bs, clap->cleanApertureHeightD );
378 lsmash_bs_put_be32( bs, clap->horizOffN );
379 lsmash_bs_put_be32( bs, clap->horizOffD );
380 lsmash_bs_put_be32( bs, clap->vertOffN );
381 lsmash_bs_put_be32( bs, clap->vertOffD );
382 return 0;
385 static int isom_write_colr( lsmash_bs_t *bs, isom_box_t *box )
387 isom_colr_t *colr = (isom_colr_t *)box;
388 if( colr->color_parameter_type != ISOM_COLOR_PARAMETER_TYPE_NCLX
389 && colr->color_parameter_type != QT_COLOR_PARAMETER_TYPE_NCLC )
390 return 0;
391 isom_bs_put_box_common( bs, colr );
392 lsmash_bs_put_be32( bs, colr->color_parameter_type );
393 lsmash_bs_put_be16( bs, colr->primaries_index );
394 lsmash_bs_put_be16( bs, colr->transfer_function_index );
395 lsmash_bs_put_be16( bs, colr->matrix_index );
396 if( colr->color_parameter_type == ISOM_COLOR_PARAMETER_TYPE_NCLX )
397 lsmash_bs_put_byte( bs, (colr->full_range_flag << 7) | colr->reserved );
398 return 0;
401 static int isom_write_gama( lsmash_bs_t *bs, isom_box_t *box )
403 isom_gama_t *gama = (isom_gama_t *)box;
404 if( !gama->parent )
405 return 0;
406 /* Note: 'gama' box is superseded by 'colr' box.
407 * Therefore, writers of QTFF should never write both 'colr' and 'gama' box into an Image Description. */
408 if( isom_get_extension_box_format( &((isom_visual_entry_t *)gama->parent)->extensions, QT_BOX_TYPE_COLR ) )
409 return 0;
410 isom_bs_put_box_common( bs, gama );
411 lsmash_bs_put_be32( bs, gama->level );
412 return 0;
415 static int isom_write_fiel( lsmash_bs_t *bs, isom_box_t *box )
417 isom_fiel_t *fiel = (isom_fiel_t *)box;
418 isom_bs_put_box_common( bs, fiel );
419 lsmash_bs_put_byte( bs, fiel->fields );
420 lsmash_bs_put_byte( bs, fiel->detail );
421 return 0;
424 static int isom_write_cspc( lsmash_bs_t *bs, isom_box_t *box )
426 isom_cspc_t *cspc = (isom_cspc_t *)box;
427 isom_bs_put_box_common( bs, cspc );
428 lsmash_bs_put_be32( bs, cspc->pixel_format );
429 return 0;
432 static int isom_write_sgbt( lsmash_bs_t *bs, isom_box_t *box )
434 isom_sgbt_t *sgbt = (isom_sgbt_t *)box;
435 isom_bs_put_box_common( bs, sgbt );
436 lsmash_bs_put_byte( bs, sgbt->significantBits );
437 return 0;
440 static int isom_write_stsl( lsmash_bs_t *bs, isom_box_t *box )
442 isom_stsl_t *stsl = (isom_stsl_t *)box;
443 isom_bs_put_box_common( bs, stsl );
444 lsmash_bs_put_byte( bs, stsl->constraint_flag );
445 lsmash_bs_put_byte( bs, stsl->scale_method );
446 lsmash_bs_put_be16( bs, stsl->display_center_x );
447 lsmash_bs_put_be16( bs, stsl->display_center_y );
448 return 0;
451 static int isom_write_esds( lsmash_bs_t *bs, isom_box_t *box )
453 isom_esds_t *esds = (isom_esds_t *)box;
454 isom_bs_put_box_common( bs, esds );
455 mp4sys_update_descriptor_size( esds->ES );
456 return mp4sys_write_descriptor( bs, esds->ES );
459 static int isom_write_btrt( lsmash_bs_t *bs, isom_box_t *box )
461 isom_btrt_t *btrt = (isom_btrt_t *)box;
462 isom_bs_put_box_common( bs, btrt );
463 lsmash_bs_put_be32( bs, btrt->bufferSizeDB );
464 lsmash_bs_put_be32( bs, btrt->maxBitrate );
465 lsmash_bs_put_be32( bs, btrt->avgBitrate );
466 return 0;
469 static int isom_write_glbl( lsmash_bs_t *bs, isom_box_t *box )
471 isom_glbl_t *glbl = (isom_glbl_t *)box;
472 isom_bs_put_box_common( bs, glbl );
473 if( glbl->header_data && glbl->header_size )
474 lsmash_bs_put_bytes( bs, glbl->header_size, glbl->header_data );
475 return 0;
478 static int isom_write_frma( lsmash_bs_t *bs, isom_box_t *box )
480 isom_frma_t *frma = (isom_frma_t *)box;
481 isom_bs_put_box_common( bs, frma );
482 lsmash_bs_put_be32( bs, frma->data_format );
483 return 0;
486 static int isom_write_enda( lsmash_bs_t *bs, isom_box_t *box )
488 isom_enda_t *enda = (isom_enda_t *)box;
489 isom_bs_put_box_common( bs, enda );
490 lsmash_bs_put_be16( bs, enda->littleEndian );
491 return 0;
494 static int isom_write_mp4a( lsmash_bs_t *bs, isom_box_t *box )
496 isom_mp4a_t *mp4a = (isom_mp4a_t *)box;
497 isom_bs_put_box_common( bs, mp4a );
498 lsmash_bs_put_be32( bs, mp4a->unknown );
499 return 0;
502 static int isom_write_chan( lsmash_bs_t *bs, isom_box_t *box )
504 isom_chan_t *chan = (isom_chan_t *)box;
505 isom_bs_put_box_common( bs, chan );
506 lsmash_bs_put_be32( bs, chan->channelLayoutTag );
507 lsmash_bs_put_be32( bs, chan->channelBitmap );
508 lsmash_bs_put_be32( bs, chan->numberChannelDescriptions );
509 if( chan->channelDescriptions )
510 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
512 isom_channel_description_t *channelDescriptions = (isom_channel_description_t *)(&chan->channelDescriptions[i]);
513 if( !channelDescriptions )
514 return -1;
515 lsmash_bs_put_be32( bs, channelDescriptions->channelLabel );
516 lsmash_bs_put_be32( bs, channelDescriptions->channelFlags );
517 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[0] );
518 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[1] );
519 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[2] );
521 return 0;
524 static int isom_write_terminator( lsmash_bs_t *bs, isom_box_t *box )
526 isom_bs_put_box_common( bs, box );
527 return 0;
530 static int isom_write_wave( lsmash_bs_t *bs, isom_box_t *box )
532 isom_bs_put_box_common( bs, box );
533 return 0;
536 static int isom_write_visual_description( lsmash_bs_t *bs, isom_box_t *box )
538 isom_visual_entry_t *data = (isom_visual_entry_t *)box;
539 if( !data )
540 return -1;
541 isom_bs_put_box_common( bs, data );
542 lsmash_bs_put_bytes( bs, 6, data->reserved );
543 lsmash_bs_put_be16( bs, data->data_reference_index );
544 lsmash_bs_put_be16( bs, data->version );
545 lsmash_bs_put_be16( bs, data->revision_level );
546 lsmash_bs_put_be32( bs, data->vendor );
547 lsmash_bs_put_be32( bs, data->temporalQuality );
548 lsmash_bs_put_be32( bs, data->spatialQuality );
549 lsmash_bs_put_be16( bs, data->width );
550 lsmash_bs_put_be16( bs, data->height );
551 lsmash_bs_put_be32( bs, data->horizresolution );
552 lsmash_bs_put_be32( bs, data->vertresolution );
553 lsmash_bs_put_be32( bs, data->dataSize );
554 lsmash_bs_put_be16( bs, data->frame_count );
555 lsmash_bs_put_bytes( bs, 32, data->compressorname );
556 lsmash_bs_put_be16( bs, data->depth );
557 lsmash_bs_put_be16( bs, data->color_table_ID );
558 if( data->color_table_ID == 0 )
559 isom_bs_put_qt_color_table( bs, &data->color_table );
560 return 0;
563 static int isom_write_audio_description( lsmash_bs_t *bs, isom_box_t *box )
565 isom_audio_entry_t *data = (isom_audio_entry_t *)box;
566 if( !data )
567 return -1;
568 isom_bs_put_box_common( bs, data );
569 lsmash_bs_put_bytes( bs, 6, data->reserved );
570 lsmash_bs_put_be16( bs, data->data_reference_index );
571 lsmash_bs_put_be16( bs, data->version );
572 lsmash_bs_put_be16( bs, data->revision_level );
573 lsmash_bs_put_be32( bs, data->vendor );
574 lsmash_bs_put_be16( bs, data->channelcount );
575 lsmash_bs_put_be16( bs, data->samplesize );
576 lsmash_bs_put_be16( bs, data->compression_ID );
577 lsmash_bs_put_be16( bs, data->packet_size );
578 lsmash_bs_put_be32( bs, data->samplerate );
579 if( data->version == 1 )
581 lsmash_bs_put_be32( bs, data->samplesPerPacket );
582 lsmash_bs_put_be32( bs, data->bytesPerPacket );
583 lsmash_bs_put_be32( bs, data->bytesPerFrame );
584 lsmash_bs_put_be32( bs, data->bytesPerSample );
586 else if( data->version == 2 )
588 lsmash_bs_put_be32( bs, data->sizeOfStructOnly );
589 lsmash_bs_put_be64( bs, data->audioSampleRate );
590 lsmash_bs_put_be32( bs, data->numAudioChannels );
591 lsmash_bs_put_be32( bs, data->always7F000000 );
592 lsmash_bs_put_be32( bs, data->constBitsPerChannel );
593 lsmash_bs_put_be32( bs, data->formatSpecificFlags );
594 lsmash_bs_put_be32( bs, data->constBytesPerAudioPacket );
595 lsmash_bs_put_be32( bs, data->constLPCMFramesPerAudioPacket );
597 return 0;
600 #if 0
601 static int isom_write_hint_description( lsmash_bs_t *bs, lsmash_entry_t *entry )
603 isom_hint_entry_t *data = (isom_hint_entry_t *)entry->data;
604 if( !data )
605 return -1;
606 isom_bs_put_box_common( bs, data );
607 lsmash_bs_put_bytes( bs, 6, data->reserved );
608 lsmash_bs_put_be16( bs, data->data_reference_index );
609 if( data->data && data->data_length )
610 lsmash_bs_put_bytes( bs, data->data_length, data->data );
611 return 0;
614 static int isom_write_metadata_description( lsmash_bs_t *bs, lsmash_entry_t *entry )
616 isom_metadata_entry_t *data = (isom_metadata_entry_t *)entry->data;
617 if( !data )
618 return -1;
619 isom_bs_put_box_common( bs, data );
620 lsmash_bs_put_bytes( bs, 6, data->reserved );
621 lsmash_bs_put_be16( bs, data->data_reference_index );
622 return 0;
624 #endif
626 static int isom_write_qt_text_description( lsmash_bs_t *bs, isom_box_t *box )
628 isom_qt_text_entry_t *data = (isom_qt_text_entry_t *)box;
629 if( !data )
630 return -1;
631 isom_bs_put_box_common( bs, data );
632 lsmash_bs_put_bytes( bs, 6, data->reserved );
633 lsmash_bs_put_be16( bs, data->data_reference_index );
634 lsmash_bs_put_be32( bs, data->displayFlags );
635 lsmash_bs_put_be32( bs, data->textJustification );
636 for( uint32_t i = 0; i < 3; i++ )
637 lsmash_bs_put_be16( bs, data->bgColor[i] );
638 lsmash_bs_put_be16( bs, data->top );
639 lsmash_bs_put_be16( bs, data->left );
640 lsmash_bs_put_be16( bs, data->bottom );
641 lsmash_bs_put_be16( bs, data->right );
642 lsmash_bs_put_be32( bs, data->scrpStartChar );
643 lsmash_bs_put_be16( bs, data->scrpHeight );
644 lsmash_bs_put_be16( bs, data->scrpAscent );
645 lsmash_bs_put_be16( bs, data->scrpFont );
646 lsmash_bs_put_be16( bs, data->scrpFace );
647 lsmash_bs_put_be16( bs, data->scrpSize );
648 for( uint32_t i = 0; i < 3; i++ )
649 lsmash_bs_put_be16( bs, data->scrpColor[i] );
650 lsmash_bs_put_byte( bs, data->font_name_length );
651 if( data->font_name && data->font_name_length )
652 lsmash_bs_put_bytes( bs, data->font_name_length, data->font_name );
653 return 0;
656 static int isom_write_ftab( lsmash_bs_t *bs, isom_box_t *box )
658 isom_ftab_t *ftab = (isom_ftab_t *)box;
659 assert( ftab->list );
660 isom_bs_put_box_common( bs, ftab );
661 lsmash_bs_put_be16( bs, ftab->list->entry_count );
662 for( lsmash_entry_t *entry = ftab->list->head; entry; entry = entry->next )
664 isom_font_record_t *data = (isom_font_record_t *)entry->data;
665 if( !data )
666 return -1;
667 lsmash_bs_put_be16( bs, data->font_ID );
668 lsmash_bs_put_byte( bs, data->font_name_length );
669 if( data->font_name && data->font_name_length )
670 lsmash_bs_put_bytes( bs, data->font_name_length, data->font_name );
672 return 0;
675 static int isom_write_tx3g_description( lsmash_bs_t *bs, isom_box_t *box )
677 isom_tx3g_entry_t *data = (isom_tx3g_entry_t *)box;
678 if( !data )
679 return -1;
680 isom_bs_put_box_common( bs, data );
681 lsmash_bs_put_bytes( bs, 6, data->reserved );
682 lsmash_bs_put_be16( bs, data->data_reference_index );
683 lsmash_bs_put_be32( bs, data->displayFlags );
684 lsmash_bs_put_byte( bs, data->horizontal_justification );
685 lsmash_bs_put_byte( bs, data->vertical_justification );
686 for( uint32_t i = 0; i < 4; i++ )
687 lsmash_bs_put_byte( bs, data->background_color_rgba[i] );
688 lsmash_bs_put_be16( bs, data->top );
689 lsmash_bs_put_be16( bs, data->left );
690 lsmash_bs_put_be16( bs, data->bottom );
691 lsmash_bs_put_be16( bs, data->right );
692 lsmash_bs_put_be16( bs, data->startChar );
693 lsmash_bs_put_be16( bs, data->endChar );
694 lsmash_bs_put_be16( bs, data->font_ID );
695 lsmash_bs_put_byte( bs, data->face_style_flags );
696 lsmash_bs_put_byte( bs, data->font_size );
697 for( uint32_t i = 0; i < 4; i++ )
698 lsmash_bs_put_byte( bs, data->text_color_rgba[i] );
699 return 0;
702 static int isom_write_stsd( lsmash_bs_t *bs, isom_box_t *box )
704 isom_stsd_t *stsd = (isom_stsd_t *)box;
705 isom_bs_put_box_common( bs, stsd );
706 lsmash_bs_put_be32( bs, stsd->list.entry_count );
707 return 0;
710 static int isom_write_stts( lsmash_bs_t *bs, isom_box_t *box )
712 isom_stts_t *stts = (isom_stts_t *)box;
713 assert( stts->list );
714 isom_bs_put_box_common( bs, stts );
715 lsmash_bs_put_be32( bs, stts->list->entry_count );
716 for( lsmash_entry_t *entry = stts->list->head; entry; entry = entry->next )
718 isom_stts_entry_t *data = (isom_stts_entry_t *)entry->data;
719 if( !data )
720 return -1;
721 lsmash_bs_put_be32( bs, data->sample_count );
722 lsmash_bs_put_be32( bs, data->sample_delta );
724 return 0;
727 static int isom_write_ctts( lsmash_bs_t *bs, isom_box_t *box )
729 isom_ctts_t *ctts = (isom_ctts_t *)box;
730 assert( ctts->list );
731 isom_bs_put_box_common( bs, ctts );
732 lsmash_bs_put_be32( bs, ctts->list->entry_count );
733 for( lsmash_entry_t *entry = ctts->list->head; entry; entry = entry->next )
735 isom_ctts_entry_t *data = (isom_ctts_entry_t *)entry->data;
736 if( !data )
737 return -1;
738 lsmash_bs_put_be32( bs, data->sample_count );
739 lsmash_bs_put_be32( bs, data->sample_offset );
741 return 0;
744 static int isom_write_cslg( lsmash_bs_t *bs, isom_box_t *box )
746 isom_cslg_t *cslg = (isom_cslg_t *)box;
747 isom_bs_put_box_common( bs, cslg );
748 lsmash_bs_put_be32( bs, cslg->compositionToDTSShift );
749 lsmash_bs_put_be32( bs, cslg->leastDecodeToDisplayDelta );
750 lsmash_bs_put_be32( bs, cslg->greatestDecodeToDisplayDelta );
751 lsmash_bs_put_be32( bs, cslg->compositionStartTime );
752 lsmash_bs_put_be32( bs, cslg->compositionEndTime );
753 return 0;
756 static int isom_write_stsz( lsmash_bs_t *bs, isom_box_t *box )
758 isom_stsz_t *stsz = (isom_stsz_t *)box;
759 isom_bs_put_box_common( bs, stsz );
760 lsmash_bs_put_be32( bs, stsz->sample_size );
761 lsmash_bs_put_be32( bs, stsz->sample_count );
762 if( stsz->sample_size == 0 && stsz->list )
763 for( lsmash_entry_t *entry = stsz->list->head; entry; entry = entry->next )
765 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
766 if( !data )
767 return -1;
768 lsmash_bs_put_be32( bs, data->entry_size );
770 return 0;
773 static int isom_write_stss( lsmash_bs_t *bs, isom_box_t *box )
775 isom_stss_t *stss = (isom_stss_t *)box;
776 assert( stss->list );
777 isom_bs_put_box_common( bs, stss );
778 lsmash_bs_put_be32( bs, stss->list->entry_count );
779 for( lsmash_entry_t *entry = stss->list->head; entry; entry = entry->next )
781 isom_stss_entry_t *data = (isom_stss_entry_t *)entry->data;
782 if( !data )
783 return -1;
784 lsmash_bs_put_be32( bs, data->sample_number );
786 return 0;
789 static int isom_write_stps( lsmash_bs_t *bs, isom_box_t *box )
791 isom_stps_t *stps = (isom_stps_t *)box;
792 assert( stps->list );
793 isom_bs_put_box_common( bs, stps );
794 lsmash_bs_put_be32( bs, stps->list->entry_count );
795 for( lsmash_entry_t *entry = stps->list->head; entry; entry = entry->next )
797 isom_stps_entry_t *data = (isom_stps_entry_t *)entry->data;
798 if( !data )
799 return -1;
800 lsmash_bs_put_be32( bs, data->sample_number );
802 return 0;
805 static int isom_write_sdtp( lsmash_bs_t *bs, isom_box_t *box )
807 isom_sdtp_t *sdtp = (isom_sdtp_t *)box;
808 assert( sdtp->list );
809 isom_bs_put_box_common( bs, sdtp );
810 for( lsmash_entry_t *entry = sdtp->list->head; entry; entry = entry->next )
812 isom_sdtp_entry_t *data = (isom_sdtp_entry_t *)entry->data;
813 if( !data )
814 return -1;
815 uint8_t temp = (data->is_leading << 6)
816 | (data->sample_depends_on << 4)
817 | (data->sample_is_depended_on << 2)
818 | data->sample_has_redundancy;
819 lsmash_bs_put_byte( bs, temp );
821 return 0;
824 static int isom_write_stsc( lsmash_bs_t *bs, isom_box_t *box )
826 isom_stsc_t *stsc = (isom_stsc_t *)box;
827 assert( stsc->list );
828 isom_bs_put_box_common( bs, stsc );
829 lsmash_bs_put_be32( bs, stsc->list->entry_count );
830 for( lsmash_entry_t *entry = stsc->list->head; entry; entry = entry->next )
832 isom_stsc_entry_t *data = (isom_stsc_entry_t *)entry->data;
833 if( !data )
834 return -1;
835 lsmash_bs_put_be32( bs, data->first_chunk );
836 lsmash_bs_put_be32( bs, data->samples_per_chunk );
837 lsmash_bs_put_be32( bs, data->sample_description_index );
839 return 0;
842 static int isom_write_co64( lsmash_bs_t *bs, isom_box_t *box )
844 isom_stco_t *co64 = (isom_stco_t *)box;
845 assert( co64->list );
846 isom_bs_put_box_common( bs, co64 );
847 lsmash_bs_put_be32( bs, co64->list->entry_count );
848 for( lsmash_entry_t *entry = co64->list->head; entry; entry = entry->next )
850 isom_co64_entry_t *data = (isom_co64_entry_t *)entry->data;
851 if( !data )
852 return -1;
853 lsmash_bs_put_be64( bs, data->chunk_offset );
855 return 0;
858 static int isom_write_stco( lsmash_bs_t *bs, isom_box_t *box )
860 isom_stco_t *stco = (isom_stco_t *)box;
861 if( stco->large_presentation )
862 return isom_write_co64( bs, box );
863 assert( stco->list );
864 isom_bs_put_box_common( bs, stco );
865 lsmash_bs_put_be32( bs, stco->list->entry_count );
866 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
868 isom_stco_entry_t *data = (isom_stco_entry_t *)entry->data;
869 if( !data )
870 return -1;
871 lsmash_bs_put_be32( bs, data->chunk_offset );
873 return 0;
876 static int isom_write_sgpd( lsmash_bs_t *bs, isom_box_t *box )
878 isom_sgpd_t *sgpd = (isom_sgpd_t *)box;
879 assert( sgpd->list );
880 isom_bs_put_box_common( bs, sgpd );
881 lsmash_bs_put_be32( bs, sgpd->grouping_type );
882 if( sgpd->version == 1 )
883 lsmash_bs_put_be32( bs, sgpd->default_length );
884 lsmash_bs_put_be32( bs, sgpd->list->entry_count );
885 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
887 if( !entry->data )
888 return -1;
889 switch( sgpd->grouping_type )
891 case ISOM_GROUP_TYPE_RAP :
893 isom_rap_entry_t *rap = (isom_rap_entry_t *)entry->data;
894 uint8_t temp = (rap->num_leading_samples_known << 7)
895 | rap->num_leading_samples;
896 lsmash_bs_put_byte( bs, temp );
897 break;
899 case ISOM_GROUP_TYPE_ROLL :
900 case ISOM_GROUP_TYPE_PROL :
901 lsmash_bs_put_be16( bs, ((isom_roll_entry_t *)entry->data)->roll_distance );
902 break;
903 default :
904 /* We don't consider other grouping types currently. */
905 // if( sgpd->version == 1 && !sgpd->default_length )
906 // lsmash_bs_put_be32( bs, ((isom_sgpd_t *)entry->data)->description_length );
907 break;
910 return 0;
913 static int isom_write_sbgp( lsmash_bs_t *bs, isom_box_t *box )
915 isom_sbgp_t *sbgp = (isom_sbgp_t *)box;
916 assert( sbgp->list );
917 isom_bs_put_box_common( bs, sbgp );
918 lsmash_bs_put_be32( bs, sbgp->grouping_type );
919 if( sbgp->version == 1 )
920 lsmash_bs_put_be32( bs, sbgp->grouping_type_parameter );
921 lsmash_bs_put_be32( bs, sbgp->list->entry_count );
922 for( lsmash_entry_t *entry = sbgp->list->head; entry; entry = entry->next )
924 isom_group_assignment_entry_t *data = (isom_group_assignment_entry_t *)entry->data;
925 if( !data )
926 return -1;
927 lsmash_bs_put_be32( bs, data->sample_count );
928 lsmash_bs_put_be32( bs, data->group_description_index );
930 return 0;
933 static int isom_write_stbl( lsmash_bs_t *bs, isom_box_t *box )
935 isom_bs_put_box_common( bs, box );
936 return 0;
939 static int isom_write_minf( lsmash_bs_t *bs, isom_box_t *box )
941 isom_bs_put_box_common( bs, box );
942 return 0;
945 static int isom_write_mdia( lsmash_bs_t *bs, isom_box_t *box )
947 isom_bs_put_box_common( bs, box );
948 return 0;
951 static int isom_write_chpl( lsmash_bs_t *bs, isom_box_t *box )
953 isom_chpl_t *chpl = (isom_chpl_t *)box;
954 assert( chpl->list );
955 isom_bs_put_box_common( bs, chpl );
956 if( chpl->version == 1 )
958 lsmash_bs_put_byte( bs, chpl->unknown );
959 lsmash_bs_put_be32( bs, chpl->list->entry_count );
961 else /* chpl->version == 0 */
962 lsmash_bs_put_byte( bs, (uint8_t)chpl->list->entry_count );
963 for( lsmash_entry_t *entry = chpl->list->head; entry; entry = entry->next )
965 isom_chpl_entry_t *data = (isom_chpl_entry_t *)entry->data;
966 if( !data )
967 return -1;
968 lsmash_bs_put_be64( bs, data->start_time );
969 lsmash_bs_put_byte( bs, data->chapter_name_length );
970 lsmash_bs_put_bytes( bs, data->chapter_name_length, data->chapter_name );
972 return 0;
975 static int isom_write_mean( lsmash_bs_t *bs, isom_box_t *box )
977 isom_mean_t *mean = (isom_mean_t *)box;
978 isom_bs_put_box_common( bs, mean );
979 if( mean->meaning_string && mean->meaning_string_length )
980 lsmash_bs_put_bytes( bs, mean->meaning_string_length, mean->meaning_string );
981 return 0;
984 static int isom_write_name( lsmash_bs_t *bs, isom_box_t *box )
986 isom_name_t *name = (isom_name_t *)box;
987 isom_bs_put_box_common( bs, name );
988 if( name->name && name->name_length )
989 lsmash_bs_put_bytes( bs, name->name_length, name->name );
990 return 0;
993 static int isom_write_data( lsmash_bs_t *bs, isom_box_t *box )
995 isom_data_t *data = (isom_data_t *)box;
996 isom_bs_put_box_common( bs, data );
997 lsmash_bs_put_be16( bs, data->reserved );
998 lsmash_bs_put_byte( bs, data->type_set_identifier );
999 lsmash_bs_put_byte( bs, data->type_code );
1000 lsmash_bs_put_be32( bs, data->the_locale );
1001 if( data->value && data->value_length )
1002 lsmash_bs_put_bytes( bs, data->value_length, data->value );
1003 return 0;
1006 static int isom_write_metaitem( lsmash_bs_t *bs, isom_box_t *box )
1008 isom_bs_put_box_common( bs, box );
1009 return 0;
1012 static int isom_write_ilst( lsmash_bs_t *bs, isom_box_t *box )
1014 isom_bs_put_box_common( bs, box );
1015 return 0;
1018 static int isom_write_meta( lsmash_bs_t *bs, isom_box_t *box )
1020 isom_bs_put_box_common( bs, box );
1021 return 0;
1024 static int isom_write_cprt( lsmash_bs_t *bs, isom_box_t *box )
1026 isom_cprt_t *cprt = (isom_cprt_t *)box;
1027 isom_bs_put_box_common( bs, cprt );
1028 lsmash_bs_put_be16( bs, cprt->language );
1029 lsmash_bs_put_bytes( bs, cprt->notice_length, cprt->notice );
1030 return 0;
1033 static int isom_write_udta( lsmash_bs_t *bs, isom_box_t *box )
1035 isom_bs_put_box_common( bs, box );
1036 return 0;
1039 static int isom_write_trak( lsmash_bs_t *bs, isom_box_t *box )
1041 isom_bs_put_box_common( bs, box );
1042 return 0;
1045 static int isom_write_iods( lsmash_bs_t *bs, isom_box_t *box )
1047 isom_iods_t *iods = (isom_iods_t *)box;
1048 isom_bs_put_box_common( bs, iods );
1049 mp4sys_update_descriptor_size( iods->OD );
1050 return mp4sys_write_descriptor( bs, iods->OD );
1053 static int isom_write_mvhd( lsmash_bs_t *bs, isom_box_t *box )
1055 isom_mvhd_t *mvhd = (isom_mvhd_t *)box;
1056 /* Check the version. */
1057 if( (mvhd->file && !mvhd->file->undefined_64_ver)
1058 && (mvhd->creation_time > UINT32_MAX
1059 || mvhd->modification_time > UINT32_MAX
1060 || mvhd->duration > UINT32_MAX) )
1061 mvhd->version = 1;
1062 else
1063 mvhd->version = 0;
1064 /* Write. */
1065 isom_bs_put_box_common( bs, mvhd );
1066 if( mvhd->version )
1068 lsmash_bs_put_be64( bs, mvhd->creation_time );
1069 lsmash_bs_put_be64( bs, mvhd->modification_time );
1070 lsmash_bs_put_be32( bs, mvhd->timescale );
1071 lsmash_bs_put_be64( bs, mvhd->duration );
1073 else
1075 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->creation_time, UINT32_MAX ) );
1076 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->modification_time, UINT32_MAX ) );
1077 lsmash_bs_put_be32( bs, mvhd->timescale );
1078 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->duration, UINT32_MAX ) );
1080 lsmash_bs_put_be32( bs, mvhd->rate );
1081 lsmash_bs_put_be16( bs, mvhd->volume );
1082 lsmash_bs_put_be16( bs, mvhd->reserved );
1083 lsmash_bs_put_be32( bs, mvhd->preferredLong[0] );
1084 lsmash_bs_put_be32( bs, mvhd->preferredLong[1] );
1085 for( int i = 0; i < 9; i++ )
1086 lsmash_bs_put_be32( bs, mvhd->matrix[i] );
1087 lsmash_bs_put_be32( bs, mvhd->previewTime );
1088 lsmash_bs_put_be32( bs, mvhd->previewDuration );
1089 lsmash_bs_put_be32( bs, mvhd->posterTime );
1090 lsmash_bs_put_be32( bs, mvhd->selectionTime );
1091 lsmash_bs_put_be32( bs, mvhd->selectionDuration );
1092 lsmash_bs_put_be32( bs, mvhd->currentTime );
1093 lsmash_bs_put_be32( bs, mvhd->next_track_ID );
1094 return 0;
1097 static void isom_bs_put_sample_flags( lsmash_bs_t *bs, isom_sample_flags_t *flags )
1099 uint32_t temp = (flags->reserved << 28)
1100 | (flags->is_leading << 26)
1101 | (flags->sample_depends_on << 24)
1102 | (flags->sample_is_depended_on << 22)
1103 | (flags->sample_has_redundancy << 20)
1104 | (flags->sample_padding_value << 17)
1105 | (flags->sample_is_non_sync_sample << 16)
1106 | flags->sample_degradation_priority;
1107 lsmash_bs_put_be32( bs, temp );
1110 static int isom_write_mehd( lsmash_bs_t *bs, isom_box_t *box )
1112 if( box->manager & LSMASH_PLACEHOLDER )
1114 /* Movie Extends Header Box is not written immediately.
1115 * It's done after finishing all movie fragments.
1116 * The following will be overwritten by Movie Extends Header Box.
1117 * We use version 1 Movie Extends Header Box since it causes extra 4 bytes region
1118 * we cannot replace with empty Free Space Box as we place version 0 one. */
1119 box->pos = box->file->bs->written;
1120 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + 12 );
1121 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_FREE.fourcc );
1122 lsmash_bs_put_be32( bs, 0 );
1123 lsmash_bs_put_be64( bs, 0 );
1125 else
1127 isom_mehd_t *mehd = (isom_mehd_t *)box;
1128 //mehd->version = mehd->fragment_duration > UINT32_MAX ? 1 : 0;
1129 isom_bs_put_box_common( bs, mehd );
1130 if( mehd->version == 1 )
1131 lsmash_bs_put_be64( bs, mehd->fragment_duration );
1132 else
1133 lsmash_bs_put_be32( bs, LSMASH_MIN( mehd->fragment_duration, UINT32_MAX ) );
1135 return 0;
1138 static int isom_write_trex( lsmash_bs_t *bs, isom_box_t *box )
1140 isom_trex_t *trex = (isom_trex_t *)box;
1141 isom_bs_put_box_common( bs, trex );
1142 lsmash_bs_put_be32( bs, trex->track_ID );
1143 lsmash_bs_put_be32( bs, trex->default_sample_description_index );
1144 lsmash_bs_put_be32( bs, trex->default_sample_duration );
1145 lsmash_bs_put_be32( bs, trex->default_sample_size );
1146 isom_bs_put_sample_flags( bs, &trex->default_sample_flags );
1147 return 0;
1150 static int isom_write_mvex( lsmash_bs_t *bs, isom_box_t *box )
1152 isom_bs_put_box_common( bs, box );
1153 return 0;
1156 static int isom_write_mfhd( lsmash_bs_t *bs, isom_box_t *box )
1158 isom_mfhd_t *mfhd = (isom_mfhd_t *)box;
1159 isom_bs_put_box_common( bs, mfhd );
1160 lsmash_bs_put_be32( bs, mfhd->sequence_number );
1161 return 0;
1164 static int isom_write_tfhd( lsmash_bs_t *bs, isom_box_t *box )
1166 isom_tfhd_t *tfhd = (isom_tfhd_t *)box;
1167 isom_bs_put_box_common( bs, tfhd );
1168 lsmash_bs_put_be32( bs, tfhd->track_ID );
1169 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) lsmash_bs_put_be64( bs, tfhd->base_data_offset );
1170 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) lsmash_bs_put_be32( bs, tfhd->sample_description_index );
1171 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) lsmash_bs_put_be32( bs, tfhd->default_sample_duration );
1172 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) lsmash_bs_put_be32( bs, tfhd->default_sample_size );
1173 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &tfhd->default_sample_flags );
1174 return 0;
1177 static int isom_write_tfdt( lsmash_bs_t *bs, isom_box_t *box )
1179 isom_tfdt_t *tfdt = (isom_tfdt_t *)box;
1180 /* Check the version. */
1181 tfdt->version = tfdt->baseMediaDecodeTime > UINT32_MAX ? 1 : 0;
1182 /* Write. */
1183 isom_bs_put_box_common( bs, tfdt );
1184 if( tfdt->version == 1 )
1185 lsmash_bs_put_be64( bs, tfdt->baseMediaDecodeTime );
1186 else
1187 lsmash_bs_put_be32( bs, tfdt->baseMediaDecodeTime );
1188 return 0;
1191 static int isom_write_trun( lsmash_bs_t *bs, isom_box_t *box )
1193 isom_trun_t *trun = (isom_trun_t *)box;
1194 isom_bs_put_box_common( bs, trun );
1195 lsmash_bs_put_be32( bs, trun->sample_count );
1196 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) lsmash_bs_put_be32( bs, trun->data_offset );
1197 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &trun->first_sample_flags );
1198 if( trun->optional )
1199 for( lsmash_entry_t *entry = trun->optional->head; entry; entry = entry->next )
1201 isom_trun_optional_row_t *data = (isom_trun_optional_row_t *)entry->data;
1202 if( !data )
1203 return -1;
1204 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) lsmash_bs_put_be32( bs, data->sample_duration );
1205 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) lsmash_bs_put_be32( bs, data->sample_size );
1206 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &data->sample_flags );
1207 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) lsmash_bs_put_be32( bs, data->sample_composition_time_offset );
1209 return 0;
1212 static int isom_write_traf( lsmash_bs_t *bs, isom_box_t *box )
1214 isom_bs_put_box_common( bs, box );
1215 return 0;
1218 static int isom_write_moof( lsmash_bs_t *bs, isom_box_t *box )
1220 isom_bs_put_box_common( bs, box );
1221 return 0;
1224 static int isom_write_tfra( lsmash_bs_t *bs, isom_box_t *box )
1226 isom_tfra_t *tfra = (isom_tfra_t *)box;
1227 isom_bs_put_box_common( bs, tfra );
1228 uint32_t temp = (tfra->reserved << 6)
1229 | (tfra->length_size_of_traf_num << 4)
1230 | (tfra->length_size_of_trun_num << 2)
1231 | tfra->length_size_of_sample_num;
1232 lsmash_bs_put_be32( bs, tfra->track_ID );
1233 lsmash_bs_put_be32( bs, temp );
1234 lsmash_bs_put_be32( bs, tfra->number_of_entry );
1235 if( tfra->list )
1237 void (*bs_put_funcs[5])( lsmash_bs_t *, uint64_t ) =
1239 lsmash_bs_put_byte_from_64,
1240 lsmash_bs_put_be16_from_64,
1241 lsmash_bs_put_be24_from_64,
1242 lsmash_bs_put_be32_from_64,
1243 lsmash_bs_put_be64
1245 void (*bs_put_time) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->version == 1 ? 4 : 3 ];
1246 void (*bs_put_moof_offset) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->version == 1 ? 4 : 3 ];
1247 void (*bs_put_traf_number) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_traf_num ];
1248 void (*bs_put_trun_number) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_trun_num ];
1249 void (*bs_put_sample_number)( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_sample_num ];
1250 for( lsmash_entry_t *entry = tfra->list->head; entry; entry = entry->next )
1252 isom_tfra_location_time_entry_t *data = (isom_tfra_location_time_entry_t *)entry->data;
1253 if( !data )
1254 return -1;
1255 bs_put_time ( bs, data->time );
1256 bs_put_moof_offset ( bs, data->moof_offset );
1257 bs_put_traf_number ( bs, data->traf_number );
1258 bs_put_trun_number ( bs, data->trun_number );
1259 bs_put_sample_number( bs, data->sample_number );
1262 return 0;
1265 static int isom_write_mfro( lsmash_bs_t *bs, isom_box_t *box )
1267 isom_mfro_t *mfro = (isom_mfro_t *)box;
1268 isom_bs_put_box_common( bs, mfro );
1269 lsmash_bs_put_be32( bs, mfro->length ); /* determined at isom_write_mfra(). */
1270 return 0;
1273 static int isom_write_mfra( lsmash_bs_t *bs, isom_box_t *box )
1275 isom_mfra_t *mfra = (isom_mfra_t *)box;
1276 if( mfra->mfro )
1277 mfra->mfro->length = mfra->size;
1278 isom_bs_put_box_common( bs, mfra );
1279 return 0;
1282 static int isom_write_mdat( lsmash_bs_t *bs, isom_box_t *box )
1284 isom_mdat_t *mdat = (isom_mdat_t *)box;
1285 lsmash_file_t *file = mdat->file;
1286 /* If any fragment, write the Media Data Box all at once. */
1287 if( file->fragment )
1289 /* Write the size and type fields of the Media Data Box. */
1290 mdat->size = ISOM_BASEBOX_COMMON_SIZE + file->fragment->pool_size;
1291 if( mdat->size > UINT32_MAX )
1292 mdat->size += 8; /* large_size */
1293 isom_bs_put_box_common( bs, mdat );
1294 /* Write the samples in the current movie fragment. */
1295 for( lsmash_entry_t *entry = file->fragment->pool->head; entry; entry = entry->next )
1297 isom_sample_pool_t *pool = (isom_sample_pool_t *)entry->data;
1298 if( !pool )
1299 return -1;
1300 lsmash_bs_put_bytes( bs, pool->size, pool->data );
1302 mdat->media_size = file->fragment->pool_size;
1303 return 0;
1305 if( mdat->manager & LSMASH_PLACEHOLDER )
1307 /* Write the placeholder for large size. */
1308 if( !file->free && !isom_add_free( file ) )
1309 return -1;
1310 isom_free_t *skip = file->free;
1311 skip->pos = bs->offset;
1312 skip->size = ISOM_BASEBOX_COMMON_SIZE;
1313 skip->manager |= LSMASH_PLACEHOLDER;
1314 if( isom_write_box( bs, (isom_box_t *)skip ) < 0 )
1315 return -1;
1316 /* Write an incomplete Media Data Box. */
1317 mdat->pos = bs->offset;
1318 mdat->size = ISOM_BASEBOX_COMMON_SIZE;
1319 mdat->manager |= LSMASH_INCOMPLETE_BOX;
1320 mdat->manager &= ~LSMASH_PLACEHOLDER;
1321 isom_bs_put_box_common( bs, mdat );
1322 return 0;
1324 if( !bs->unseekable )
1326 /* Write the actual size. */
1327 uint64_t current_pos = bs->offset;
1328 mdat->size = ISOM_BASEBOX_COMMON_SIZE + mdat->media_size;
1329 if( mdat->size > UINT32_MAX )
1331 /* The placeholder is overwritten by the Media Data Box. */
1332 assert( file->free );
1333 mdat->pos = file->free->pos;
1334 mdat->size += file->free->size;
1335 isom_remove_box_by_itself( file->free );
1337 lsmash_bs_write_seek( bs, mdat->pos, SEEK_SET );
1338 isom_bs_put_box_common( bs, mdat );
1339 /* isom_write_box() also calls lsmash_bs_flush_buffer() but it must do nothing. */
1340 int ret = lsmash_bs_flush_buffer( bs );
1341 lsmash_bs_write_seek( bs, current_pos, SEEK_SET );
1342 return ret;
1344 return -1;
1347 static int isom_write_ftyp( lsmash_bs_t *bs, isom_box_t *box )
1349 isom_ftyp_t *ftyp = (isom_ftyp_t *)box;
1350 if( ftyp->brand_count == 0 )
1351 return 0;
1352 isom_bs_put_box_common( bs, ftyp );
1353 lsmash_bs_put_be32( bs, ftyp->major_brand );
1354 lsmash_bs_put_be32( bs, ftyp->minor_version );
1355 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
1356 lsmash_bs_put_be32( bs, ftyp->compatible_brands[i] );
1357 return 0;
1360 static int isom_write_moov( lsmash_bs_t *bs, isom_box_t *box )
1362 isom_bs_put_box_common( bs, box );
1363 return 0;
1366 static int isom_write_free( lsmash_bs_t *bs, isom_box_t *box )
1368 isom_free_t *skip = (isom_free_t *)box;
1369 isom_bs_put_box_common( bs, skip );
1370 if( skip->data && skip->length )
1371 lsmash_bs_put_bytes( bs, skip->length, skip->data );
1372 return 0;
1375 static int isom_write_sidx( lsmash_bs_t *bs, isom_box_t *box )
1377 isom_sidx_t *sidx = (isom_sidx_t *)box;
1378 /* Check the version. */
1379 if( sidx->earliest_presentation_time > UINT32_MAX
1380 || sidx->first_offset > UINT32_MAX )
1381 sidx->version = 1;
1382 else
1383 sidx->version = 0;
1384 /* Write. */
1385 isom_bs_put_box_common( bs, sidx );
1386 lsmash_bs_put_be32( bs, sidx->reference_ID );
1387 lsmash_bs_put_be32( bs, sidx->timescale );
1388 if( sidx->version == 0 )
1390 lsmash_bs_put_be32( bs, LSMASH_MIN( sidx->earliest_presentation_time, UINT32_MAX ) );
1391 lsmash_bs_put_be32( bs, LSMASH_MIN( sidx->first_offset, UINT32_MAX ) );
1393 else
1395 lsmash_bs_put_be64( bs, sidx->earliest_presentation_time );
1396 lsmash_bs_put_be64( bs, sidx->first_offset );
1398 lsmash_bs_put_be16( bs, sidx->reserved );
1399 lsmash_bs_put_be16( bs, sidx->reference_count );
1400 for( lsmash_entry_t *entry = sidx->list->head; entry; entry = entry->next )
1402 isom_sidx_referenced_item_t *data = (isom_sidx_referenced_item_t *)entry->data;
1403 if( !data )
1404 return -1;
1405 uint32_t temp32;
1406 temp32 = (data->reference_type << 31)
1407 | data->reference_size;
1408 lsmash_bs_put_be32( bs, temp32 );
1409 lsmash_bs_put_be32( bs, data->subsegment_duration );
1410 temp32 = (data->starts_with_SAP << 31)
1411 | (data->SAP_type << 28)
1412 | data->SAP_delta_time;
1413 lsmash_bs_put_be32( bs, temp32 );
1415 return 0;
1418 int isom_write_box( lsmash_bs_t *bs, isom_box_t *box )
1420 assert( bs );
1421 /* Don't write any incomplete or already written box to a file. */
1422 if( !box || !box->write
1423 || (bs->stream && (box->manager & (LSMASH_INCOMPLETE_BOX | LSMASH_WRITTEN_BOX))) )
1424 return 0;
1425 if( box->write( bs, box ) < 0 )
1426 return -1;
1427 if( bs->stream )
1429 if( lsmash_bs_flush_buffer( bs ) < 0 )
1430 return -1;
1431 /* Don't write any child box if this box is a placeholder or an incomplete box. */
1432 if( box->manager & (LSMASH_PLACEHOLDER | LSMASH_INCOMPLETE_BOX) )
1433 return 0;
1434 else
1435 box->manager |= LSMASH_WRITTEN_BOX;
1437 return isom_write_children( bs, box );
1440 void isom_set_box_writer( isom_box_t *box )
1442 if( box->manager & LSMASH_BINARY_CODED_BOX )
1444 box->write = isom_write_binary_coded_box;
1445 return;
1447 else if( box->manager & LSMASH_UNKNOWN_BOX )
1449 box->write = isom_write_unknown_box;
1450 return;
1452 assert( box->parent );
1453 isom_box_t *parent = box->parent;
1454 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1456 /* Check whether CODEC is RAW Video/Audio encapsulated in QTFF. */
1457 if( parent->parent && parent->parent->parent )
1459 isom_minf_t *minf = (isom_minf_t *)parent->parent->parent;
1460 if( minf->vmhd )
1461 box->write = isom_write_visual_description;
1462 else if( minf->smhd )
1463 box->write = isom_write_audio_description;
1464 if( box->write )
1465 return;
1467 if( lsmash_check_box_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1468 box->write = isom_write_qt_text_description;
1469 else if( lsmash_check_box_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1470 box->write = isom_write_tx3g_description;
1471 if( box->write )
1472 return;
1474 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1476 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FRMA ) ) box->write = isom_write_frma;
1477 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ENDA ) ) box->write = isom_write_enda;
1478 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_MP4A ) ) box->write = isom_write_mp4a;
1479 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ESDS ) ) box->write = isom_write_esds;
1480 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CHAN ) ) box->write = isom_write_chan;
1481 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_TERMINATOR ) ) box->write = isom_write_terminator;
1482 else box->write = NULL;
1483 return;
1485 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
1487 box->write = isom_write_track_reference_type;
1488 return;
1490 static struct box_writer_table_tag
1492 lsmash_box_type_t type;
1493 isom_extension_writer_t writer_func;
1494 } box_writer_table[128] = { { LSMASH_BOX_TYPE_INITIALIZER, NULL } };
1495 if( !box_writer_table[0].writer_func )
1497 /* Initialize the table. */
1498 int i = 0;
1499 #define ADD_BOX_WRITER_TABLE_ELEMENT( type, reader_func ) \
1500 box_writer_table[i++] = (struct box_writer_table_tag){ type, reader_func }
1501 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, isom_write_ftyp );
1502 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, isom_write_ftyp );
1503 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, isom_write_sidx );
1504 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, isom_write_moov );
1505 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, isom_write_mvhd );
1506 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, isom_write_iods );
1507 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, isom_write_ctab );
1508 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, isom_write_esds );
1509 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, isom_write_trak );
1510 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, isom_write_tkhd );
1511 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, isom_write_tapt );
1512 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, isom_write_clef );
1513 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, isom_write_prof );
1514 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, isom_write_enof );
1515 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, isom_write_edts );
1516 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, isom_write_elst );
1517 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, isom_write_tref );
1518 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, isom_write_mdia );
1519 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, isom_write_mdhd );
1520 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, isom_write_hdlr );
1521 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, isom_write_minf );
1522 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, isom_write_vmhd );
1523 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, isom_write_smhd );
1524 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, isom_write_hmhd );
1525 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, isom_write_nmhd );
1526 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, isom_write_gmhd );
1527 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, isom_write_gmin );
1528 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, isom_write_text );
1529 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, isom_write_dinf );
1530 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, isom_write_dref );
1531 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL, isom_write_url );
1532 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, isom_write_stbl );
1533 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, isom_write_stsd );
1534 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, isom_write_btrt );
1535 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, isom_write_colr );
1536 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_COLR, isom_write_colr );
1537 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, isom_write_clap );
1538 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, isom_write_pasp );
1539 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, isom_write_glbl );
1540 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, isom_write_gama );
1541 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, isom_write_fiel );
1542 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, isom_write_cspc );
1543 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, isom_write_sgbt );
1544 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, isom_write_stsl );
1545 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, isom_write_wave );
1546 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MP4A, isom_write_mp4a );
1547 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, isom_write_chan );
1548 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, isom_write_ftab );
1549 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, isom_write_stts );
1550 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, isom_write_ctts );
1551 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, isom_write_cslg );
1552 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, isom_write_stss );
1553 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, isom_write_stps );
1554 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, isom_write_sdtp );
1555 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, isom_write_stsc );
1556 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, isom_write_stsz );
1557 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, isom_write_stco );
1558 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, isom_write_stco );
1559 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, isom_write_sgpd );
1560 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, isom_write_sbgp );
1561 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, isom_write_udta );
1562 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, isom_write_chpl );
1563 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, isom_write_mvex );
1564 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, isom_write_mehd );
1565 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, isom_write_trex );
1566 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, isom_write_moof );
1567 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, isom_write_mfhd );
1568 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, isom_write_traf );
1569 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, isom_write_tfhd );
1570 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, isom_write_tfdt );
1571 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, isom_write_trun );
1572 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, isom_write_mdat );
1573 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, isom_write_free );
1574 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, isom_write_free );
1575 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_META, isom_write_meta );
1576 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_META, isom_write_meta );
1577 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST, isom_write_ilst );
1578 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ILST, isom_write_ilst );
1579 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, isom_write_mfra );
1580 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, isom_write_tfra );
1581 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, isom_write_mfro );
1582 ADD_BOX_WRITER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
1583 #undef ADD_BOX_WRITER_TABLE_ELEMENT
1585 for( int i = 0; box_writer_table[i].writer_func; i++ )
1586 if( lsmash_check_box_type_identical( box->type, box_writer_table[i].type ) )
1588 box->write = box_writer_table[i].writer_func;
1589 return;
1591 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
1592 || lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
1594 box->write = isom_write_metaitem;
1595 return;
1597 if( parent->parent && lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_ILST ) )
1599 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_MEAN ) )
1600 box->write = isom_write_mean;
1601 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_NAME ) )
1602 box->write = isom_write_name;
1603 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_DATA ) )
1604 box->write = isom_write_data;
1605 if( box->write )
1606 return;
1608 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_CPRT ) )
1610 /* Avoid confusing udta.cprt with ilst.cprt. */
1611 box->write = isom_write_cprt;
1612 return;
1614 box->write = isom_write_unknown_box;