write: Fix type size for mdcv luminance
[L-SMASH.git] / core / write.c
blob4f5c4f4a9a060fed7a29acef0d368926943b609f
1 /*****************************************************************************
2 * write.c
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 */
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( LSMASH_IS_NON_EXISTING_BOX( 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( (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) )
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 elst->version = 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;
180 if( !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 )
185 elst->version = 1;
187 /* Remember to rewrite entries. */
188 if( file->fragment && !file->bs->unseekable )
189 elst->pos = file->bs->written;
191 /* Write. */
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;
197 if( elst->version )
199 lsmash_bs_put_be64( bs, data->segment_duration );
200 lsmash_bs_put_be64( bs, data->media_time );
202 else
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 );
209 return 0;
212 static int isom_write_edts( lsmash_bs_t *bs, isom_box_t *box )
214 isom_bs_put_box_common( bs, box );
215 return 0;
218 static int isom_write_tref( lsmash_bs_t *bs, isom_box_t *box )
220 isom_bs_put_box_common( bs, box );
221 return 0;
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] );
230 return 0;
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) )
241 mdhd->version = 1;
242 else
243 mdhd->version = 0;
244 /* Write. */
245 isom_bs_put_box_common( bs, mdhd );
246 if( mdhd->version )
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 );
253 else
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 );
262 return 0;
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 );
275 return 0;
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] );
285 return 0;
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 );
294 return 0;
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 );
306 return 0;
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 );
313 return 0;
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 );
325 return 0;
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] );
334 return 0;
337 static int isom_write_gmhd( lsmash_bs_t *bs, isom_box_t *box )
339 isom_bs_put_box_common( bs, box );
340 return 0;
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 );
348 return 0;
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 );
356 return 0;
359 static int isom_write_dinf( lsmash_bs_t *bs, isom_box_t *box )
361 isom_bs_put_box_common( bs, box );
362 return 0;
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 );
371 return 0;
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 );
386 return 0;
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 )
394 return 0;
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 );
402 return 0;
405 static int isom_write_gama( lsmash_bs_t *bs, isom_box_t *box )
407 isom_gama_t *gama = (isom_gama_t *)box;
408 if( !gama->parent )
409 return 0;
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 ) )
413 return 0;
414 isom_bs_put_box_common( bs, gama );
415 lsmash_bs_put_be32( bs, gama->level );
416 return 0;
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 );
425 return 0;
428 static int isom_write_clli( lsmash_bs_t *bs, isom_box_t *box )
430 isom_clli_t *clli = (isom_clli_t *)box;
431 isom_bs_put_box_common( bs, clli );
432 lsmash_bs_put_be16( bs, clli->max_content_light_level );
433 lsmash_bs_put_be16( bs, clli->max_pic_average_light_level );
434 return 0;
437 static int isom_write_mdcv( lsmash_bs_t *bs, isom_box_t *box )
439 isom_mdcv_t *mdcv = (isom_mdcv_t *)box;
440 isom_bs_put_box_common( bs, mdcv );
441 lsmash_bs_put_be16( bs, mdcv->display_primaries_g_x );
442 lsmash_bs_put_be16( bs, mdcv->display_primaries_g_y );
443 lsmash_bs_put_be16( bs, mdcv->display_primaries_b_x );
444 lsmash_bs_put_be16( bs, mdcv->display_primaries_b_y );
445 lsmash_bs_put_be16( bs, mdcv->display_primaries_r_x );
446 lsmash_bs_put_be16( bs, mdcv->display_primaries_r_y );
447 lsmash_bs_put_be16( bs, mdcv->white_point_x );
448 lsmash_bs_put_be16( bs, mdcv->white_point_y );
449 lsmash_bs_put_be32( bs, mdcv->max_display_mastering_luminance );
450 lsmash_bs_put_be32( bs, mdcv->min_display_mastering_luminance );
451 return 0;
454 static int isom_write_cspc( lsmash_bs_t *bs, isom_box_t *box )
456 isom_cspc_t *cspc = (isom_cspc_t *)box;
457 isom_bs_put_box_common( bs, cspc );
458 lsmash_bs_put_be32( bs, cspc->pixel_format );
459 return 0;
462 static int isom_write_sgbt( lsmash_bs_t *bs, isom_box_t *box )
464 isom_sgbt_t *sgbt = (isom_sgbt_t *)box;
465 isom_bs_put_box_common( bs, sgbt );
466 lsmash_bs_put_byte( bs, sgbt->significantBits );
467 return 0;
470 static int isom_write_stsl( lsmash_bs_t *bs, isom_box_t *box )
472 isom_stsl_t *stsl = (isom_stsl_t *)box;
473 isom_bs_put_box_common( bs, stsl );
474 lsmash_bs_put_byte( bs, stsl->constraint_flag );
475 lsmash_bs_put_byte( bs, stsl->scale_method );
476 lsmash_bs_put_be16( bs, stsl->display_center_x );
477 lsmash_bs_put_be16( bs, stsl->display_center_y );
478 return 0;
481 static int isom_write_esds( lsmash_bs_t *bs, isom_box_t *box )
483 isom_esds_t *esds = (isom_esds_t *)box;
484 isom_bs_put_box_common( bs, esds );
485 mp4sys_update_descriptor_size( esds->ES );
486 return mp4sys_write_descriptor( bs, esds->ES );
489 static int isom_write_btrt( lsmash_bs_t *bs, isom_box_t *box )
491 isom_btrt_t *btrt = (isom_btrt_t *)box;
492 isom_bs_put_box_common( bs, btrt );
493 lsmash_bs_put_be32( bs, btrt->bufferSizeDB );
494 lsmash_bs_put_be32( bs, btrt->maxBitrate );
495 lsmash_bs_put_be32( bs, btrt->avgBitrate );
496 return 0;
499 static int isom_write_tims( lsmash_bs_t *bs, isom_box_t *box )
501 isom_tims_t *tims = (isom_tims_t *)box;
502 isom_bs_put_box_common( bs, tims );
503 lsmash_bs_put_be32( bs, tims->timescale );
504 return 0;
507 static int isom_write_tsro( lsmash_bs_t *bs, isom_box_t *box )
509 isom_tsro_t *tsro = (isom_tsro_t *)box;
510 isom_bs_put_box_common( bs, tsro );
511 lsmash_bs_put_be32( bs, tsro->offset );
512 return 0;
515 static int isom_write_tssy( lsmash_bs_t *bs, isom_box_t *box )
517 isom_tssy_t *tssy = (isom_tssy_t *)box;
518 isom_bs_put_box_common( bs, tssy );
519 uint8_t data = 0;
520 data = tssy->reserved << 2;
521 data |= tssy->timestamp_sync;
522 lsmash_bs_put_byte( bs, data );
523 return 0;
526 static int isom_write_glbl( lsmash_bs_t *bs, isom_box_t *box )
528 isom_glbl_t *glbl = (isom_glbl_t *)box;
529 isom_bs_put_box_common( bs, glbl );
530 if( glbl->header_data && glbl->header_size )
531 lsmash_bs_put_bytes( bs, glbl->header_size, glbl->header_data );
532 return 0;
535 static int isom_write_frma( lsmash_bs_t *bs, isom_box_t *box )
537 isom_frma_t *frma = (isom_frma_t *)box;
538 isom_bs_put_box_common( bs, frma );
539 lsmash_bs_put_be32( bs, frma->data_format );
540 return 0;
543 static int isom_write_enda( lsmash_bs_t *bs, isom_box_t *box )
545 isom_enda_t *enda = (isom_enda_t *)box;
546 isom_bs_put_box_common( bs, enda );
547 lsmash_bs_put_be16( bs, enda->littleEndian );
548 return 0;
551 static int isom_write_mp4a( lsmash_bs_t *bs, isom_box_t *box )
553 isom_mp4a_t *mp4a = (isom_mp4a_t *)box;
554 isom_bs_put_box_common( bs, mp4a );
555 lsmash_bs_put_be32( bs, mp4a->unknown );
556 return 0;
559 static int isom_write_chan( lsmash_bs_t *bs, isom_box_t *box )
561 isom_chan_t *chan = (isom_chan_t *)box;
562 isom_bs_put_box_common( bs, chan );
563 lsmash_bs_put_be32( bs, chan->channelLayoutTag );
564 lsmash_bs_put_be32( bs, chan->channelBitmap );
565 lsmash_bs_put_be32( bs, chan->numberChannelDescriptions );
566 if( chan->channelDescriptions )
567 for( uint32_t i = 0; i < chan->numberChannelDescriptions; i++ )
569 isom_channel_description_t *channelDescriptions = (isom_channel_description_t *)(&chan->channelDescriptions[i]);
570 lsmash_bs_put_be32( bs, channelDescriptions->channelLabel );
571 lsmash_bs_put_be32( bs, channelDescriptions->channelFlags );
572 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[0] );
573 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[1] );
574 lsmash_bs_put_be32( bs, channelDescriptions->coordinates[2] );
576 return 0;
579 static int isom_write_terminator( lsmash_bs_t *bs, isom_box_t *box )
581 isom_bs_put_box_common( bs, box );
582 return 0;
585 static int isom_write_wave( lsmash_bs_t *bs, isom_box_t *box )
587 isom_bs_put_box_common( bs, box );
588 return 0;
591 static int isom_write_visual_description( lsmash_bs_t *bs, isom_box_t *box )
593 isom_visual_entry_t *data = (isom_visual_entry_t *)box;
594 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
595 return LSMASH_ERR_NAMELESS;
596 isom_bs_put_box_common( bs, data );
597 lsmash_bs_put_bytes( bs, 6, data->reserved );
598 lsmash_bs_put_be16( bs, data->data_reference_index );
599 lsmash_bs_put_be16( bs, data->version );
600 lsmash_bs_put_be16( bs, data->revision_level );
601 lsmash_bs_put_be32( bs, data->vendor );
602 lsmash_bs_put_be32( bs, data->temporalQuality );
603 lsmash_bs_put_be32( bs, data->spatialQuality );
604 lsmash_bs_put_be16( bs, data->width );
605 lsmash_bs_put_be16( bs, data->height );
606 lsmash_bs_put_be32( bs, data->horizresolution );
607 lsmash_bs_put_be32( bs, data->vertresolution );
608 lsmash_bs_put_be32( bs, data->dataSize );
609 lsmash_bs_put_be16( bs, data->frame_count );
610 lsmash_bs_put_bytes( bs, 32, data->compressorname );
611 lsmash_bs_put_be16( bs, data->depth );
612 lsmash_bs_put_be16( bs, data->color_table_ID );
613 if( data->color_table_ID == 0 )
614 isom_bs_put_qt_color_table( bs, &data->color_table );
615 return 0;
618 static int isom_write_audio_description( lsmash_bs_t *bs, isom_box_t *box )
620 isom_audio_entry_t *data = (isom_audio_entry_t *)box;
621 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
622 return LSMASH_ERR_NAMELESS;
623 isom_bs_put_box_common( bs, data );
624 lsmash_bs_put_bytes( bs, 6, data->reserved );
625 lsmash_bs_put_be16( bs, data->data_reference_index );
626 lsmash_bs_put_be16( bs, data->version );
627 lsmash_bs_put_be16( bs, data->revision_level );
628 lsmash_bs_put_be32( bs, data->vendor );
629 lsmash_bs_put_be16( bs, data->channelcount );
630 lsmash_bs_put_be16( bs, data->samplesize );
631 lsmash_bs_put_be16( bs, data->compression_ID );
632 lsmash_bs_put_be16( bs, data->packet_size );
633 lsmash_bs_put_be32( bs, data->samplerate );
634 if( data->version == 1 )
636 lsmash_bs_put_be32( bs, data->samplesPerPacket );
637 lsmash_bs_put_be32( bs, data->bytesPerPacket );
638 lsmash_bs_put_be32( bs, data->bytesPerFrame );
639 lsmash_bs_put_be32( bs, data->bytesPerSample );
641 else if( data->version == 2 )
643 lsmash_bs_put_be32( bs, data->sizeOfStructOnly );
644 lsmash_bs_put_be64( bs, data->audioSampleRate );
645 lsmash_bs_put_be32( bs, data->numAudioChannels );
646 lsmash_bs_put_be32( bs, data->always7F000000 );
647 lsmash_bs_put_be32( bs, data->constBitsPerChannel );
648 lsmash_bs_put_be32( bs, data->formatSpecificFlags );
649 lsmash_bs_put_be32( bs, data->constBytesPerAudioPacket );
650 lsmash_bs_put_be32( bs, data->constLPCMFramesPerAudioPacket );
652 return 0;
655 static int isom_write_hint_description( lsmash_bs_t *bs, isom_box_t *box )
657 isom_hint_entry_t *data = (isom_hint_entry_t *)box;
658 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
659 return LSMASH_ERR_NAMELESS;
660 isom_bs_put_box_common( bs, data );
661 lsmash_bs_put_bytes( bs, 6, data->reserved );
662 lsmash_bs_put_be16( bs, data->hinttrackversion );
663 lsmash_bs_put_be16( bs, data->highestcompatibleversion );
664 lsmash_bs_put_be32( bs, data->maxpacketsize );
665 return 0;
668 #if 0
669 static int isom_write_metadata_description( lsmash_bs_t *bs, lsmash_entry_t *entry )
671 isom_metadata_entry_t *data = (isom_metadata_entry_t *)entry->data;
672 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
673 return LSMASH_ERR_NAMELESS;
674 isom_bs_put_box_common( bs, data );
675 lsmash_bs_put_bytes( bs, 6, data->reserved );
676 lsmash_bs_put_be16( bs, data->data_reference_index );
677 return 0;
679 #endif
681 static int isom_write_qt_text_description( lsmash_bs_t *bs, isom_box_t *box )
683 isom_qt_text_entry_t *data = (isom_qt_text_entry_t *)box;
684 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
685 return LSMASH_ERR_NAMELESS;
686 isom_bs_put_box_common( bs, data );
687 lsmash_bs_put_bytes( bs, 6, data->reserved );
688 lsmash_bs_put_be16( bs, data->data_reference_index );
689 lsmash_bs_put_be32( bs, data->displayFlags );
690 lsmash_bs_put_be32( bs, data->textJustification );
691 for( uint32_t i = 0; i < 3; i++ )
692 lsmash_bs_put_be16( bs, data->bgColor[i] );
693 lsmash_bs_put_be16( bs, data->top );
694 lsmash_bs_put_be16( bs, data->left );
695 lsmash_bs_put_be16( bs, data->bottom );
696 lsmash_bs_put_be16( bs, data->right );
697 lsmash_bs_put_be32( bs, data->scrpStartChar );
698 lsmash_bs_put_be16( bs, data->scrpHeight );
699 lsmash_bs_put_be16( bs, data->scrpAscent );
700 lsmash_bs_put_be16( bs, data->scrpFont );
701 lsmash_bs_put_be16( bs, data->scrpFace );
702 lsmash_bs_put_be16( bs, data->scrpSize );
703 for( uint32_t i = 0; i < 3; i++ )
704 lsmash_bs_put_be16( bs, data->scrpColor[i] );
705 lsmash_bs_put_byte( bs, data->font_name_length );
706 if( data->font_name && data->font_name_length )
707 lsmash_bs_put_bytes( bs, data->font_name_length, data->font_name );
708 return 0;
711 static int isom_write_ftab( lsmash_bs_t *bs, isom_box_t *box )
713 isom_ftab_t *ftab = (isom_ftab_t *)box;
714 assert( ftab->list );
715 isom_bs_put_box_common( bs, ftab );
716 lsmash_bs_put_be16( bs, ftab->list->entry_count );
717 for( lsmash_entry_t *entry = ftab->list->head; entry; entry = entry->next )
719 isom_font_record_t *data = (isom_font_record_t *)entry->data;
720 if( !data )
721 return LSMASH_ERR_NAMELESS;
722 lsmash_bs_put_be16( bs, data->font_ID );
723 lsmash_bs_put_byte( bs, data->font_name_length );
724 if( data->font_name && data->font_name_length )
725 lsmash_bs_put_bytes( bs, data->font_name_length, data->font_name );
727 return 0;
730 static int isom_write_tx3g_description( lsmash_bs_t *bs, isom_box_t *box )
732 isom_tx3g_entry_t *data = (isom_tx3g_entry_t *)box;
733 if( LSMASH_IS_NON_EXISTING_BOX( data ) )
734 return LSMASH_ERR_NAMELESS;
735 isom_bs_put_box_common( bs, data );
736 lsmash_bs_put_bytes( bs, 6, data->reserved );
737 lsmash_bs_put_be16( bs, data->data_reference_index );
738 lsmash_bs_put_be32( bs, data->displayFlags );
739 lsmash_bs_put_byte( bs, data->horizontal_justification );
740 lsmash_bs_put_byte( bs, data->vertical_justification );
741 for( uint32_t i = 0; i < 4; i++ )
742 lsmash_bs_put_byte( bs, data->background_color_rgba[i] );
743 lsmash_bs_put_be16( bs, data->top );
744 lsmash_bs_put_be16( bs, data->left );
745 lsmash_bs_put_be16( bs, data->bottom );
746 lsmash_bs_put_be16( bs, data->right );
747 lsmash_bs_put_be16( bs, data->startChar );
748 lsmash_bs_put_be16( bs, data->endChar );
749 lsmash_bs_put_be16( bs, data->font_ID );
750 lsmash_bs_put_byte( bs, data->face_style_flags );
751 lsmash_bs_put_byte( bs, data->font_size );
752 for( uint32_t i = 0; i < 4; i++ )
753 lsmash_bs_put_byte( bs, data->text_color_rgba[i] );
754 return 0;
757 static int isom_write_stsd( lsmash_bs_t *bs, isom_box_t *box )
759 isom_stsd_t *stsd = (isom_stsd_t *)box;
760 isom_bs_put_box_common( bs, stsd );
761 lsmash_bs_put_be32( bs, stsd->list.entry_count );
762 return 0;
765 static int isom_write_stts( lsmash_bs_t *bs, isom_box_t *box )
767 isom_stts_t *stts = (isom_stts_t *)box;
768 assert( stts->list );
769 isom_bs_put_box_common( bs, stts );
770 lsmash_bs_put_be32( bs, stts->list->entry_count );
771 for( lsmash_entry_t *entry = stts->list->head; entry; entry = entry->next )
773 isom_stts_entry_t *data = (isom_stts_entry_t *)entry->data;
774 if( !data )
775 return LSMASH_ERR_NAMELESS;
776 lsmash_bs_put_be32( bs, data->sample_count );
777 lsmash_bs_put_be32( bs, data->sample_delta );
779 return 0;
782 static int isom_write_ctts( lsmash_bs_t *bs, isom_box_t *box )
784 isom_ctts_t *ctts = (isom_ctts_t *)box;
785 assert( ctts->list );
786 isom_bs_put_box_common( bs, ctts );
787 lsmash_bs_put_be32( bs, ctts->list->entry_count );
788 for( lsmash_entry_t *entry = ctts->list->head; entry; entry = entry->next )
790 isom_ctts_entry_t *data = (isom_ctts_entry_t *)entry->data;
791 if( !data )
792 return LSMASH_ERR_NAMELESS;
793 lsmash_bs_put_be32( bs, data->sample_count );
794 lsmash_bs_put_be32( bs, data->sample_offset );
796 return 0;
799 static int isom_write_cslg( lsmash_bs_t *bs, isom_box_t *box )
801 isom_cslg_t *cslg = (isom_cslg_t *)box;
802 isom_bs_put_box_common( bs, cslg );
803 lsmash_bs_put_be32( bs, cslg->compositionToDTSShift );
804 lsmash_bs_put_be32( bs, cslg->leastDecodeToDisplayDelta );
805 lsmash_bs_put_be32( bs, cslg->greatestDecodeToDisplayDelta );
806 lsmash_bs_put_be32( bs, cslg->compositionStartTime );
807 lsmash_bs_put_be32( bs, cslg->compositionEndTime );
808 return 0;
811 static int isom_write_stsz( lsmash_bs_t *bs, isom_box_t *box )
813 isom_stsz_t *stsz = (isom_stsz_t *)box;
814 isom_bs_put_box_common( bs, stsz );
815 lsmash_bs_put_be32( bs, stsz->sample_size );
816 lsmash_bs_put_be32( bs, stsz->sample_count );
817 if( stsz->sample_size == 0 && stsz->list )
818 for( lsmash_entry_t *entry = stsz->list->head; entry; entry = entry->next )
820 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
821 if( !data )
822 return LSMASH_ERR_NAMELESS;
823 lsmash_bs_put_be32( bs, data->entry_size );
825 return 0;
828 static int isom_write_stz2( lsmash_bs_t *bs, isom_box_t *box )
830 isom_stz2_t *stz2 = (isom_stz2_t *)box;
831 isom_bs_put_box_common( bs, stz2 );
832 lsmash_bs_put_be32( bs, (stz2->reserved << 8) | stz2->field_size );
833 lsmash_bs_put_be32( bs, stz2->sample_count );
834 if( stz2->field_size == 16 )
835 for( lsmash_entry_t *entry = stz2->list->head; entry; entry = entry->next )
837 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
838 if( !data )
839 return LSMASH_ERR_NAMELESS;
840 assert( data->entry_size <= 0xffff );
841 lsmash_bs_put_be16( bs, data->entry_size );
843 else if( stz2->field_size == 8 )
844 for( lsmash_entry_t *entry = stz2->list->head; entry; entry = entry->next )
846 isom_stsz_entry_t *data = (isom_stsz_entry_t *)entry->data;
847 if( !data )
848 return LSMASH_ERR_NAMELESS;
849 assert( data->entry_size <= 0xff );
850 lsmash_bs_put_byte( bs, data->entry_size );
852 else if( stz2->field_size == 4 )
854 isom_stsz_entry_t zero_padding = { .entry_size = 0 };
855 for( lsmash_entry_t *entry = stz2->list->head; entry; entry = entry->next ? entry->next->next : entry->next )
857 isom_stsz_entry_t *data_o = (isom_stsz_entry_t *)entry->data;
858 isom_stsz_entry_t *data_e = (isom_stsz_entry_t *)(entry->next ? entry->next->data : &zero_padding);
859 if( !data_o || !data_e )
860 return LSMASH_ERR_NAMELESS;
861 assert( data_o->entry_size <= 0xf && data_e->entry_size <= 0xf );
862 lsmash_bs_put_byte( bs, (data_o->entry_size << 4) | data_e->entry_size );
865 else
866 return LSMASH_ERR_NAMELESS;
867 return 0;
870 static int isom_write_stss( lsmash_bs_t *bs, isom_box_t *box )
872 isom_stss_t *stss = (isom_stss_t *)box;
873 assert( stss->list );
874 isom_bs_put_box_common( bs, stss );
875 lsmash_bs_put_be32( bs, stss->list->entry_count );
876 for( lsmash_entry_t *entry = stss->list->head; entry; entry = entry->next )
878 isom_stss_entry_t *data = (isom_stss_entry_t *)entry->data;
879 if( !data )
880 return LSMASH_ERR_NAMELESS;
881 lsmash_bs_put_be32( bs, data->sample_number );
883 return 0;
886 static int isom_write_stps( lsmash_bs_t *bs, isom_box_t *box )
888 isom_stps_t *stps = (isom_stps_t *)box;
889 assert( stps->list );
890 isom_bs_put_box_common( bs, stps );
891 lsmash_bs_put_be32( bs, stps->list->entry_count );
892 for( lsmash_entry_t *entry = stps->list->head; entry; entry = entry->next )
894 isom_stps_entry_t *data = (isom_stps_entry_t *)entry->data;
895 if( !data )
896 return LSMASH_ERR_NAMELESS;
897 lsmash_bs_put_be32( bs, data->sample_number );
899 return 0;
902 static int isom_write_sdtp( lsmash_bs_t *bs, isom_box_t *box )
904 isom_sdtp_t *sdtp = (isom_sdtp_t *)box;
905 assert( sdtp->list );
906 isom_bs_put_box_common( bs, sdtp );
907 for( lsmash_entry_t *entry = sdtp->list->head; entry; entry = entry->next )
909 isom_sdtp_entry_t *data = (isom_sdtp_entry_t *)entry->data;
910 if( !data )
911 return LSMASH_ERR_NAMELESS;
912 uint8_t temp = (data->is_leading << 6)
913 | (data->sample_depends_on << 4)
914 | (data->sample_is_depended_on << 2)
915 | data->sample_has_redundancy;
916 lsmash_bs_put_byte( bs, temp );
918 return 0;
921 static int isom_write_stsc( lsmash_bs_t *bs, isom_box_t *box )
923 isom_stsc_t *stsc = (isom_stsc_t *)box;
924 assert( stsc->list );
925 isom_bs_put_box_common( bs, stsc );
926 lsmash_bs_put_be32( bs, stsc->list->entry_count );
927 for( lsmash_entry_t *entry = stsc->list->head; entry; entry = entry->next )
929 isom_stsc_entry_t *data = (isom_stsc_entry_t *)entry->data;
930 if( !data )
931 return LSMASH_ERR_NAMELESS;
932 lsmash_bs_put_be32( bs, data->first_chunk );
933 lsmash_bs_put_be32( bs, data->samples_per_chunk );
934 lsmash_bs_put_be32( bs, data->sample_description_index );
936 return 0;
939 static int isom_write_co64( lsmash_bs_t *bs, isom_box_t *box )
941 isom_stco_t *co64 = (isom_stco_t *)box;
942 assert( co64->list );
943 isom_bs_put_box_common( bs, co64 );
944 lsmash_bs_put_be32( bs, co64->list->entry_count );
945 for( lsmash_entry_t *entry = co64->list->head; entry; entry = entry->next )
947 isom_co64_entry_t *data = (isom_co64_entry_t *)entry->data;
948 if( !data )
949 return LSMASH_ERR_NAMELESS;
950 lsmash_bs_put_be64( bs, data->chunk_offset );
952 return 0;
955 static int isom_write_stco( lsmash_bs_t *bs, isom_box_t *box )
957 isom_stco_t *stco = (isom_stco_t *)box;
958 if( stco->large_presentation )
959 return isom_write_co64( bs, box );
960 assert( stco->list );
961 isom_bs_put_box_common( bs, stco );
962 lsmash_bs_put_be32( bs, stco->list->entry_count );
963 for( lsmash_entry_t *entry = stco->list->head; entry; entry = entry->next )
965 isom_stco_entry_t *data = (isom_stco_entry_t *)entry->data;
966 if( !data )
967 return LSMASH_ERR_NAMELESS;
968 lsmash_bs_put_be32( bs, data->chunk_offset );
970 return 0;
973 static int isom_write_sgpd( lsmash_bs_t *bs, isom_box_t *box )
975 isom_sgpd_t *sgpd = (isom_sgpd_t *)box;
976 assert( sgpd->list );
977 isom_bs_put_box_common( bs, sgpd );
978 lsmash_bs_put_be32( bs, sgpd->grouping_type );
979 if( sgpd->version == 1 )
980 lsmash_bs_put_be32( bs, sgpd->default_length );
981 lsmash_bs_put_be32( bs, sgpd->list->entry_count );
982 for( lsmash_entry_t *entry = sgpd->list->head; entry; entry = entry->next )
984 if( !entry->data )
985 return LSMASH_ERR_NAMELESS;
986 switch( sgpd->grouping_type )
988 case ISOM_GROUP_TYPE_RAP :
990 isom_rap_entry_t *rap = (isom_rap_entry_t *)entry->data;
991 uint8_t temp = (rap->num_leading_samples_known << 7)
992 | rap->num_leading_samples;
993 lsmash_bs_put_byte( bs, temp );
994 break;
996 case ISOM_GROUP_TYPE_ROLL :
997 case ISOM_GROUP_TYPE_PROL :
998 lsmash_bs_put_be16( bs, ((isom_roll_entry_t *)entry->data)->roll_distance );
999 break;
1000 default :
1001 /* We don't consider other grouping types currently. */
1002 // if( sgpd->version == 1 && !sgpd->default_length )
1003 // lsmash_bs_put_be32( bs, ((isom_sgpd_t *)entry->data)->description_length );
1004 break;
1007 return 0;
1010 static int isom_write_sbgp( lsmash_bs_t *bs, isom_box_t *box )
1012 isom_sbgp_t *sbgp = (isom_sbgp_t *)box;
1013 assert( sbgp->list );
1014 isom_bs_put_box_common( bs, sbgp );
1015 lsmash_bs_put_be32( bs, sbgp->grouping_type );
1016 if( sbgp->version == 1 )
1017 lsmash_bs_put_be32( bs, sbgp->grouping_type_parameter );
1018 lsmash_bs_put_be32( bs, sbgp->list->entry_count );
1019 for( lsmash_entry_t *entry = sbgp->list->head; entry; entry = entry->next )
1021 isom_group_assignment_entry_t *data = (isom_group_assignment_entry_t *)entry->data;
1022 if( !data )
1023 return LSMASH_ERR_NAMELESS;
1024 lsmash_bs_put_be32( bs, data->sample_count );
1025 lsmash_bs_put_be32( bs, data->group_description_index );
1027 return 0;
1030 static int isom_write_stbl( lsmash_bs_t *bs, isom_box_t *box )
1032 isom_bs_put_box_common( bs, box );
1033 return 0;
1036 static int isom_write_minf( lsmash_bs_t *bs, isom_box_t *box )
1038 isom_bs_put_box_common( bs, box );
1039 return 0;
1042 static int isom_write_mdia( lsmash_bs_t *bs, isom_box_t *box )
1044 isom_bs_put_box_common( bs, box );
1045 return 0;
1048 static int isom_write_chpl( lsmash_bs_t *bs, isom_box_t *box )
1050 isom_chpl_t *chpl = (isom_chpl_t *)box;
1051 assert( chpl->list );
1052 isom_bs_put_box_common( bs, chpl );
1053 if( chpl->version == 1 )
1055 lsmash_bs_put_byte( bs, chpl->unknown );
1056 lsmash_bs_put_be32( bs, chpl->list->entry_count );
1058 else /* chpl->version == 0 */
1059 lsmash_bs_put_byte( bs, (uint8_t)chpl->list->entry_count );
1060 for( lsmash_entry_t *entry = chpl->list->head; entry; entry = entry->next )
1062 isom_chpl_entry_t *data = (isom_chpl_entry_t *)entry->data;
1063 if( !data )
1064 return LSMASH_ERR_NAMELESS;
1065 lsmash_bs_put_be64( bs, data->start_time );
1066 lsmash_bs_put_byte( bs, data->chapter_name_length );
1067 lsmash_bs_put_bytes( bs, data->chapter_name_length, data->chapter_name );
1069 return 0;
1072 static int isom_write_mean( lsmash_bs_t *bs, isom_box_t *box )
1074 isom_mean_t *mean = (isom_mean_t *)box;
1075 isom_bs_put_box_common( bs, mean );
1076 if( mean->meaning_string && mean->meaning_string_length )
1077 lsmash_bs_put_bytes( bs, mean->meaning_string_length, mean->meaning_string );
1078 return 0;
1081 static int isom_write_name( lsmash_bs_t *bs, isom_box_t *box )
1083 isom_name_t *name = (isom_name_t *)box;
1084 isom_bs_put_box_common( bs, name );
1085 if( name->name && name->name_length )
1086 lsmash_bs_put_bytes( bs, name->name_length, name->name );
1087 return 0;
1090 static int isom_write_data( lsmash_bs_t *bs, isom_box_t *box )
1092 isom_data_t *data = (isom_data_t *)box;
1093 isom_bs_put_box_common( bs, data );
1094 lsmash_bs_put_be16( bs, data->reserved );
1095 lsmash_bs_put_byte( bs, data->type_set_identifier );
1096 lsmash_bs_put_byte( bs, data->type_code );
1097 lsmash_bs_put_be32( bs, data->the_locale );
1098 if( data->value && data->value_length )
1099 lsmash_bs_put_bytes( bs, data->value_length, data->value );
1100 return 0;
1103 static int isom_write_metaitem( lsmash_bs_t *bs, isom_box_t *box )
1105 isom_bs_put_box_common( bs, box );
1106 return 0;
1109 static int isom_write_ilst( lsmash_bs_t *bs, isom_box_t *box )
1111 isom_bs_put_box_common( bs, box );
1112 return 0;
1115 static int isom_write_meta( lsmash_bs_t *bs, isom_box_t *box )
1117 isom_bs_put_box_common( bs, box );
1118 return 0;
1121 static int isom_write_cprt( lsmash_bs_t *bs, isom_box_t *box )
1123 isom_cprt_t *cprt = (isom_cprt_t *)box;
1124 isom_bs_put_box_common( bs, cprt );
1125 lsmash_bs_put_be16( bs, cprt->language );
1126 lsmash_bs_put_bytes( bs, cprt->notice_length, cprt->notice );
1127 return 0;
1130 static int isom_write_udta( lsmash_bs_t *bs, isom_box_t *box )
1132 isom_bs_put_box_common( bs, box );
1133 return 0;
1136 static int isom_write_hnti( lsmash_bs_t *bs, isom_box_t *box )
1138 isom_bs_put_box_common( bs, box );
1139 return 0;
1142 static int isom_write_rtp( lsmash_bs_t *bs, isom_box_t *box )
1144 isom_rtp_t *rtp = (isom_rtp_t *)box;
1145 isom_bs_put_box_common( bs, rtp );
1146 lsmash_bs_put_be32( bs, rtp->descriptionformat );
1147 lsmash_bs_put_bytes( bs, rtp->sdp_length, rtp->sdptext );
1148 return 0;
1150 static int isom_write_sdp( lsmash_bs_t *bs, isom_box_t *box )
1152 isom_sdp_t *sdp = (isom_sdp_t *)box;
1153 isom_bs_put_box_common( bs, sdp );
1154 lsmash_bs_put_bytes( bs, sdp->sdp_length, sdp->sdptext );
1155 return 0;
1158 static int isom_write_trak( lsmash_bs_t *bs, isom_box_t *box )
1160 isom_bs_put_box_common( bs, box );
1161 return 0;
1164 static int isom_write_iods( lsmash_bs_t *bs, isom_box_t *box )
1166 isom_iods_t *iods = (isom_iods_t *)box;
1167 isom_bs_put_box_common( bs, iods );
1168 mp4sys_update_descriptor_size( iods->OD );
1169 return mp4sys_write_descriptor( bs, iods->OD );
1172 static int isom_write_mvhd( lsmash_bs_t *bs, isom_box_t *box )
1174 isom_mvhd_t *mvhd = (isom_mvhd_t *)box;
1175 /* Check the version. */
1176 if( (LSMASH_IS_EXISTING_BOX( mvhd->file ) && !mvhd->file->undefined_64_ver)
1177 && (mvhd->creation_time > UINT32_MAX
1178 || mvhd->modification_time > UINT32_MAX
1179 || mvhd->duration > UINT32_MAX) )
1180 mvhd->version = 1;
1181 else
1182 mvhd->version = 0;
1183 /* Write. */
1184 isom_bs_put_box_common( bs, mvhd );
1185 if( mvhd->version )
1187 lsmash_bs_put_be64( bs, mvhd->creation_time );
1188 lsmash_bs_put_be64( bs, mvhd->modification_time );
1189 lsmash_bs_put_be32( bs, mvhd->timescale );
1190 lsmash_bs_put_be64( bs, mvhd->duration );
1192 else
1194 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->creation_time, UINT32_MAX ) );
1195 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->modification_time, UINT32_MAX ) );
1196 lsmash_bs_put_be32( bs, mvhd->timescale );
1197 lsmash_bs_put_be32( bs, LSMASH_MIN( mvhd->duration, UINT32_MAX ) );
1199 lsmash_bs_put_be32( bs, mvhd->rate );
1200 lsmash_bs_put_be16( bs, mvhd->volume );
1201 lsmash_bs_put_be16( bs, mvhd->reserved );
1202 lsmash_bs_put_be32( bs, mvhd->preferredLong[0] );
1203 lsmash_bs_put_be32( bs, mvhd->preferredLong[1] );
1204 for( int i = 0; i < 9; i++ )
1205 lsmash_bs_put_be32( bs, mvhd->matrix[i] );
1206 lsmash_bs_put_be32( bs, mvhd->previewTime );
1207 lsmash_bs_put_be32( bs, mvhd->previewDuration );
1208 lsmash_bs_put_be32( bs, mvhd->posterTime );
1209 lsmash_bs_put_be32( bs, mvhd->selectionTime );
1210 lsmash_bs_put_be32( bs, mvhd->selectionDuration );
1211 lsmash_bs_put_be32( bs, mvhd->currentTime );
1212 lsmash_bs_put_be32( bs, mvhd->next_track_ID );
1213 return 0;
1216 static void isom_bs_put_sample_flags( lsmash_bs_t *bs, isom_sample_flags_t *flags )
1218 uint32_t temp = (flags->reserved << 28)
1219 | (flags->is_leading << 26)
1220 | (flags->sample_depends_on << 24)
1221 | (flags->sample_is_depended_on << 22)
1222 | (flags->sample_has_redundancy << 20)
1223 | (flags->sample_padding_value << 17)
1224 | (flags->sample_is_non_sync_sample << 16)
1225 | flags->sample_degradation_priority;
1226 lsmash_bs_put_be32( bs, temp );
1229 static int isom_write_mehd( lsmash_bs_t *bs, isom_box_t *box )
1231 if( box->manager & LSMASH_PLACEHOLDER )
1233 /* Movie Extends Header Box is not written immediately.
1234 * It's done after finishing all movie fragments.
1235 * The following will be overwritten by Movie Extends Header Box.
1236 * We use version 1 Movie Extends Header Box since it causes extra 4 bytes region
1237 * we cannot replace with empty Free Space Box as we place version 0 one. */
1238 box->pos = box->file->bs->written;
1239 lsmash_bs_put_be32( bs, ISOM_BASEBOX_COMMON_SIZE + 12 );
1240 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_FREE.fourcc );
1241 lsmash_bs_put_be32( bs, 0 );
1242 lsmash_bs_put_be64( bs, 0 );
1244 else
1246 isom_mehd_t *mehd = (isom_mehd_t *)box;
1247 //mehd->version = mehd->fragment_duration > UINT32_MAX ? 1 : 0;
1248 isom_bs_put_box_common( bs, mehd );
1249 if( mehd->version == 1 )
1250 lsmash_bs_put_be64( bs, mehd->fragment_duration );
1251 else
1252 lsmash_bs_put_be32( bs, LSMASH_MIN( mehd->fragment_duration, UINT32_MAX ) );
1254 return 0;
1257 static int isom_write_trex( lsmash_bs_t *bs, isom_box_t *box )
1259 isom_trex_t *trex = (isom_trex_t *)box;
1260 isom_bs_put_box_common( bs, trex );
1261 lsmash_bs_put_be32( bs, trex->track_ID );
1262 lsmash_bs_put_be32( bs, trex->default_sample_description_index );
1263 lsmash_bs_put_be32( bs, trex->default_sample_duration );
1264 lsmash_bs_put_be32( bs, trex->default_sample_size );
1265 isom_bs_put_sample_flags( bs, &trex->default_sample_flags );
1266 return 0;
1269 static int isom_write_mvex( lsmash_bs_t *bs, isom_box_t *box )
1271 isom_bs_put_box_common( bs, box );
1272 return 0;
1275 static int isom_write_mfhd( lsmash_bs_t *bs, isom_box_t *box )
1277 isom_mfhd_t *mfhd = (isom_mfhd_t *)box;
1278 isom_bs_put_box_common( bs, mfhd );
1279 lsmash_bs_put_be32( bs, mfhd->sequence_number );
1280 return 0;
1283 static int isom_write_tfhd( lsmash_bs_t *bs, isom_box_t *box )
1285 isom_tfhd_t *tfhd = (isom_tfhd_t *)box;
1286 isom_bs_put_box_common( bs, tfhd );
1287 lsmash_bs_put_be32( bs, tfhd->track_ID );
1288 if( tfhd->flags & ISOM_TF_FLAGS_BASE_DATA_OFFSET_PRESENT ) lsmash_bs_put_be64( bs, tfhd->base_data_offset );
1289 if( tfhd->flags & ISOM_TF_FLAGS_SAMPLE_DESCRIPTION_INDEX_PRESENT ) lsmash_bs_put_be32( bs, tfhd->sample_description_index );
1290 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT ) lsmash_bs_put_be32( bs, tfhd->default_sample_duration );
1291 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_SIZE_PRESENT ) lsmash_bs_put_be32( bs, tfhd->default_sample_size );
1292 if( tfhd->flags & ISOM_TF_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &tfhd->default_sample_flags );
1293 return 0;
1296 static int isom_write_tfdt( lsmash_bs_t *bs, isom_box_t *box )
1298 isom_tfdt_t *tfdt = (isom_tfdt_t *)box;
1299 /* Check the version. */
1300 tfdt->version = tfdt->baseMediaDecodeTime > UINT32_MAX ? 1 : 0;
1301 /* Write. */
1302 isom_bs_put_box_common( bs, tfdt );
1303 if( tfdt->version == 1 )
1304 lsmash_bs_put_be64( bs, tfdt->baseMediaDecodeTime );
1305 else
1306 lsmash_bs_put_be32( bs, tfdt->baseMediaDecodeTime );
1307 return 0;
1310 static int isom_write_trun( lsmash_bs_t *bs, isom_box_t *box )
1312 isom_trun_t *trun = (isom_trun_t *)box;
1313 isom_bs_put_box_common( bs, trun );
1314 lsmash_bs_put_be32( bs, trun->sample_count );
1315 if( trun->flags & ISOM_TR_FLAGS_DATA_OFFSET_PRESENT ) lsmash_bs_put_be32( bs, trun->data_offset );
1316 if( trun->flags & ISOM_TR_FLAGS_FIRST_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &trun->first_sample_flags );
1317 if( trun->optional )
1318 for( lsmash_entry_t *entry = trun->optional->head; entry; entry = entry->next )
1320 isom_trun_optional_row_t *data = (isom_trun_optional_row_t *)entry->data;
1321 if( !data )
1322 return LSMASH_ERR_NAMELESS;
1323 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_DURATION_PRESENT ) lsmash_bs_put_be32( bs, data->sample_duration );
1324 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_SIZE_PRESENT ) lsmash_bs_put_be32( bs, data->sample_size );
1325 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_FLAGS_PRESENT ) isom_bs_put_sample_flags( bs, &data->sample_flags );
1326 if( trun->flags & ISOM_TR_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT ) lsmash_bs_put_be32( bs, data->sample_composition_time_offset );
1328 return 0;
1331 static int isom_write_traf( lsmash_bs_t *bs, isom_box_t *box )
1333 isom_bs_put_box_common( bs, box );
1334 return 0;
1337 static int isom_write_moof( lsmash_bs_t *bs, isom_box_t *box )
1339 isom_bs_put_box_common( bs, box );
1340 return 0;
1343 static int isom_write_tfra( lsmash_bs_t *bs, isom_box_t *box )
1345 isom_tfra_t *tfra = (isom_tfra_t *)box;
1346 isom_bs_put_box_common( bs, tfra );
1347 uint32_t temp = (tfra->reserved << 6)
1348 | (tfra->length_size_of_traf_num << 4)
1349 | (tfra->length_size_of_trun_num << 2)
1350 | tfra->length_size_of_sample_num;
1351 lsmash_bs_put_be32( bs, tfra->track_ID );
1352 lsmash_bs_put_be32( bs, temp );
1353 lsmash_bs_put_be32( bs, tfra->number_of_entry );
1354 if( tfra->list )
1356 void (*bs_put_funcs[5])( lsmash_bs_t *, uint64_t ) =
1358 lsmash_bs_put_byte_from_64,
1359 lsmash_bs_put_be16_from_64,
1360 lsmash_bs_put_be24_from_64,
1361 lsmash_bs_put_be32_from_64,
1362 lsmash_bs_put_be64
1364 void (*bs_put_time) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->version == 1 ? 4 : 3 ];
1365 void (*bs_put_moof_offset) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->version == 1 ? 4 : 3 ];
1366 void (*bs_put_traf_number) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_traf_num ];
1367 void (*bs_put_trun_number) ( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_trun_num ];
1368 void (*bs_put_sample_number)( lsmash_bs_t *, uint64_t ) = bs_put_funcs[ tfra->length_size_of_sample_num ];
1369 for( lsmash_entry_t *entry = tfra->list->head; entry; entry = entry->next )
1371 isom_tfra_location_time_entry_t *data = (isom_tfra_location_time_entry_t *)entry->data;
1372 if( !data )
1373 return LSMASH_ERR_NAMELESS;
1374 bs_put_time ( bs, data->time );
1375 bs_put_moof_offset ( bs, data->moof_offset );
1376 bs_put_traf_number ( bs, data->traf_number );
1377 bs_put_trun_number ( bs, data->trun_number );
1378 bs_put_sample_number( bs, data->sample_number );
1381 return 0;
1384 static int isom_write_mfro( lsmash_bs_t *bs, isom_box_t *box )
1386 isom_mfro_t *mfro = (isom_mfro_t *)box;
1387 isom_bs_put_box_common( bs, mfro );
1388 lsmash_bs_put_be32( bs, mfro->length ); /* determined at isom_write_mfra(). */
1389 return 0;
1392 static int isom_write_mfra( lsmash_bs_t *bs, isom_box_t *box )
1394 isom_mfra_t *mfra = (isom_mfra_t *)box;
1395 if( mfra->mfro )
1396 mfra->mfro->length = mfra->size;
1397 isom_bs_put_box_common( bs, mfra );
1398 return 0;
1401 static int isom_write_mdat( lsmash_bs_t *bs, isom_box_t *box )
1403 isom_mdat_t *mdat = (isom_mdat_t *)box;
1404 lsmash_file_t *file = mdat->file;
1405 /* If any fragment, write the Media Data Box all at once. */
1406 if( file->fragment )
1408 /* Write the size and type fields of the Media Data Box. */
1409 mdat->size = ISOM_BASEBOX_COMMON_SIZE + file->fragment->pool_size;
1410 if( mdat->size > UINT32_MAX )
1411 mdat->size += 8; /* large_size */
1412 isom_bs_put_box_common( bs, mdat );
1413 /* Write the samples in the current movie fragment. */
1414 for( lsmash_entry_t *entry = file->fragment->pool->head; entry; entry = entry->next )
1416 isom_sample_pool_t *pool = (isom_sample_pool_t *)entry->data;
1417 if( !pool )
1418 return LSMASH_ERR_NAMELESS;
1419 lsmash_bs_put_bytes( bs, pool->size, pool->data );
1421 mdat->media_size = file->fragment->pool_size;
1422 return 0;
1424 if( mdat->manager & LSMASH_PLACEHOLDER )
1426 /* Write an incomplete Media Data Box.
1427 * Braindead implementation might check box order and return an error if an expected box does not come the
1428 * next. Placement of eight 0x00 byte string as a simple large_size placeholder passes such silly box order
1429 * checks. This placement is more compatible than placement of a Free Space Box ('free' or 'skip') or a
1430 * Placeholder Atom ('wide') as a large_size placeholder since Media Data Box can store any data and any
1431 * implementation surely do not check what contents are stored in it until taking samples out according to
1432 * chunk offsets, and the placeholder is placed before any chunk offset thus it won't be touched. */
1433 mdat->pos = bs->offset;
1434 mdat->size = ISOM_BASEBOX_COMMON_SIZE + 8 + mdat->reserved_size;
1435 mdat->manager |= LSMASH_INCOMPLETE_BOX;
1436 mdat->manager &= ~LSMASH_PLACEHOLDER;
1437 isom_bs_put_box_common( bs, mdat );
1438 if( mdat->size <= UINT32_MAX )
1439 lsmash_bs_put_be64( bs, 0x0000000000000000 );
1440 mdat->size = ISOM_BASEBOX_COMMON_SIZE + 8;
1441 return 0;
1443 assert( !(mdat->manager & (LSMASH_INCOMPLETE_BOX | LSMASH_PLACEHOLDER)) );
1444 uint64_t actual_size = ISOM_BASEBOX_COMMON_SIZE + 8 + mdat->media_size;
1445 uint64_t reserved_size = ISOM_BASEBOX_COMMON_SIZE + 8 + mdat->reserved_size;
1446 if( actual_size < reserved_size )
1448 /* Write padding zero bytes until end of this box.
1449 * This code path is invoked when the size of a Media Data Box was reserved. */
1450 mdat->size = reserved_size;
1451 int err = lsmash_bs_flush_buffer( bs );
1452 if( err )
1453 return err;
1454 uint64_t padding_size = reserved_size - actual_size;
1455 static const uint8_t zero_bytes[64] = { 0 };
1456 while( padding_size > sizeof(zero_bytes) )
1458 if( (err = lsmash_bs_write_data( bs, zero_bytes, sizeof(zero_bytes) )) < 0 )
1459 return err;
1460 padding_size -= sizeof(zero_bytes);
1462 return lsmash_bs_write_data( bs, zero_bytes, padding_size );
1464 if( !bs->unseekable )
1466 /* Write the actual size. */
1467 uint64_t current_pos = bs->offset;
1468 mdat->size = actual_size;
1469 lsmash_bs_write_seek( bs, mdat->pos, SEEK_SET );
1470 isom_bs_put_box_common( bs, mdat );
1471 /* isom_write_box() also calls lsmash_bs_flush_buffer() but it must do nothing. */
1472 int ret = lsmash_bs_flush_buffer( bs );
1473 lsmash_bs_write_seek( bs, current_pos, SEEK_SET );
1474 return ret;
1476 return LSMASH_ERR_NAMELESS;
1479 static int isom_write_ftyp( lsmash_bs_t *bs, isom_box_t *box )
1481 isom_ftyp_t *ftyp = (isom_ftyp_t *)box;
1482 if( ftyp->brand_count == 0 )
1483 return 0;
1484 isom_bs_put_box_common( bs, ftyp );
1485 lsmash_bs_put_be32( bs, ftyp->major_brand );
1486 lsmash_bs_put_be32( bs, ftyp->minor_version );
1487 for( uint32_t i = 0; i < ftyp->brand_count; i++ )
1488 lsmash_bs_put_be32( bs, ftyp->compatible_brands[i] );
1489 return 0;
1492 static int isom_write_moov( lsmash_bs_t *bs, isom_box_t *box )
1494 isom_bs_put_box_common( bs, box );
1495 return 0;
1498 static int isom_write_free( lsmash_bs_t *bs, isom_box_t *box )
1500 isom_free_t *skip = (isom_free_t *)box;
1501 isom_bs_put_box_common( bs, skip );
1502 if( skip->data && skip->length )
1503 lsmash_bs_put_bytes( bs, skip->length, skip->data );
1504 return 0;
1507 static int isom_write_sidx( lsmash_bs_t *bs, isom_box_t *box )
1509 isom_sidx_t *sidx = (isom_sidx_t *)box;
1510 /* Check the version. */
1511 if( sidx->earliest_presentation_time > UINT32_MAX
1512 || sidx->first_offset > UINT32_MAX )
1513 sidx->version = 1;
1514 else
1515 sidx->version = 0;
1516 /* Write. */
1517 isom_bs_put_box_common( bs, sidx );
1518 lsmash_bs_put_be32( bs, sidx->reference_ID );
1519 lsmash_bs_put_be32( bs, sidx->timescale );
1520 if( sidx->version == 0 )
1522 lsmash_bs_put_be32( bs, LSMASH_MIN( sidx->earliest_presentation_time, UINT32_MAX ) );
1523 lsmash_bs_put_be32( bs, LSMASH_MIN( sidx->first_offset, UINT32_MAX ) );
1525 else
1527 lsmash_bs_put_be64( bs, sidx->earliest_presentation_time );
1528 lsmash_bs_put_be64( bs, sidx->first_offset );
1530 lsmash_bs_put_be16( bs, sidx->reserved );
1531 lsmash_bs_put_be16( bs, sidx->reference_count );
1532 for( lsmash_entry_t *entry = sidx->list->head; entry; entry = entry->next )
1534 isom_sidx_referenced_item_t *data = (isom_sidx_referenced_item_t *)entry->data;
1535 if( !data )
1536 return LSMASH_ERR_NAMELESS;
1537 uint32_t temp32;
1538 temp32 = (data->reference_type << 31)
1539 | data->reference_size;
1540 lsmash_bs_put_be32( bs, temp32 );
1541 lsmash_bs_put_be32( bs, data->subsegment_duration );
1542 temp32 = (data->starts_with_SAP << 31)
1543 | (data->SAP_type << 28)
1544 | data->SAP_delta_time;
1545 lsmash_bs_put_be32( bs, temp32 );
1547 return 0;
1550 int isom_write_box( lsmash_bs_t *bs, isom_box_t *box )
1552 assert( bs );
1553 /* Don't write any incomplete or already written box to a file. */
1554 if( LSMASH_IS_NON_EXISTING_BOX( box )
1555 || !box->write
1556 || (bs->stream && (box->manager & (LSMASH_INCOMPLETE_BOX | LSMASH_WRITTEN_BOX))) )
1557 return 0;
1558 int ret = box->write( bs, box );
1559 if( ret < 0 )
1560 return ret;
1561 if( bs->stream )
1563 if( (ret = lsmash_bs_flush_buffer( bs )) < 0 )
1564 return ret;
1565 /* Don't write any child box if this box is a placeholder or an incomplete box. */
1566 if( box->manager & (LSMASH_PLACEHOLDER | LSMASH_INCOMPLETE_BOX) )
1567 return 0;
1568 else
1569 box->manager |= LSMASH_WRITTEN_BOX;
1571 return isom_write_children( bs, box );
1574 void isom_set_box_writer( isom_box_t *box )
1576 if( box->manager & LSMASH_BINARY_CODED_BOX )
1578 box->write = isom_write_binary_coded_box;
1579 return;
1581 else if( box->manager & LSMASH_UNKNOWN_BOX )
1583 box->write = isom_write_unknown_box;
1584 return;
1586 assert( LSMASH_IS_EXISTING_BOX( box->parent ) );
1587 isom_box_t *parent = box->parent;
1588 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_STSD ) )
1590 /* OK, this box is a sample entry.
1591 * Here, determine the suitable sample entry writer by media type if possible. */
1592 if( !isom_check_media_hdlr_from_stsd( (isom_stsd_t *)parent ) )
1593 return;
1594 lsmash_media_type media_type = isom_get_media_type_from_stsd( (isom_stsd_t *)parent );
1595 if( media_type == ISOM_MEDIA_HANDLER_TYPE_VIDEO_TRACK )
1596 box->write = isom_write_visual_description;
1597 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_AUDIO_TRACK )
1598 box->write = isom_write_audio_description;
1599 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_HINT_TRACK )
1600 box->write = isom_write_hint_description;
1601 else if( media_type == ISOM_MEDIA_HANDLER_TYPE_TEXT_TRACK )
1603 if( lsmash_check_box_type_identical( box->type, QT_CODEC_TYPE_TEXT_TEXT ) )
1604 box->write = isom_write_qt_text_description;
1605 else if( lsmash_check_box_type_identical( box->type, ISOM_CODEC_TYPE_TX3G_TEXT ) )
1606 box->write = isom_write_tx3g_description;
1608 if( box->write )
1609 return;
1611 if( lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_WAVE ) )
1613 if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_FRMA ) ) box->write = isom_write_frma;
1614 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ENDA ) ) box->write = isom_write_enda;
1615 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_MP4A ) ) box->write = isom_write_mp4a;
1616 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_ESDS ) ) box->write = isom_write_esds;
1617 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_CHAN ) ) box->write = isom_write_chan;
1618 else if( lsmash_check_box_type_identical( box->type, QT_BOX_TYPE_TERMINATOR ) ) box->write = isom_write_terminator;
1619 else box->write = NULL;
1620 return;
1622 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_TREF ) )
1624 box->write = isom_write_track_reference_type;
1625 return;
1627 static struct box_writer_table_tag
1629 lsmash_box_type_t type;
1630 isom_extension_writer_t writer_func;
1631 } box_writer_table[128] = { { LSMASH_BOX_TYPE_INITIALIZER, NULL } };
1632 if( !box_writer_table[0].writer_func )
1634 /* Initialize the table. */
1635 int i = 0;
1636 #define ADD_BOX_WRITER_TABLE_ELEMENT( type, reader_func ) \
1637 box_writer_table[i++] = (struct box_writer_table_tag){ type, reader_func }
1638 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTYP, isom_write_ftyp );
1639 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STYP, isom_write_ftyp );
1640 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SIDX, isom_write_sidx );
1641 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOV, isom_write_moov );
1642 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVHD, isom_write_mvhd );
1643 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_IODS, isom_write_iods );
1644 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CTAB, isom_write_ctab );
1645 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ESDS, isom_write_esds );
1646 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAK, isom_write_trak );
1647 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TKHD, isom_write_tkhd );
1648 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TAPT, isom_write_tapt );
1649 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLEF, isom_write_clef );
1650 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_PROF, isom_write_prof );
1651 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ENOF, isom_write_enof );
1652 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_EDTS, isom_write_edts );
1653 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ELST, isom_write_elst );
1654 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREF, isom_write_tref );
1655 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDIA, isom_write_mdia );
1656 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDHD, isom_write_mdhd );
1657 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HDLR, isom_write_hdlr );
1658 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MINF, isom_write_minf );
1659 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_VMHD, isom_write_vmhd );
1660 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SMHD, isom_write_smhd );
1661 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HMHD, isom_write_hmhd );
1662 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_NMHD, isom_write_nmhd );
1663 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMHD, isom_write_gmhd );
1664 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GMIN, isom_write_gmin );
1665 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_TEXT, isom_write_text );
1666 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DINF, isom_write_dinf );
1667 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_DREF, isom_write_dref );
1668 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_URL, isom_write_url );
1669 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STBL, isom_write_stbl );
1670 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSD, isom_write_stsd );
1671 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_BTRT, isom_write_btrt );
1672 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TIMS, isom_write_tims );
1673 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSRO, isom_write_tsro );
1674 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TSSY, isom_write_tssy );
1675 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_COLR, isom_write_colr );
1676 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_COLR, isom_write_colr );
1677 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CLAP, isom_write_clap );
1678 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_PASP, isom_write_pasp );
1679 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GLBL, isom_write_glbl );
1680 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_GAMA, isom_write_gama );
1681 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_FIEL, isom_write_fiel );
1682 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CLLI, isom_write_clli );
1683 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MDCV, isom_write_mdcv );
1684 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CSPC, isom_write_cspc );
1685 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_SGBT, isom_write_sgbt );
1686 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSL, isom_write_stsl );
1687 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_WAVE, isom_write_wave );
1688 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_MP4A, isom_write_mp4a );
1689 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_CHAN, isom_write_chan );
1690 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FTAB, isom_write_ftab );
1691 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STTS, isom_write_stts );
1692 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CTTS, isom_write_ctts );
1693 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CSLG, isom_write_cslg );
1694 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSS, isom_write_stss );
1695 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_STPS, isom_write_stps );
1696 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDTP, isom_write_sdtp );
1697 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSC, isom_write_stsc );
1698 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STSZ, isom_write_stsz );
1699 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STZ2, isom_write_stz2 );
1700 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_STCO, isom_write_stco );
1701 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CO64, isom_write_stco );
1702 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SGPD, isom_write_sgpd );
1703 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SBGP, isom_write_sbgp );
1704 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_UDTA, isom_write_udta );
1705 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_HNTI, isom_write_hnti );
1706 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_RTP, isom_write_rtp );
1707 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SDP, isom_write_sdp );
1708 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_CHPL, isom_write_chpl );
1709 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MVEX, isom_write_mvex );
1710 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MEHD, isom_write_mehd );
1711 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TREX, isom_write_trex );
1712 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MOOF, isom_write_moof );
1713 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFHD, isom_write_mfhd );
1714 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRAF, isom_write_traf );
1715 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFHD, isom_write_tfhd );
1716 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFDT, isom_write_tfdt );
1717 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TRUN, isom_write_trun );
1718 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MDAT, isom_write_mdat );
1719 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_FREE, isom_write_free );
1720 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_SKIP, isom_write_free );
1721 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_META, isom_write_meta );
1722 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_META, isom_write_meta );
1723 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_ILST, isom_write_ilst );
1724 ADD_BOX_WRITER_TABLE_ELEMENT( QT_BOX_TYPE_ILST, isom_write_ilst );
1725 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRA, isom_write_mfra );
1726 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_TFRA, isom_write_tfra );
1727 ADD_BOX_WRITER_TABLE_ELEMENT( ISOM_BOX_TYPE_MFRO, isom_write_mfro );
1728 ADD_BOX_WRITER_TABLE_ELEMENT( LSMASH_BOX_TYPE_UNSPECIFIED, NULL );
1729 #undef ADD_BOX_WRITER_TABLE_ELEMENT
1731 for( int i = 0; box_writer_table[i].writer_func; i++ )
1732 if( lsmash_check_box_type_identical( box->type, box_writer_table[i].type ) )
1734 box->write = box_writer_table[i].writer_func;
1735 return;
1737 if( lsmash_check_box_type_identical( parent->type, ISOM_BOX_TYPE_ILST )
1738 || lsmash_check_box_type_identical( parent->type, QT_BOX_TYPE_ILST ) )
1740 box->write = isom_write_metaitem;
1741 return;
1743 if( lsmash_check_box_type_identical( parent->parent->type, ISOM_BOX_TYPE_ILST ) )
1745 if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_MEAN ) )
1746 box->write = isom_write_mean;
1747 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_NAME ) )
1748 box->write = isom_write_name;
1749 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_DATA ) )
1750 box->write = isom_write_data;
1751 if( box->write )
1752 return;
1754 else if( lsmash_check_box_type_identical( box->type, ISOM_BOX_TYPE_CPRT ) )
1756 /* Avoid confusing udta.cprt with ilst.cprt. */
1757 box->write = isom_write_cprt;
1758 return;
1760 box->write = isom_write_unknown_box;