1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Contributors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *****************************************************************************/
22 /* This file is available under an ISC license. */
24 #include "common/internal.h" /* must be placed first */
28 #define LSMASH_IMPORTER_INTERNAL
31 /***************************************************************************
33 ***************************************************************************/
34 static const lsmash_class_t lsmash_importer_class
=
37 offsetof( importer_t
, log_level
)
40 extern const importer_functions mp4sys_adts_importer
;
41 extern const importer_functions mp4sys_mp3_importer
;
42 extern const importer_functions amr_importer
;
43 extern const importer_functions ac3_importer
;
44 extern const importer_functions eac3_importer
;
45 extern const importer_functions mp4a_als_importer
;
46 extern const importer_functions dts_importer
;
47 extern const importer_functions wave_importer
;
48 extern const importer_functions h264_importer
;
49 extern const importer_functions hevc_importer
;
50 extern const importer_functions vc1_importer
;
51 extern const importer_functions isobm_importer
;
53 /******** importer listing table ********/
54 static const importer_functions
*importer_func_table
[] =
56 &mp4sys_adts_importer
,
71 /***************************************************************************
72 importer public interfaces
73 ***************************************************************************/
75 /******** importer public functions ********/
76 importer_t
*lsmash_importer_alloc( lsmash_root_t
*root
)
78 if( LSMASH_IS_NON_EXISTING_BOX( root
) )
80 importer_t
*importer
= (importer_t
*)lsmash_malloc_zero( sizeof(importer_t
) );
83 importer
->root
= root
;
84 importer
->summaries
= lsmash_create_entry_list();
85 if( !importer
->summaries
)
87 lsmash_destroy_root( importer
->root
);
88 lsmash_free( importer
);
94 void lsmash_importer_destroy( importer_t
*importer
)
98 lsmash_file_t
*file
= importer
->file
;
99 if( importer
->funcs
.cleanup
)
100 importer
->funcs
.cleanup( importer
);
101 lsmash_remove_list( importer
->summaries
, lsmash_cleanup_summary
);
102 lsmash_free( importer
);
103 /* Prevent freeing this already freed importer in file's destructor again. */
105 file
->importer
= NULL
;
108 int lsmash_importer_set_file( importer_t
*importer
, lsmash_file_t
*file
)
111 || lsmash_activate_file( importer
->root
, file
) < 0
113 return LSMASH_ERR_NAMELESS
;
114 importer
->file
= file
;
115 importer
->bs
= file
->bs
;
116 file
->importer
= importer
;
120 void lsmash_importer_close( importer_t
*importer
)
124 if( !importer
->is_stdin
)
125 /* FIXME: stdin should not be closed by fclose(). */
126 lsmash_close_file( &importer
->file_param
);
127 lsmash_importer_destroy( importer
);
130 int lsmash_importer_find( importer_t
*importer
, const char *format
, int auto_detect
)
132 importer
->log_level
= LSMASH_LOG_QUIET
; /* Any error log is confusing for the probe step. */
133 const importer_functions
*funcs
;
134 int err
= LSMASH_ERR_NAMELESS
;
137 /* just rely on detector. */
138 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
140 importer
->class = &funcs
->class;
141 if( !funcs
->detectable
)
143 if( (err
= funcs
->probe( importer
)) == 0
144 || lsmash_bs_read_seek( importer
->bs
, 0, SEEK_SET
) != 0 )
150 /* needs name matching. */
151 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
153 importer
->class = &funcs
->class;
154 if( strcmp( importer
->class->name
, format
) )
156 if( (err
= funcs
->probe( importer
)) < 0 )
161 importer
->log_level
= LSMASH_LOG_INFO
;
164 importer
->class = &lsmash_importer_class
;
165 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to find the matched importer.\n" );
168 importer
->funcs
= *funcs
;
172 importer_t
*lsmash_importer_open( lsmash_root_t
*root
, const char *identifier
, const char *format
)
174 if( identifier
== NULL
)
176 int auto_detect
= (format
== NULL
|| !strcmp( format
, "auto" ));
177 importer_t
*importer
= lsmash_importer_alloc( root
);
180 importer
->is_adhoc_open
= 1;
181 /* Open an input 'stream'. */
182 if( !strcmp( identifier
, "-" ) )
184 /* special treatment for stdin */
187 lsmash_log( importer
, LSMASH_LOG_ERROR
, "auto importer detection on stdin is not supported.\n" );
190 importer
->is_stdin
= 1;
192 if( lsmash_open_file( identifier
, 1, &importer
->file_param
) < 0 )
194 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to open %s.\n", identifier
);
197 lsmash_file_t
*file
= lsmash_set_file( root
, &importer
->file_param
);
198 if( LSMASH_IS_NON_EXISTING_BOX( file
) )
200 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to set opened file.\n" );
203 lsmash_importer_set_file( importer
, file
);
204 if( lsmash_importer_find( importer
, format
, auto_detect
) < 0 )
208 lsmash_importer_close( importer
);
212 /* 0 if success, positive if changed, negative if failed */
213 int lsmash_importer_get_access_unit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
215 if( !importer
|| !p_sample
)
216 return LSMASH_ERR_FUNCTION_PARAM
;
217 if( !importer
->funcs
.get_accessunit
)
218 return LSMASH_ERR_NAMELESS
;
220 return importer
->funcs
.get_accessunit( importer
, track_number
, p_sample
);
223 /* Return 0 if failed, otherwise succeeded. */
224 uint32_t lsmash_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
226 if( !importer
|| !importer
->funcs
.get_last_delta
)
228 return importer
->funcs
.get_last_delta( importer
, track_number
);
231 int lsmash_importer_construct_timeline( importer_t
*importer
, uint32_t track_number
)
234 return LSMASH_ERR_FUNCTION_PARAM
;
235 if( !importer
->funcs
.construct_timeline
)
236 return LSMASH_ERR_PATCH_WELCOME
;
237 return importer
->funcs
.construct_timeline( importer
, track_number
);
240 uint32_t lsmash_importer_get_track_count( importer_t
*importer
)
242 if( !importer
|| !importer
->summaries
)
244 return importer
->summaries
->entry_count
;
247 lsmash_summary_t
*lsmash_duplicate_summary( importer_t
*importer
, uint32_t track_number
)
251 lsmash_summary_t
*src_summary
= lsmash_get_entry_data( importer
->summaries
, track_number
);
254 lsmash_summary_t
*summary
= lsmash_create_summary( src_summary
->summary_type
);
257 lsmash_codec_specific_list_t
*opaque
= summary
->opaque
;
258 switch( src_summary
->summary_type
)
260 case LSMASH_SUMMARY_TYPE_VIDEO
:
261 *(lsmash_video_summary_t
*)summary
= *(lsmash_video_summary_t
*)src_summary
;
263 case LSMASH_SUMMARY_TYPE_AUDIO
:
264 *(lsmash_audio_summary_t
*)summary
= *(lsmash_audio_summary_t
*)src_summary
;
267 lsmash_cleanup_summary( summary
);
270 summary
->opaque
= opaque
;
271 for( lsmash_entry_t
*entry
= src_summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
273 lsmash_codec_specific_t
*src_specific
= (lsmash_codec_specific_t
*)entry
->data
;
276 lsmash_codec_specific_t
*dup
= isom_duplicate_codec_specific_data( src_specific
);
277 if( lsmash_add_entry( &summary
->opaque
->list
, dup
) < 0 )
279 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
280 lsmash_destroy_codec_specific_data( dup
);
287 int lsmash_importer_make_fake_movie( importer_t
*importer
)
289 if( !importer
|| (importer
->file
->flags
& LSMASH_FILE_MODE_BOX
) )
290 return LSMASH_ERR_FUNCTION_PARAM
;
291 if( LSMASH_IS_BOX_ADDITION_FAILURE( isom_movie_create( importer
->file
) ) )
292 return LSMASH_ERR_NAMELESS
;
296 int lsmash_importer_make_fake_track( importer_t
*importer
, lsmash_media_type media_type
, uint32_t *track_ID
)
298 if( !importer
|| (importer
->file
->flags
& LSMASH_FILE_MODE_BOX
) || track_ID
== 0 )
299 return LSMASH_ERR_FUNCTION_PARAM
;
300 isom_trak_t
*trak
= isom_track_create( importer
->file
, media_type
);
302 if( LSMASH_IS_NON_EXISTING_BOX( trak
->tkhd
)
303 || LSMASH_IS_NON_EXISTING_BOX( trak
->mdia
->minf
)
304 || trak
->tkhd
->track_ID
== 0 )
306 err
= LSMASH_ERR_NAMELESS
;
309 if( (err
= isom_complement_data_reference( trak
->mdia
->minf
)) < 0 )
311 *track_ID
= trak
->tkhd
->track_ID
;
314 isom_remove_box_by_itself( trak
);
318 void lsmash_importer_break_fake_movie( importer_t
*importer
)
322 isom_remove_box_by_itself( importer
->file
->moov
);