print: Avoid Variable Length Arrays.
[L-SMASH.git] / importer / dts_imp.c
blob91a0120f2bb1fe6b31079694cba83b07343d5da8
1 /*****************************************************************************
2 * dts_imp.c
3 *****************************************************************************
4 * Copyright (C) 2012-2014 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 */
25 #include <string.h>
27 #define LSMASH_IMPORTER_INTERNAL
28 #include "importer.h"
30 /***************************************************************************
31 DTS importer
32 ETSI TS 102 114 V1.2.1 (2002-12)
33 ETSI TS 102 114 V1.3.1 (2011-08)
34 ETSI TS 102 114 V1.4.1 (2012-09)
35 ***************************************************************************/
36 #include "codecs/dts.h"
38 typedef struct
40 dts_info_t info;
41 uint64_t next_frame_pos;
42 uint8_t buffer[DTS_MAX_EXSS_SIZE];
43 lsmash_multiple_buffers_t *au_buffers;
44 uint8_t *au;
45 uint32_t au_length;
46 uint8_t *incomplete_au;
47 uint32_t incomplete_au_length;
48 uint32_t au_number;
49 } dts_importer_t;
51 static void remove_dts_importer( dts_importer_t *dts_imp )
53 if( !dts_imp )
54 return;
55 lsmash_destroy_multiple_buffers( dts_imp->au_buffers );
56 lsmash_bits_cleanup( dts_imp->info.bits );
57 lsmash_free( dts_imp );
60 static dts_importer_t *create_dts_importer( importer_t *importer )
62 dts_importer_t *dts_imp = (dts_importer_t *)lsmash_malloc_zero( sizeof(dts_importer_t) );
63 if( !dts_imp )
64 return NULL;
65 dts_info_t *dts_info = &dts_imp->info;
66 dts_info->bits = lsmash_bits_create( importer->bs );
67 if( !dts_info->bits )
69 lsmash_free( dts_imp );
70 return NULL;
72 dts_imp->au_buffers = lsmash_create_multiple_buffers( 2, DTS_MAX_EXSS_SIZE );
73 if( !dts_imp->au_buffers )
75 lsmash_bits_cleanup( dts_info->bits );
76 lsmash_free( dts_imp );
77 return NULL;
79 dts_imp->au = lsmash_withdraw_buffer( dts_imp->au_buffers, 1 );
80 dts_imp->incomplete_au = lsmash_withdraw_buffer( dts_imp->au_buffers, 2 );
81 dts_setup_parser( dts_info );
82 return dts_imp;
85 static void dts_importer_cleanup( importer_t *importer )
87 debug_if( importer && importer->info )
88 remove_dts_importer( importer->info );
91 static int dts_importer_get_next_accessunit_internal( importer_t *importer )
93 int au_completed = 0;
94 dts_importer_t *dts_imp = (dts_importer_t *)importer->info;
95 dts_info_t *info = &dts_imp->info;
96 lsmash_bs_t *bs = info->bits->bs;
97 while( !au_completed )
99 /* Read data from the stream if needed. */
100 dts_imp->next_frame_pos += info->frame_size;
101 lsmash_bs_read_seek( bs, dts_imp->next_frame_pos, SEEK_SET );
102 uint64_t remain_size = lsmash_bs_get_remaining_buffer_size( bs );
103 if( remain_size < DTS_MAX_EXSS_SIZE )
105 int err = lsmash_bs_read( bs, bs->buffer.max_size );
106 if( err < 0 )
108 lsmash_log( importer, LSMASH_LOG_ERROR, "failed to read data from the stream.\n" );
109 return err;
111 remain_size = lsmash_bs_get_remaining_buffer_size( bs );
113 memcpy( dts_imp->buffer, lsmash_bs_get_buffer_data( bs ), LSMASH_MIN( remain_size, DTS_MAX_EXSS_SIZE ) );
114 /* Check the remainder length of the buffer.
115 * If there is enough length, then parse the frame in it.
116 * The length 10 is the required byte length to get frame size. */
117 if( bs->eob || (bs->eof && remain_size < 10) )
119 /* Reached the end of stream. */
120 importer->status = IMPORTER_EOF;
121 au_completed = !!dts_imp->incomplete_au_length;
122 if( !au_completed )
124 /* No more access units in the stream. */
125 if( lsmash_bs_get_remaining_buffer_size( bs ) )
127 lsmash_log( importer, LSMASH_LOG_WARNING, "the stream is truncated at the end.\n" );
128 return LSMASH_ERR_INVALID_DATA;
130 return 0;
132 if( !info->ddts_param_initialized )
133 dts_update_specific_param( info );
135 else
137 /* Parse substream frame. */
138 dts_substream_type prev_substream_type = info->substream_type;
139 info->substream_type = dts_get_substream_type( info );
140 int err;
141 int (*dts_parse_frame)( dts_info_t * ) = NULL;
142 switch( info->substream_type )
144 /* Decide substream frame parser and check if this frame and the previous frame belong to the same AU. */
145 case DTS_SUBSTREAM_TYPE_CORE :
146 if( prev_substream_type != DTS_SUBSTREAM_TYPE_NONE )
147 au_completed = 1;
148 dts_parse_frame = dts_parse_core_substream;
149 break;
150 case DTS_SUBSTREAM_TYPE_EXTENSION :
152 uint8_t prev_exss_index = info->exss_index;
153 if( (err = dts_get_exss_index( info, &info->exss_index )) < 0 )
155 lsmash_log( importer, LSMASH_LOG_ERROR, "failed to get the index of an extension substream.\n" );
156 return err;
158 if( prev_substream_type == DTS_SUBSTREAM_TYPE_EXTENSION
159 && info->exss_index <= prev_exss_index )
160 au_completed = 1;
161 dts_parse_frame = dts_parse_extension_substream;
162 break;
164 default :
165 lsmash_log( importer, LSMASH_LOG_ERROR, "unknown substream type is detected.\n" );
166 return LSMASH_ERR_NAMELESS;
168 if( !info->ddts_param_initialized && au_completed )
169 dts_update_specific_param( info );
170 info->frame_size = 0;
171 if( (err = dts_parse_frame( info )) < 0 )
173 lsmash_log( importer, LSMASH_LOG_ERROR, "failed to parse a frame.\n" );
174 return err;
177 if( au_completed )
179 memcpy( dts_imp->au, dts_imp->incomplete_au, dts_imp->incomplete_au_length );
180 dts_imp->au_length = dts_imp->incomplete_au_length;
181 dts_imp->incomplete_au_length = 0;
182 info->exss_count = (info->substream_type == DTS_SUBSTREAM_TYPE_EXTENSION);
183 if( importer->status == IMPORTER_EOF )
184 break;
186 /* Increase buffer size to store AU if short. */
187 if( dts_imp->incomplete_au_length + info->frame_size > dts_imp->au_buffers->buffer_size )
189 lsmash_multiple_buffers_t *temp = lsmash_resize_multiple_buffers( dts_imp->au_buffers,
190 dts_imp->au_buffers->buffer_size + DTS_MAX_EXSS_SIZE );
191 if( !temp )
192 return LSMASH_ERR_MEMORY_ALLOC;
193 dts_imp->au_buffers = temp;
194 dts_imp->au = lsmash_withdraw_buffer( dts_imp->au_buffers, 1 );
195 dts_imp->incomplete_au = lsmash_withdraw_buffer( dts_imp->au_buffers, 2 );
197 /* Append frame data. */
198 memcpy( dts_imp->incomplete_au + dts_imp->incomplete_au_length, dts_imp->buffer, info->frame_size );
199 dts_imp->incomplete_au_length += info->frame_size;
201 return bs->error ? LSMASH_ERR_NAMELESS : 0;
204 static int dts_importer_get_accessunit( importer_t *importer, uint32_t track_number, lsmash_sample_t **p_sample )
206 if( !importer->info )
207 return LSMASH_ERR_NAMELESS;
208 if( track_number != 1 )
209 return LSMASH_ERR_FUNCTION_PARAM;
210 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_get_entry_data( importer->summaries, track_number );
211 if( !summary )
212 return LSMASH_ERR_NAMELESS;
213 dts_importer_t *dts_imp = (dts_importer_t *)importer->info;
214 dts_info_t *info = &dts_imp->info;
215 importer_status current_status = importer->status;
216 if( current_status == IMPORTER_ERROR )
217 return LSMASH_ERR_NAMELESS;
218 if( current_status == IMPORTER_EOF && dts_imp->au_length == 0 )
219 return IMPORTER_EOF;
220 if( current_status == IMPORTER_CHANGE )
221 summary->max_au_length = 0;
222 lsmash_sample_t *sample = lsmash_create_sample( dts_imp->au_length );
223 if( !sample )
224 return LSMASH_ERR_MEMORY_ALLOC;
225 *p_sample = sample;
226 memcpy( sample->data, dts_imp->au, dts_imp->au_length );
227 sample->length = dts_imp->au_length;
228 sample->dts = dts_imp->au_number++ * summary->samples_in_frame;
229 sample->cts = sample->dts;
230 sample->prop.ra_flags = ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC;
231 sample->prop.pre_roll.distance = !!(info->flags & DTS_EXT_SUBSTREAM_LBR_FLAG); /* MDCT */
232 if( importer->status == IMPORTER_EOF )
234 dts_imp->au_length = 0;
235 return 0;
237 if( dts_importer_get_next_accessunit_internal( importer ) < 0 )
238 importer->status = IMPORTER_ERROR;
239 return current_status;
242 static lsmash_audio_summary_t *dts_create_summary( dts_info_t *info )
244 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO );
245 if( !summary )
246 return NULL;
247 lsmash_dts_specific_parameters_t *param = &info->ddts_param;
248 lsmash_codec_specific_t *specific = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_AUDIO_DTS,
249 LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED );
250 specific->data.unstructured = lsmash_create_dts_specific_info( param, &specific->size );
251 if( !specific->data.unstructured
252 || lsmash_add_entry( &summary->opaque->list, specific ) < 0 )
254 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
255 lsmash_destroy_codec_specific_data( specific );
256 return NULL;
258 /* The CODEC identifiers probably should not be the combination of 'mp4a' and
259 * the objectTypeIndications for DTS audio since there is no public specification
260 * which defines the encapsulation of the stream as the MPEG-4 Audio context yet.
261 * In the world, there are muxers which is using such doubtful implementation.
262 * The objectTypeIndications are registered at MP4RA, but this does not always
263 * mean we can mux by using those objectTypeIndications.
264 * If available, there shall be the specification which defines the existence of
265 * DecoderSpecificInfo and its semantics, and what access unit consists of. */
266 summary->sample_type = lsmash_dts_get_codingname( param );
267 summary->aot = MP4A_AUDIO_OBJECT_TYPE_NULL; /* make no sense */
268 summary->sbr_mode = MP4A_AAC_SBR_NOT_SPECIFIED; /* make no sense */
269 switch( param->DTSSamplingFrequency )
271 case 12000 : /* Invalid? (No reference in the spec) */
272 case 24000 :
273 case 48000 :
274 case 96000 :
275 case 192000 :
276 case 384000 : /* Invalid? (No reference in the spec) */
277 summary->frequency = 48000;
278 break;
279 case 22050 :
280 case 44100 :
281 case 88200 :
282 case 176400 :
283 case 352800 : /* Invalid? (No reference in the spec) */
284 summary->frequency = 44100;
285 break;
286 case 8000 : /* Invalid? (No reference in the spec) */
287 case 16000 :
288 case 32000 :
289 case 64000 :
290 case 128000 :
291 summary->frequency = 32000;
292 break;
293 default :
294 summary->frequency = 0;
295 break;
297 summary->samples_in_frame = (summary->frequency * info->frame_duration) / param->DTSSamplingFrequency;
298 summary->max_au_length = DTS_MAX_CORE_SIZE + DTS_MAX_NUM_EXSS * DTS_MAX_EXSS_SIZE;
299 summary->sample_size = param->pcmSampleDepth;
300 summary->channels = dts_get_max_channel_count( info );
301 return summary;
304 static int dts_importer_probe( importer_t *importer )
306 dts_importer_t *dts_imp = create_dts_importer( importer );
307 if( !dts_imp )
308 return LSMASH_ERR_MEMORY_ALLOC;
309 lsmash_bits_t *bits = dts_imp->info.bits;
310 lsmash_bs_t *bs = bits->bs;
311 bs->buffer.max_size = DTS_MAX_EXSS_SIZE;
312 importer->info = dts_imp;
313 int err = dts_importer_get_next_accessunit_internal( importer );
314 if( err < 0 )
315 goto fail;
316 lsmash_audio_summary_t *summary = dts_create_summary( &dts_imp->info );
317 if( !summary )
319 err = LSMASH_ERR_NAMELESS;
320 goto fail;
322 if( importer->status != IMPORTER_EOF )
323 importer->status = IMPORTER_OK;
324 dts_imp->au_number = 0;
325 if( lsmash_add_entry( importer->summaries, summary ) < 0 )
327 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
328 err = LSMASH_ERR_MEMORY_ALLOC;
329 goto fail;
331 return 0;
332 fail:
333 remove_dts_importer( dts_imp );
334 importer->info = NULL;
335 return err;
338 static uint32_t dts_importer_get_last_delta( importer_t* importer, uint32_t track_number )
340 debug_if( !importer || !importer->info )
341 return 0;
342 dts_importer_t *dts_imp = (dts_importer_t *)importer->info;
343 if( !dts_imp || track_number != 1 || importer->status != IMPORTER_EOF || dts_imp->au_length )
344 return 0;
345 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_get_entry_data( importer->summaries, track_number );
346 if( !summary )
347 return 0;
348 return (summary->frequency * dts_imp->info.frame_duration) / dts_imp->info.ddts_param.DTSSamplingFrequency;
351 const importer_functions dts_importer =
353 { "DTS Coherent Acoustics", offsetof( importer_t, log_level ) },
355 dts_importer_probe,
356 dts_importer_get_accessunit,
357 dts_importer_get_last_delta,
358 dts_importer_cleanup