1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2015 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 */
37 #include "importer/importer.h"
39 static void isom_clear_compat_flags
44 /* Clear flags for compatibility. */
45 memset( (int8_t *)file
+ COMPAT_FLAGS_OFFSET
, 0, sizeof(lsmash_file_t
) - COMPAT_FLAGS_OFFSET
);
46 file
->min_isom_version
= UINT8_MAX
; /* undefined value */
49 int isom_check_compatibility
55 return LSMASH_ERR_FUNCTION_PARAM
;
56 isom_clear_compat_flags( file
);
57 /* Get the brand container. */
58 isom_ftyp_t
*ftyp
= file
->ftyp
? file
->ftyp
: (isom_ftyp_t
*)lsmash_get_entry_data( &file
->styp_list
, 1 );
59 /* Check brand to decide mandatory boxes. */
62 /* No brand declaration means this file is a MP4 version 1 or QuickTime file format. */
66 file
->mp4_version1
= 1;
67 file
->isom_compatible
= 1;
71 file
->qt_compatible
= 1;
72 file
->undefined_64_ver
= 1;
76 for( uint32_t i
= 0; i
<= ftyp
->brand_count
; i
++ )
78 uint32_t brand
= (i
== ftyp
->brand_count
? ftyp
->major_brand
: ftyp
->compatible_brands
[i
]);
81 case ISOM_BRAND_TYPE_QT
:
82 file
->qt_compatible
= 1;
84 case ISOM_BRAND_TYPE_MP41
:
85 file
->mp4_version1
= 1;
87 case ISOM_BRAND_TYPE_MP42
:
88 file
->mp4_version2
= 1;
90 case ISOM_BRAND_TYPE_AVC1
:
91 case ISOM_BRAND_TYPE_ISOM
:
92 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 1 );
93 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 1 );
95 case ISOM_BRAND_TYPE_ISO2
:
96 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 2 );
97 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 2 );
99 case ISOM_BRAND_TYPE_ISO3
:
100 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 3 );
101 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 3 );
103 case ISOM_BRAND_TYPE_ISO4
:
104 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 4 );
105 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 4 );
107 case ISOM_BRAND_TYPE_ISO5
:
108 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 5 );
109 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 5 );
111 case ISOM_BRAND_TYPE_ISO6
:
112 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 6 );
113 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 6 );
115 case ISOM_BRAND_TYPE_ISO7
:
116 file
->max_isom_version
= LSMASH_MAX( file
->max_isom_version
, 7 );
117 file
->min_isom_version
= LSMASH_MIN( file
->min_isom_version
, 7 );
119 case ISOM_BRAND_TYPE_M4A
:
120 case ISOM_BRAND_TYPE_M4B
:
121 case ISOM_BRAND_TYPE_M4P
:
122 case ISOM_BRAND_TYPE_M4V
:
123 file
->itunes_movie
= 1;
125 case ISOM_BRAND_TYPE_3GP4
:
126 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 4 );
128 case ISOM_BRAND_TYPE_3GP5
:
129 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 5 );
131 case ISOM_BRAND_TYPE_3GE6
:
132 case ISOM_BRAND_TYPE_3GG6
:
133 case ISOM_BRAND_TYPE_3GP6
:
134 case ISOM_BRAND_TYPE_3GR6
:
135 case ISOM_BRAND_TYPE_3GS6
:
136 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 6 );
138 case ISOM_BRAND_TYPE_3GP7
:
139 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 7 );
141 case ISOM_BRAND_TYPE_3GP8
:
142 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 8 );
144 case ISOM_BRAND_TYPE_3GE9
:
145 case ISOM_BRAND_TYPE_3GF9
:
146 case ISOM_BRAND_TYPE_3GG9
:
147 case ISOM_BRAND_TYPE_3GH9
:
148 case ISOM_BRAND_TYPE_3GM9
:
149 case ISOM_BRAND_TYPE_3GP9
:
150 case ISOM_BRAND_TYPE_3GR9
:
151 case ISOM_BRAND_TYPE_3GS9
:
152 case ISOM_BRAND_TYPE_3GT9
:
153 file
->max_3gpp_version
= LSMASH_MAX( file
->max_3gpp_version
, 9 );
160 case ISOM_BRAND_TYPE_AVC1
:
161 case ISOM_BRAND_TYPE_ISO2
:
162 case ISOM_BRAND_TYPE_ISO3
:
163 case ISOM_BRAND_TYPE_ISO4
:
164 case ISOM_BRAND_TYPE_ISO5
:
165 case ISOM_BRAND_TYPE_ISO6
:
166 file
->avc_extensions
= 1;
168 case ISOM_BRAND_TYPE_3GP4
:
169 case ISOM_BRAND_TYPE_3GP5
:
170 case ISOM_BRAND_TYPE_3GP6
:
171 case ISOM_BRAND_TYPE_3GP7
:
172 case ISOM_BRAND_TYPE_3GP8
:
173 case ISOM_BRAND_TYPE_3GP9
:
174 file
->forbid_tref
= 1;
176 case ISOM_BRAND_TYPE_3GH9
:
177 case ISOM_BRAND_TYPE_3GM9
:
178 case ISOM_BRAND_TYPE_DASH
:
179 case ISOM_BRAND_TYPE_DSMS
:
180 case ISOM_BRAND_TYPE_LMSG
:
181 case ISOM_BRAND_TYPE_MSDH
:
182 case ISOM_BRAND_TYPE_MSIX
:
183 case ISOM_BRAND_TYPE_SIMS
:
184 file
->media_segment
= 1;
190 file
->isom_compatible
= !file
->qt_compatible
191 || file
->mp4_version1
192 || file
->mp4_version2
193 || file
->itunes_movie
194 || file
->max_3gpp_version
;
195 file
->undefined_64_ver
= file
->qt_compatible
|| file
->itunes_movie
;
196 if( file
->flags
& LSMASH_FILE_MODE_WRITE
)
198 /* Media Segment is incompatible with ISO Base Media File Format version 4 or former must be compatible with
199 * version 6 or later since it requires default-base-is-moof and Track Fragment Base Media Decode Time Box. */
200 if( file
->media_segment
&& (file
->min_isom_version
< 5 || (file
->max_isom_version
&& file
->max_isom_version
< 6)) )
201 return LSMASH_ERR_INVALID_DATA
;
202 file
->allow_moof_base
= (file
->max_isom_version
>= 5 && file
->min_isom_version
>= 5)
203 || (file
->max_isom_version
== 0 && file
->min_isom_version
== UINT8_MAX
&& file
->media_segment
);
208 int isom_check_mandatory_boxes
215 || !file
->moov
->mvhd
)
216 return LSMASH_ERR_INVALID_DATA
;
217 /* A movie requires at least one track. */
218 if( !file
->moov
->trak_list
.head
)
219 return LSMASH_ERR_INVALID_DATA
;
220 for( lsmash_entry_t
*entry
= file
->moov
->trak_list
.head
; entry
; entry
= entry
->next
)
222 isom_trak_t
*trak
= (isom_trak_t
*)entry
->data
;
229 || !trak
->mdia
->minf
->dinf
230 || !trak
->mdia
->minf
->dinf
->dref
231 || !trak
->mdia
->minf
->stbl
232 || !trak
->mdia
->minf
->stbl
->stsd
233 || (!trak
->mdia
->minf
->stbl
->stsz
&& !trak
->mdia
->minf
->stbl
->stz2
)
234 || !trak
->mdia
->minf
->stbl
->stts
235 || !trak
->mdia
->minf
->stbl
->stsc
236 || !trak
->mdia
->minf
->stbl
->stco
)
237 return LSMASH_ERR_INVALID_DATA
;
238 if( file
->qt_compatible
&& !trak
->mdia
->minf
->hdlr
)
239 return LSMASH_ERR_INVALID_DATA
;
240 isom_stbl_t
*stbl
= trak
->mdia
->minf
->stbl
;
241 if( !stbl
->stsd
->list
.head
)
242 return LSMASH_ERR_INVALID_DATA
;
244 && (!stbl
->stsd
->list
.head
245 || !stbl
->stts
->list
|| !stbl
->stts
->list
->head
246 || !stbl
->stsc
->list
|| !stbl
->stsc
->list
->head
247 || !stbl
->stco
->list
|| !stbl
->stco
->list
->head
) )
248 return LSMASH_ERR_INVALID_DATA
;
250 if( !file
->fragment
)
252 if( !file
->moov
->mvex
)
253 return LSMASH_ERR_INVALID_DATA
;
254 for( lsmash_entry_t
*entry
= file
->moov
->mvex
->trex_list
.head
; entry
; entry
= entry
->next
)
255 if( !entry
->data
) /* trex */
256 return LSMASH_ERR_INVALID_DATA
;
260 int isom_rearrange_data
263 lsmash_adhoc_remux_t
*remux
,
275 lsmash_bs_t
*bs
= file
->bs
;
278 while( read_num
== size
)
280 ret64
= lsmash_bs_write_seek( bs
, read_pos
, SEEK_SET
);
283 ret
= lsmash_bs_read_data( bs
, buf
[buf_switch
], &read_num
);
286 read_pos
= bs
->offset
;
288 ret64
= lsmash_bs_write_seek( bs
, write_pos
, SEEK_SET
);
291 ret
= lsmash_bs_write_data( bs
, buf
[buf_switch
], size
);
294 write_pos
= bs
->offset
;
296 remux
->func( remux
->param
, write_pos
, file_size
); // FIXME:
298 ret
= lsmash_bs_write_data( bs
, buf
[buf_switch
^ 0x1], read_num
);
302 remux
->func( remux
->param
, file_size
, file_size
); // FIXME:
306 static int isom_set_brands
309 lsmash_brand_type major_brand
,
310 uint32_t minor_version
,
311 lsmash_brand_type
*brands
,
315 if( brand_count
> 50 )
316 return LSMASH_ERR_FUNCTION_PARAM
; /* We support setting brands up to 50. */
317 if( major_brand
== 0 && (!brands
|| brand_count
== 0 || brands
[0] == 0) )
319 if( file
->flags
& LSMASH_FILE_MODE_INITIALIZATION
)
321 /* Absence of File Type Box means this file is a QuickTime or MP4 version 1 format file. */
322 isom_remove_box_by_itself( file
->ftyp
);
323 /* Anyway we use QTFF as a default file format. */
324 isom_clear_compat_flags( file
);
325 file
->qt_compatible
= 1;
329 /* The absence of the Segment Type Box is allowed.
330 * We set brands from the initialization segment after switching to this segment. */
331 for( lsmash_entry_t
*entry
= file
->styp_list
.head
; entry
; entry
= entry
->next
)
332 isom_remove_box_by_itself( entry
->data
);
333 if( file
->initializer
)
335 /* Copy flags for compatibility. */
336 memcpy( (int8_t *)file
+ COMPAT_FLAGS_OFFSET
, file
->initializer
, sizeof(lsmash_file_t
) - COMPAT_FLAGS_OFFSET
);
337 file
->isom_compatible
= 1;
338 file
->allow_moof_base
= 1;
339 file
->media_segment
= 1;
340 if( file
->min_isom_version
< 5 )
341 file
->min_isom_version
= 5;
342 if( file
->max_isom_version
< 6 )
343 file
->max_isom_version
= 6;
348 else if( major_brand
== 0 )
350 major_brand
= brands
[0];
351 lsmash_log( NULL
, LSMASH_LOG_WARNING
,
352 "major_brand is not specified. Use the first brand in the compatible brand list as major_brand.\n" );
357 if( file
->flags
& LSMASH_FILE_MODE_INITIALIZATION
)
359 /* Add File Type Box if absent yet. */
360 if( !file
->ftyp
&& !isom_add_ftyp( file
) )
361 return LSMASH_ERR_NAMELESS
;
366 /* Add Segment Type Box if absent yet. */
367 ftyp
= file
->styp_list
.head
&& file
->styp_list
.head
->data
368 ? (isom_styp_t
*)file
->styp_list
.head
->data
369 : isom_add_styp( file
);
371 return LSMASH_ERR_NAMELESS
;
373 /* Allocate an array of compatible brands.
374 * ISO/IEC 14496-12 doesn't forbid the absence of brands in the compatible brand list.
375 * For a reason of safety, however, we set at least one brand in the list. */
376 size_t alloc_size
= (brand_count
? brand_count
: 1) * sizeof(uint32_t);
377 lsmash_brand_type
*compatible_brands
;
378 if( !file
->compatible_brands
)
379 compatible_brands
= lsmash_malloc( alloc_size
);
381 compatible_brands
= lsmash_realloc( file
->compatible_brands
, alloc_size
);
382 if( !compatible_brands
)
383 return LSMASH_ERR_MEMORY_ALLOC
;
384 /* Set compatible brands. */
386 for( uint32_t i
= 0; i
< brand_count
; i
++ )
387 compatible_brands
[i
] = brands
[i
];
390 /* At least one compatible brand. */
391 compatible_brands
[0] = major_brand
;
394 file
->compatible_brands
= compatible_brands
;
395 /* Duplicate an array of compatible brands. */
396 lsmash_free( ftyp
->compatible_brands
);
397 ftyp
->compatible_brands
= lsmash_memdup( compatible_brands
, alloc_size
);
398 if( !ftyp
->compatible_brands
)
400 lsmash_freep( &file
->compatible_brands
);
401 return LSMASH_ERR_MEMORY_ALLOC
;
403 ftyp
->size
= ISOM_BASEBOX_COMMON_SIZE
+ 8 + brand_count
* 4;
404 ftyp
->major_brand
= major_brand
;
405 ftyp
->minor_version
= minor_version
;
406 ftyp
->brand_count
= brand_count
;
407 file
->brand_count
= brand_count
;
408 return isom_check_compatibility( file
);
411 /*******************************
413 *******************************/
415 void lsmash_discard_boxes
420 if( !root
|| !root
->file
)
422 isom_remove_all_extension_boxes( &root
->file
->extensions
);
427 const char *filename
,
429 lsmash_file_parameters_t
*param
432 if( !filename
|| !param
)
433 return LSMASH_ERR_FUNCTION_PARAM
;
434 char mode
[4] = { 0 };
435 lsmash_file_mode file_mode
= 0;
438 memcpy( mode
, "w+b", 4 );
439 file_mode
= LSMASH_FILE_MODE_WRITE
440 | LSMASH_FILE_MODE_BOX
441 | LSMASH_FILE_MODE_INITIALIZATION
442 | LSMASH_FILE_MODE_MEDIA
;
444 else if( open_mode
== 1 )
446 memcpy( mode
, "rb", 3 );
447 file_mode
= LSMASH_FILE_MODE_READ
;
450 return LSMASH_ERR_FUNCTION_PARAM
;
452 _setmode( _fileno( stdin
), _O_BINARY
);
453 _setmode( _fileno( stdout
), _O_BINARY
);
454 _setmode( _fileno( stderr
), _O_BINARY
);
458 if( !strcmp( filename
, "-" ) )
460 if( file_mode
& LSMASH_FILE_MODE_READ
)
465 else if( file_mode
& LSMASH_FILE_MODE_WRITE
)
469 file_mode
|= LSMASH_FILE_MODE_FRAGMENTED
;
473 stream
= lsmash_fopen( filename
, mode
);
475 return LSMASH_ERR_NAMELESS
;
476 memset( param
, 0, sizeof(lsmash_file_parameters_t
) );
477 param
->mode
= file_mode
;
478 param
->opaque
= (void *)stream
;
479 param
->read
= lsmash_fread_wrapper
;
480 param
->write
= lsmash_fwrite_wrapper
;
481 param
->seek
= seekable
? lsmash_fseek_wrapper
: NULL
;
482 param
->major_brand
= 0;
483 param
->brands
= NULL
;
484 param
->brand_count
= 0;
485 param
->minor_version
= 0;
486 param
->max_chunk_duration
= 0.5;
487 param
->max_async_tolerance
= 2.0;
488 param
->max_chunk_size
= 4 * 1024 * 1024;
489 param
->max_read_size
= 4 * 1024 * 1024;
493 int lsmash_close_file
495 lsmash_file_parameters_t
*param
499 return LSMASH_ERR_NAMELESS
;
502 int ret
= fclose( (FILE *)param
->opaque
);
503 param
->opaque
= NULL
;
504 return ret
== 0 ? 0 : LSMASH_ERR_UNKNOWN
;
507 lsmash_file_t
*lsmash_set_file
510 lsmash_file_parameters_t
*param
513 if( !root
|| !param
)
515 lsmash_file_t
*file
= isom_add_file( root
);
518 lsmash_bs_t
*bs
= lsmash_bs_create();
522 file
->flags
= param
->mode
;
523 file
->bs
->stream
= param
->opaque
;
524 file
->bs
->read
= param
->read
;
525 file
->bs
->write
= param
->write
;
526 file
->bs
->seek
= param
->seek
;
527 file
->bs
->unseekable
= (param
->seek
== NULL
);
528 file
->bs
->buffer
.max_size
= param
->max_read_size
;
529 file
->max_chunk_duration
= param
->max_chunk_duration
;
530 file
->max_async_tolerance
= LSMASH_MAX( param
->max_async_tolerance
, 2 * param
->max_chunk_duration
);
531 file
->max_chunk_size
= param
->max_chunk_size
;
532 if( (file
->flags
& LSMASH_FILE_MODE_WRITE
)
533 && (file
->flags
& LSMASH_FILE_MODE_BOX
) )
535 /* Construction of Segment Index Box requires seekability at our current implementation.
536 * If segment is not so large, data rearrangement can be avoided by buffering i.e. the
537 * seekability is not essential, but at present we don't support buffering of all materials
539 if( (file
->flags
& LSMASH_FILE_MODE_INDEX
) && file
->bs
->unseekable
)
541 /* Establish the fragment handler if required. */
542 if( file
->flags
& LSMASH_FILE_MODE_FRAGMENTED
)
544 file
->fragment
= lsmash_malloc_zero( sizeof(isom_fragment_manager_t
) );
545 if( !file
->fragment
)
547 file
->fragment
->first_moof_pos
= FIRST_MOOF_POS_UNDETERMINED
;
548 file
->fragment
->pool
= lsmash_create_entry_list();
549 if( !file
->fragment
->pool
)
552 else if( file
->bs
->unseekable
)
553 /* For unseekable output operations, LSMASH_FILE_MODE_FRAGMENTED shall be set. */
555 /* Establish file types. */
556 if( isom_set_brands( file
, param
->major_brand
,
557 param
->minor_version
,
558 param
->brands
, param
->brand_count
) < 0 )
560 /* Create the movie header if the initialization of the streams is required. */
561 if( (file
->flags
& LSMASH_FILE_MODE_INITIALIZATION
) && !isom_movie_create( file
) )
568 isom_remove_box_by_itself( file
);
572 int64_t lsmash_read_file
575 lsmash_file_parameters_t
*param
579 return (int64_t)LSMASH_ERR_FUNCTION_PARAM
;
581 return (int64_t)LSMASH_ERR_NAMELESS
;
582 int64_t ret
= LSMASH_ERR_NAMELESS
;
583 if( file
->flags
& (LSMASH_FILE_MODE_READ
| LSMASH_FILE_MODE_DUMP
) )
585 importer_t
*importer
= lsmash_importer_alloc();
587 return (int64_t)LSMASH_ERR_MEMORY_ALLOC
;
588 file
->importer
= importer
;
589 lsmash_importer_set_file( importer
, file
);
590 ret
= lsmash_importer_find( importer
, "ISOBMFF/QTFF", !file
->bs
->unseekable
);
598 isom_ftyp_t
*ftyp
= file
->ftyp
;
599 param
->major_brand
= ftyp
->major_brand
? ftyp
->major_brand
: ISOM_BRAND_TYPE_QT
;
600 param
->minor_version
= ftyp
->minor_version
;
601 param
->brands
= file
->compatible_brands
;
602 param
->brand_count
= file
->brand_count
;
604 else if( file
->styp_list
.head
&& file
->styp_list
.head
->data
)
607 isom_styp_t
*styp
= (isom_styp_t
*)file
->styp_list
.head
->data
;
608 param
->major_brand
= styp
->major_brand
? styp
->major_brand
: ISOM_BRAND_TYPE_QT
;
609 param
->minor_version
= styp
->minor_version
;
610 param
->brands
= file
->compatible_brands
;
611 param
->brand_count
= file
->brand_count
;
615 param
->major_brand
= file
->mp4_version1
? ISOM_BRAND_TYPE_MP41
: ISOM_BRAND_TYPE_QT
;
616 param
->minor_version
= 0;
617 param
->brands
= NULL
;
618 param
->brand_count
= 0;
625 int lsmash_activate_file
631 if( !root
|| !file
|| file
->root
!= root
)
632 return LSMASH_ERR_FUNCTION_PARAM
;
637 int lsmash_switch_media_segment
640 lsmash_file_t
*successor
,
641 lsmash_adhoc_remux_t
*remux
644 if( !root
|| !remux
)
645 return LSMASH_ERR_FUNCTION_PARAM
;
646 lsmash_file_t
*predecessor
= root
->file
;
647 if( !predecessor
|| !successor
648 || predecessor
== successor
649 || predecessor
->root
!= successor
->root
650 || !predecessor
->root
|| !successor
->root
651 || predecessor
->root
!= root
|| successor
->root
!= root
652 || (successor
->flags
& LSMASH_FILE_MODE_INITIALIZATION
)
653 || !(successor
->flags
& LSMASH_FILE_MODE_MEDIA
)
654 || !(predecessor
->flags
& LSMASH_FILE_MODE_WRITE
) || !(successor
->flags
& LSMASH_FILE_MODE_WRITE
)
655 || !(predecessor
->flags
& LSMASH_FILE_MODE_BOX
) || !(successor
->flags
& LSMASH_FILE_MODE_BOX
)
656 || !(predecessor
->flags
& LSMASH_FILE_MODE_FRAGMENTED
) || !(successor
->flags
& LSMASH_FILE_MODE_FRAGMENTED
)
657 || !(predecessor
->flags
& LSMASH_FILE_MODE_SEGMENT
) || !(successor
->flags
& LSMASH_FILE_MODE_SEGMENT
)
658 || (!(predecessor
->flags
& LSMASH_FILE_MODE_MEDIA
) && !(predecessor
->flags
& LSMASH_FILE_MODE_INITIALIZATION
)) )
659 return LSMASH_ERR_FUNCTION_PARAM
;
660 int ret
= isom_finish_final_fragment_movie( predecessor
, remux
);
663 if( predecessor
->flags
& LSMASH_FILE_MODE_INITIALIZATION
)
665 if( predecessor
->initializer
!= predecessor
)
666 return LSMASH_ERR_INVALID_DATA
;
667 successor
->initializer
= predecessor
;
670 successor
->initializer
= predecessor
->initializer
;
671 if( !lsmash_get_entry_data( &successor
->styp_list
, 1 ) )
673 ret
= isom_set_brands( successor
, 0, 0, NULL
, 0 );
675 return LSMASH_ERR_NAMELESS
;
677 successor
->fragment_count
= predecessor
->fragment_count
;
678 root
->file
= successor
;