list: Decide the entry eliminator of list at its initialization.
[L-SMASH.git] / importer / dts_imp.c
blobcba43d47fbab59a315d7e5a43f4682db7e2748a7
1 /*****************************************************************************
2 * dts_imp.c
3 *****************************************************************************
4 * Copyright (C) 2012-2017 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_list_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 if( !specific )
252 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
253 return NULL;
255 specific->data.unstructured = lsmash_create_dts_specific_info( param, &specific->size );
256 if( !specific->data.unstructured
257 || lsmash_list_add_entry( &summary->opaque->list, specific ) < 0 )
259 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
260 lsmash_destroy_codec_specific_data( specific );
261 return NULL;
263 /* The CODEC identifiers probably should not be the combination of 'mp4a' and
264 * the objectTypeIndications for DTS audio since there is no public specification
265 * which defines the encapsulation of the stream as the MPEG-4 Audio context yet.
266 * In the world, there are muxers which is using such doubtful implementation.
267 * The objectTypeIndications are registered at MP4RA, but this does not always
268 * mean we can mux by using those objectTypeIndications.
269 * If available, there shall be the specification which defines the existence of
270 * DecoderSpecificInfo and its semantics, and what access unit consists of. */
271 summary->sample_type = lsmash_dts_get_codingname( param );
272 summary->aot = MP4A_AUDIO_OBJECT_TYPE_NULL; /* make no sense */
273 summary->sbr_mode = MP4A_AAC_SBR_NOT_SPECIFIED; /* make no sense */
274 switch( param->DTSSamplingFrequency )
276 case 12000 : /* Invalid? (No reference in the spec) */
277 case 24000 :
278 case 48000 :
279 case 96000 :
280 case 192000 :
281 case 384000 : /* Invalid? (No reference in the spec) */
282 summary->frequency = 48000;
283 break;
284 case 22050 :
285 case 44100 :
286 case 88200 :
287 case 176400 :
288 case 352800 : /* Invalid? (No reference in the spec) */
289 summary->frequency = 44100;
290 break;
291 case 8000 : /* Invalid? (No reference in the spec) */
292 case 16000 :
293 case 32000 :
294 case 64000 :
295 case 128000 :
296 summary->frequency = 32000;
297 break;
298 default :
299 summary->frequency = 0;
300 break;
302 summary->samples_in_frame = (summary->frequency * info->frame_duration) / param->DTSSamplingFrequency;
303 summary->max_au_length = DTS_MAX_CORE_SIZE + DTS_MAX_NUM_EXSS * DTS_MAX_EXSS_SIZE;
304 summary->sample_size = param->pcmSampleDepth;
305 summary->channels = dts_get_max_channel_count( info );
306 return summary;
309 static int dts_importer_probe( importer_t *importer )
311 dts_importer_t *dts_imp = create_dts_importer( importer );
312 if( !dts_imp )
313 return LSMASH_ERR_MEMORY_ALLOC;
314 lsmash_bits_t *bits = dts_imp->info.bits;
315 lsmash_bs_t *bs = bits->bs;
316 bs->buffer.max_size = DTS_MAX_EXSS_SIZE;
317 importer->info = dts_imp;
318 int err = dts_importer_get_next_accessunit_internal( importer );
319 if( err < 0 )
320 goto fail;
321 lsmash_audio_summary_t *summary = dts_create_summary( &dts_imp->info );
322 if( !summary )
324 err = LSMASH_ERR_NAMELESS;
325 goto fail;
327 if( importer->status != IMPORTER_EOF )
328 importer->status = IMPORTER_OK;
329 dts_imp->au_number = 0;
330 if( lsmash_list_add_entry( importer->summaries, summary ) < 0 )
332 lsmash_cleanup_summary( (lsmash_summary_t *)summary );
333 err = LSMASH_ERR_MEMORY_ALLOC;
334 goto fail;
336 return 0;
337 fail:
338 remove_dts_importer( dts_imp );
339 importer->info = NULL;
340 return err;
343 static uint32_t dts_importer_get_last_delta( importer_t* importer, uint32_t track_number )
345 debug_if( !importer || !importer->info )
346 return 0;
347 dts_importer_t *dts_imp = (dts_importer_t *)importer->info;
348 if( !dts_imp || track_number != 1 || importer->status != IMPORTER_EOF || dts_imp->au_length )
349 return 0;
350 lsmash_audio_summary_t *summary = (lsmash_audio_summary_t *)lsmash_list_get_entry_data( importer->summaries, track_number );
351 if( !summary )
352 return 0;
353 return (summary->frequency * dts_imp->info.frame_duration) / dts_imp->info.ddts_param.DTSSamplingFrequency;
356 const importer_functions dts_importer =
358 { "DTS Coherent Acoustics", offsetof( importer_t, log_level ) },
360 dts_importer_probe,
361 dts_importer_get_accessunit,
362 dts_importer_get_last_delta,
363 dts_importer_cleanup