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
)
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
);
91 importer
->class = &lsmash_importer_class
;
95 void lsmash_importer_destroy( importer_t
*importer
)
99 lsmash_file_t
*file
= importer
->file
;
100 if( importer
->funcs
.cleanup
)
101 importer
->funcs
.cleanup( importer
);
102 lsmash_remove_list( importer
->summaries
, lsmash_cleanup_summary
);
103 lsmash_free( importer
);
104 /* Prevent freeing this already freed importer in file's destructor again. */
106 file
->importer
= NULL
;
109 int lsmash_importer_set_file( importer_t
*importer
, lsmash_file_t
*file
)
112 || lsmash_activate_file( importer
->root
, file
) < 0
114 return LSMASH_ERR_NAMELESS
;
115 importer
->file
= file
;
116 importer
->bs
= file
->bs
;
117 file
->importer
= importer
;
121 void lsmash_importer_close( importer_t
*importer
)
125 if( !importer
->is_stdin
)
126 /* FIXME: stdin should not be closed by fclose(). */
127 lsmash_close_file( &importer
->file_param
);
128 lsmash_importer_destroy( importer
);
131 int lsmash_importer_find( importer_t
*importer
, const char *format
, int auto_detect
)
133 importer
->log_level
= LSMASH_LOG_QUIET
; /* Any error log is confusing for the probe step. */
134 const importer_functions
*funcs
;
135 int err
= LSMASH_ERR_NAMELESS
;
138 /* just rely on detector. */
139 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
141 importer
->class = &funcs
->class;
142 if( !funcs
->detectable
)
144 if( (err
= funcs
->probe( importer
)) == 0
145 || lsmash_bs_read_seek( importer
->bs
, 0, SEEK_SET
) != 0 )
151 /* needs name matching. */
152 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
154 importer
->class = &funcs
->class;
155 if( strcmp( importer
->class->name
, format
) )
157 if( (err
= funcs
->probe( importer
)) < 0 )
162 importer
->log_level
= LSMASH_LOG_INFO
;
165 importer
->class = &lsmash_importer_class
;
166 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to find the matched importer.\n" );
169 importer
->funcs
= *funcs
;
173 importer_t
*lsmash_importer_open( lsmash_root_t
*root
, const char *identifier
, const char *format
)
175 if( identifier
== NULL
)
177 int auto_detect
= (format
== NULL
|| !strcmp( format
, "auto" ));
178 importer_t
*importer
= lsmash_importer_alloc( root
);
181 importer
->is_adhoc_open
= 1;
182 /* Open an input 'stream'. */
183 if( !strcmp( identifier
, "-" ) )
185 /* special treatment for stdin */
188 lsmash_log( importer
, LSMASH_LOG_ERROR
, "auto importer detection on stdin is not supported.\n" );
191 importer
->is_stdin
= 1;
193 if( lsmash_open_file( identifier
, 1, &importer
->file_param
) < 0 )
195 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to open %s.\n", identifier
);
198 lsmash_file_t
*file
= lsmash_set_file( root
, &importer
->file_param
);
201 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to set opened file.\n" );
204 lsmash_importer_set_file( importer
, file
);
205 if( lsmash_importer_find( importer
, format
, auto_detect
) < 0 )
209 lsmash_importer_close( importer
);
213 /* 0 if success, positive if changed, negative if failed */
214 int lsmash_importer_get_access_unit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
216 if( !importer
|| !p_sample
)
217 return LSMASH_ERR_FUNCTION_PARAM
;
218 if( !importer
->funcs
.get_accessunit
)
219 return LSMASH_ERR_NAMELESS
;
221 return importer
->funcs
.get_accessunit( importer
, track_number
, p_sample
);
224 /* Return 0 if failed, otherwise succeeded. */
225 uint32_t lsmash_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
227 if( !importer
|| !importer
->funcs
.get_last_delta
)
229 return importer
->funcs
.get_last_delta( importer
, track_number
);
232 int lsmash_importer_construct_timeline( importer_t
*importer
, uint32_t track_number
)
235 return LSMASH_ERR_FUNCTION_PARAM
;
236 if( !importer
->funcs
.construct_timeline
)
237 return LSMASH_ERR_PATCH_WELCOME
;
238 return importer
->funcs
.construct_timeline( importer
, track_number
);
241 uint32_t lsmash_importer_get_track_count( importer_t
*importer
)
243 if( !importer
|| !importer
->summaries
)
245 return importer
->summaries
->entry_count
;
248 lsmash_summary_t
*lsmash_duplicate_summary( importer_t
*importer
, uint32_t track_number
)
252 lsmash_summary_t
*src_summary
= lsmash_get_entry_data( importer
->summaries
, track_number
);
255 lsmash_summary_t
*summary
= lsmash_create_summary( src_summary
->summary_type
);
258 lsmash_codec_specific_list_t
*opaque
= summary
->opaque
;
259 switch( src_summary
->summary_type
)
261 case LSMASH_SUMMARY_TYPE_VIDEO
:
262 *(lsmash_video_summary_t
*)summary
= *(lsmash_video_summary_t
*)src_summary
;
264 case LSMASH_SUMMARY_TYPE_AUDIO
:
265 *(lsmash_audio_summary_t
*)summary
= *(lsmash_audio_summary_t
*)src_summary
;
268 lsmash_cleanup_summary( summary
);
271 summary
->opaque
= opaque
;
272 for( lsmash_entry_t
*entry
= src_summary
->opaque
->list
.head
; entry
; entry
= entry
->next
)
274 lsmash_codec_specific_t
*src_specific
= (lsmash_codec_specific_t
*)entry
->data
;
277 lsmash_codec_specific_t
*dup
= isom_duplicate_codec_specific_data( src_specific
);
278 if( lsmash_add_entry( &summary
->opaque
->list
, dup
) < 0 )
280 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
281 lsmash_destroy_codec_specific_data( dup
);
288 int lsmash_importer_make_fake_movie( importer_t
*importer
)
290 if( !importer
|| !importer
->file
|| (importer
->file
->flags
& LSMASH_FILE_MODE_BOX
) )
291 return LSMASH_ERR_FUNCTION_PARAM
;
292 if( !isom_movie_create( importer
->file
) )
293 return LSMASH_ERR_NAMELESS
;
297 int lsmash_importer_make_fake_track( importer_t
*importer
, lsmash_media_type media_type
, uint32_t *track_ID
)
299 if( !importer
|| !importer
->file
|| (importer
->file
->flags
& LSMASH_FILE_MODE_BOX
) || !track_ID
)
300 return LSMASH_ERR_FUNCTION_PARAM
;
301 isom_trak_t
*trak
= isom_track_create( importer
->file
, media_type
);
305 || trak
->tkhd
->track_ID
== 0
307 || !trak
->mdia
->minf
)
309 err
= LSMASH_ERR_NAMELESS
;
312 if( (err
= isom_complement_data_reference( trak
->mdia
->minf
)) < 0 )
314 *track_ID
= trak
->tkhd
->track_ID
;
317 isom_remove_box_by_itself( trak
);
321 void lsmash_importer_break_fake_movie( importer_t
*importer
)
323 if( !importer
|| !importer
->file
)
325 isom_remove_box_by_itself( importer
->file
->moov
);