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_list_create( lsmash_cleanup_summary
);
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_list_destroy( importer
->summaries
);
102 lsmash_free( importer
);
103 /* Prevent freeing this already freed importer in file's destructor again. */
104 if( file
&& file
->importer
)
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 lsmash_close_file( &importer
->file_param
);
125 lsmash_importer_destroy( importer
);
128 int lsmash_importer_find( importer_t
*importer
, const char *format
, int auto_detect
)
130 importer
->log_level
= LSMASH_LOG_QUIET
; /* Any error log is confusing for the probe step. */
131 const importer_functions
*funcs
;
132 int err
= LSMASH_ERR_NAMELESS
;
135 /* just rely on detector. */
136 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
138 importer
->class = &funcs
->class;
139 if( !funcs
->detectable
)
141 if( (err
= funcs
->probe( importer
)) == 0
142 || lsmash_bs_read_seek( importer
->bs
, 0, SEEK_SET
) != 0 )
148 /* needs name matching. */
149 for( int i
= 0; (funcs
= importer_func_table
[i
]) != NULL
; i
++ )
151 importer
->class = &funcs
->class;
152 if( strcmp( importer
->class->name
, format
) )
154 if( (err
= funcs
->probe( importer
)) < 0 )
159 importer
->log_level
= LSMASH_LOG_INFO
;
162 importer
->class = &lsmash_importer_class
;
163 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to find the matched importer.\n" );
166 importer
->funcs
= *funcs
;
170 importer_t
*lsmash_importer_open( lsmash_root_t
*root
, const char *identifier
, const char *format
)
172 if( identifier
== NULL
)
174 int auto_detect
= (format
== NULL
|| !strcmp( format
, "auto" ));
175 importer_t
*importer
= lsmash_importer_alloc( root
);
178 importer
->is_adhoc_open
= 1;
179 /* Open an input 'stream'. */
180 if( !strcmp( identifier
, "-" ) )
182 /* special treatment for stdin */
185 lsmash_log( importer
, LSMASH_LOG_ERROR
, "auto importer detection on stdin is not supported.\n" );
189 if( lsmash_open_file( identifier
, 1, &importer
->file_param
) < 0 )
191 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to open %s.\n", identifier
);
194 lsmash_file_t
*file
= lsmash_set_file( root
, &importer
->file_param
);
195 if( LSMASH_IS_NON_EXISTING_BOX( file
) )
197 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to set opened file.\n" );
200 lsmash_importer_set_file( importer
, file
);
201 if( lsmash_importer_find( importer
, format
, auto_detect
) < 0 )
205 lsmash_importer_close( importer
);
209 /* 0 if success, positive if changed, negative if failed */
210 int lsmash_importer_get_access_unit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
212 if( !importer
|| !p_sample
)
213 return LSMASH_ERR_FUNCTION_PARAM
;
214 if( !importer
->funcs
.get_accessunit
)
215 return LSMASH_ERR_NAMELESS
;
217 return importer
->funcs
.get_accessunit( importer
, track_number
, p_sample
);
220 /* Return 0 if failed, otherwise succeeded. */
221 uint32_t lsmash_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
223 if( !importer
|| !importer
->funcs
.get_last_delta
)
225 return importer
->funcs
.get_last_delta( importer
, track_number
);
228 int lsmash_importer_construct_timeline( importer_t
*importer
, uint32_t track_number
)
231 return LSMASH_ERR_FUNCTION_PARAM
;
232 if( !importer
->funcs
.construct_timeline
)
233 return LSMASH_ERR_PATCH_WELCOME
;
234 return importer
->funcs
.construct_timeline( importer
, track_number
);
237 uint32_t lsmash_importer_get_track_count( importer_t
*importer
)
239 if( !importer
|| !importer
->summaries
)
241 return importer
->summaries
->entry_count
;
244 lsmash_summary_t
*lsmash_duplicate_summary( importer_t
*importer
, uint32_t track_number
)
248 lsmash_summary_t
*src_summary
= lsmash_list_get_entry_data( importer
->summaries
, track_number
);
251 lsmash_summary_t
*summary
= lsmash_create_summary( src_summary
->summary_type
);
254 lsmash_codec_specific_list_t
*opaque
= summary
->opaque
;
255 switch( src_summary
->summary_type
)
257 case LSMASH_SUMMARY_TYPE_VIDEO
:
258 *(lsmash_video_summary_t
*)summary
= *(lsmash_video_summary_t
*)src_summary
;
260 case LSMASH_SUMMARY_TYPE_AUDIO
:
261 *(lsmash_audio_summary_t
*)summary
= *(lsmash_audio_summary_t
*)src_summary
;
263 case LSMASH_SUMMARY_TYPE_HINT
:
264 *(lsmash_hint_summary_t
*)summary
= *(lsmash_hint_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_list_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
);