box: Initialize predefined children by non-existing box constants whenever
[L-SMASH.git] / importer / importer.c
blobd4af14610c2c27e21a28c201b0f79cb7af687670
1 /*****************************************************************************
2 * importer.c
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 */
26 #include <string.h>
28 #define LSMASH_IMPORTER_INTERNAL
29 #include "importer.h"
31 /***************************************************************************
32 importer classes
33 ***************************************************************************/
34 static const lsmash_class_t lsmash_importer_class =
36 "importer",
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,
57 &mp4sys_mp3_importer,
58 &amr_importer,
59 &ac3_importer,
60 &eac3_importer,
61 &mp4a_als_importer,
62 &dts_importer,
63 &wave_importer,
64 &h264_importer,
65 &hevc_importer,
66 &vc1_importer,
67 &isobm_importer,
68 NULL,
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 ) )
79 return NULL;
80 importer_t *importer = (importer_t *)lsmash_malloc_zero( sizeof(importer_t) );
81 if( !importer )
82 return NULL;
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 );
89 return NULL;
91 return importer;
94 void lsmash_importer_destroy( importer_t *importer )
96 if( !importer )
97 return;
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. */
104 if( file->importer )
105 file->importer = NULL;
108 int lsmash_importer_set_file( importer_t *importer, lsmash_file_t *file )
110 if( !importer
111 || lsmash_activate_file( importer->root, file ) < 0
112 || !file->bs )
113 return LSMASH_ERR_NAMELESS;
114 importer->file = file;
115 importer->bs = file->bs;
116 file->importer = importer;
117 return 0;
120 void lsmash_importer_close( importer_t *importer )
122 if( !importer )
123 return;
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;
135 if( auto_detect )
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 )
142 continue;
143 if( (err = funcs->probe( importer )) == 0
144 || lsmash_bs_read_seek( importer->bs, 0, SEEK_SET ) != 0 )
145 break;
148 else
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 ) )
155 continue;
156 if( (err = funcs->probe( importer )) < 0 )
157 funcs = NULL;
158 break;
161 importer->log_level = LSMASH_LOG_INFO;
162 if( !funcs )
164 importer->class = &lsmash_importer_class;
165 lsmash_log( importer, LSMASH_LOG_ERROR, "failed to find the matched importer.\n" );
167 else
168 importer->funcs = *funcs;
169 return err;
172 importer_t *lsmash_importer_open( lsmash_root_t *root, const char *identifier, const char *format )
174 if( identifier == NULL )
175 return NULL;
176 int auto_detect = (format == NULL || !strcmp( format, "auto" ));
177 importer_t *importer = lsmash_importer_alloc( root );
178 if( !importer )
179 return NULL;
180 importer->is_adhoc_open = 1;
181 /* Open an input 'stream'. */
182 if( !strcmp( identifier, "-" ) )
184 /* special treatment for stdin */
185 if( auto_detect )
187 lsmash_log( importer, LSMASH_LOG_ERROR, "auto importer detection on stdin is not supported.\n" );
188 goto fail;
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 );
195 goto fail;
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" );
201 goto fail;
203 lsmash_importer_set_file( importer, file );
204 if( lsmash_importer_find( importer, format, auto_detect ) < 0 )
205 goto fail;
206 return importer;
207 fail:
208 lsmash_importer_close( importer );
209 return NULL;
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;
219 *p_sample = NULL;
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 )
227 return 0;
228 return importer->funcs.get_last_delta( importer, track_number );
231 int lsmash_importer_construct_timeline( importer_t *importer, uint32_t track_number )
233 if( !importer )
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 )
243 return 0;
244 return importer->summaries->entry_count;
247 lsmash_summary_t *lsmash_duplicate_summary( importer_t *importer, uint32_t track_number )
249 if( !importer )
250 return NULL;
251 lsmash_summary_t *src_summary = lsmash_get_entry_data( importer->summaries, track_number );
252 if( !src_summary )
253 return NULL;
254 lsmash_summary_t *summary = lsmash_create_summary( src_summary->summary_type );
255 if( !summary )
256 return NULL;
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;
262 break;
263 case LSMASH_SUMMARY_TYPE_AUDIO :
264 *(lsmash_audio_summary_t *)summary = *(lsmash_audio_summary_t *)src_summary;
265 break;
266 default :
267 lsmash_cleanup_summary( summary );
268 return NULL;
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;
274 if( !src_specific )
275 continue;
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 );
281 return NULL;
284 return summary;
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;
293 return 0;
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 );
301 int err;
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;
307 goto fail;
309 if( (err = isom_complement_data_reference( trak->mdia->minf )) < 0 )
310 goto fail;
311 *track_ID = trak->tkhd->track_ID;
312 return 0;
313 fail:
314 isom_remove_box_by_itself( trak );
315 return err;
318 void lsmash_importer_break_fake_movie( importer_t *importer )
320 if( !importer )
321 return;
322 isom_remove_box_by_itself( importer->file->moov );