1 /*****************************************************************************
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 */
27 #define LSMASH_IMPORTER_INTERNAL
30 /***************************************************************************
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"
41 uint64_t next_frame_pos
;
42 uint8_t buffer
[DTS_MAX_EXSS_SIZE
];
43 lsmash_multiple_buffers_t
*au_buffers
;
46 uint8_t *incomplete_au
;
47 uint32_t incomplete_au_length
;
51 static void remove_dts_importer( dts_importer_t
*dts_imp
)
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
) );
65 dts_info_t
*dts_info
= &dts_imp
->info
;
66 dts_info
->bits
= lsmash_bits_create( importer
->bs
);
69 lsmash_free( dts_imp
);
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
);
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
);
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
)
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
);
108 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to read data from the stream.\n" );
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
;
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
;
132 if( !info
->ddts_param_initialized
)
133 dts_update_specific_param( info
);
137 /* Parse substream frame. */
138 dts_substream_type prev_substream_type
= info
->substream_type
;
139 info
->substream_type
= dts_get_substream_type( info
);
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
)
148 dts_parse_frame
= dts_parse_core_substream
;
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" );
158 if( prev_substream_type
== DTS_SUBSTREAM_TYPE_EXTENSION
159 && info
->exss_index
<= prev_exss_index
)
161 dts_parse_frame
= dts_parse_extension_substream
;
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" );
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
)
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
);
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
);
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 )
220 if( current_status
== IMPORTER_CHANGE
)
221 summary
->max_au_length
= 0;
222 lsmash_sample_t
*sample
= lsmash_create_sample( dts_imp
->au_length
);
224 return LSMASH_ERR_MEMORY_ALLOC
;
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;
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
);
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
);
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) */
276 case 384000 : /* Invalid? (No reference in the spec) */
277 summary
->frequency
= 48000;
283 case 352800 : /* Invalid? (No reference in the spec) */
284 summary
->frequency
= 44100;
286 case 8000 : /* Invalid? (No reference in the spec) */
291 summary
->frequency
= 32000;
294 summary
->frequency
= 0;
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
);
304 static int dts_importer_probe( importer_t
*importer
)
306 dts_importer_t
*dts_imp
= create_dts_importer( importer
);
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
);
316 lsmash_audio_summary_t
*summary
= dts_create_summary( &dts_imp
->info
);
319 err
= LSMASH_ERR_NAMELESS
;
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
;
333 remove_dts_importer( dts_imp
);
334 importer
->info
= NULL
;
338 static uint32_t dts_importer_get_last_delta( importer_t
* importer
, uint32_t track_number
)
340 debug_if( !importer
|| !importer
->info
)
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
)
345 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_get_entry_data( importer
->summaries
, track_number
);
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
) },
356 dts_importer_get_accessunit
,
357 dts_importer_get_last_delta
,