Mercurial > libavcodec.hg
annotate binkaudio.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | 7dd2a45249a9 |
children |
rev | line source |
---|---|
11067 | 1 /* |
2 * Bink Audio decoder | |
3 * Copyright (c) 2007-2010 Peter Ross (pross@xvid.org) | |
4 * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11582
diff
changeset
|
24 * @file |
11067 | 25 * Bink Audio decoder |
26 * | |
27 * Technical details here: | |
28 * http://wiki.multimedia.cx/index.php?title=Bink_Audio | |
29 */ | |
30 | |
31 #include "avcodec.h" | |
32 #define ALT_BITSTREAM_READER_LE | |
33 #include "get_bits.h" | |
34 #include "dsputil.h" | |
11370 | 35 #include "fft.h" |
36 | |
11067 | 37 extern const uint16_t ff_wma_critical_freqs[25]; |
38 | |
39 #define MAX_CHANNELS 2 | |
40 #define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) | |
41 | |
42 typedef struct { | |
43 AVCodecContext *avctx; | |
44 GetBitContext gb; | |
45 DSPContext dsp; | |
46 int first; | |
47 int channels; | |
48 int frame_len; ///< transform size (samples) | |
49 int overlap_len; ///< overlap size (samples) | |
50 int block_size; | |
51 int num_bands; | |
52 unsigned int *bands; | |
53 float root; | |
11369 | 54 DECLARE_ALIGNED(16, FFTSample, coeffs)[BINK_BLOCK_MAX_SIZE]; |
55 DECLARE_ALIGNED(16, short, previous)[BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block | |
11067 | 56 float *coeffs_ptr[MAX_CHANNELS]; ///< pointers to the coeffs arrays for float_to_int16_interleave |
57 union { | |
58 RDFTContext rdft; | |
59 DCTContext dct; | |
60 } trans; | |
61 } BinkAudioContext; | |
62 | |
63 | |
64 static av_cold int decode_init(AVCodecContext *avctx) | |
65 { | |
66 BinkAudioContext *s = avctx->priv_data; | |
67 int sample_rate = avctx->sample_rate; | |
68 int sample_rate_half; | |
69 int i; | |
70 int frame_len_bits; | |
71 | |
72 s->avctx = avctx; | |
73 dsputil_init(&s->dsp, avctx); | |
74 | |
75 /* determine frame length */ | |
76 if (avctx->sample_rate < 22050) { | |
77 frame_len_bits = 9; | |
78 } else if (avctx->sample_rate < 44100) { | |
79 frame_len_bits = 10; | |
80 } else { | |
81 frame_len_bits = 11; | |
82 } | |
83 s->frame_len = 1 << frame_len_bits; | |
84 | |
85 if (s->channels > MAX_CHANNELS) { | |
86 av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels); | |
87 return -1; | |
88 } | |
89 | |
90 if (avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT) { | |
91 // audio is already interleaved for the RDFT format variant | |
92 sample_rate *= avctx->channels; | |
93 s->frame_len *= avctx->channels; | |
94 s->channels = 1; | |
95 if (avctx->channels == 2) | |
96 frame_len_bits++; | |
97 } else { | |
98 s->channels = avctx->channels; | |
99 } | |
100 | |
101 s->overlap_len = s->frame_len / 16; | |
102 s->block_size = (s->frame_len - s->overlap_len) * s->channels; | |
103 sample_rate_half = (sample_rate + 1) / 2; | |
104 s->root = 2.0 / sqrt(s->frame_len); | |
105 | |
106 /* calculate number of bands */ | |
107 for (s->num_bands = 1; s->num_bands < 25; s->num_bands++) | |
108 if (sample_rate_half <= ff_wma_critical_freqs[s->num_bands - 1]) | |
109 break; | |
110 | |
111 s->bands = av_malloc((s->num_bands + 1) * sizeof(*s->bands)); | |
112 if (!s->bands) | |
113 return AVERROR(ENOMEM); | |
114 | |
115 /* populate bands data */ | |
116 s->bands[0] = 1; | |
117 for (i = 1; i < s->num_bands; i++) | |
118 s->bands[i] = ff_wma_critical_freqs[i - 1] * (s->frame_len / 2) / sample_rate_half; | |
119 s->bands[s->num_bands] = s->frame_len / 2; | |
120 | |
121 s->first = 1; | |
122 avctx->sample_fmt = SAMPLE_FMT_S16; | |
123 | |
124 for (i = 0; i < s->channels; i++) | |
125 s->coeffs_ptr[i] = s->coeffs + i * s->frame_len; | |
126 | |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
127 if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT) |
11391 | 128 ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R); |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
129 else if (CONFIG_BINKAUDIO_DCT_DECODER) |
11582
23cad4157bfb
Make code using 1d-DCT consistent with the API change
vitor
parents:
11560
diff
changeset
|
130 ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III); |
11067 | 131 else |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
132 return -1; |
11067 | 133 |
134 return 0; | |
135 } | |
136 | |
137 static float get_float(GetBitContext *gb) | |
138 { | |
139 int power = get_bits(gb, 5); | |
140 float f = ldexpf(get_bits_long(gb, 23), power - 23); | |
141 if (get_bits1(gb)) | |
142 f = -f; | |
143 return f; | |
144 } | |
145 | |
146 static const uint8_t rle_length_tab[16] = { | |
147 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64 | |
148 }; | |
149 | |
150 /** | |
151 * Decode Bink Audio block | |
152 * @param[out] out Output buffer (must contain s->block_size elements) | |
153 */ | |
154 static void decode_block(BinkAudioContext *s, short *out, int use_dct) | |
155 { | |
156 int ch, i, j, k; | |
157 float q, quant[25]; | |
158 int width, coeff; | |
159 GetBitContext *gb = &s->gb; | |
160 | |
161 if (use_dct) | |
162 skip_bits(gb, 2); | |
163 | |
164 for (ch = 0; ch < s->channels; ch++) { | |
165 FFTSample *coeffs = s->coeffs_ptr[ch]; | |
166 q = 0.0f; | |
167 coeffs[0] = get_float(gb) * s->root; | |
168 coeffs[1] = get_float(gb) * s->root; | |
169 | |
170 for (i = 0; i < s->num_bands; i++) { | |
171 /* constant is result of 0.066399999/log10(M_E) */ | |
172 int value = get_bits(gb, 8); | |
173 quant[i] = expf(FFMIN(value, 95) * 0.15289164787221953823f) * s->root; | |
174 } | |
175 | |
176 // find band (k) | |
177 for (k = 0; s->bands[k] < 1; k++) { | |
178 q = quant[k]; | |
179 } | |
180 | |
181 // parse coefficients | |
182 i = 2; | |
183 while (i < s->frame_len) { | |
184 if (get_bits1(gb)) { | |
185 j = i + rle_length_tab[get_bits(gb, 4)] * 8; | |
186 } else { | |
187 j = i + 8; | |
188 } | |
189 | |
190 j = FFMIN(j, s->frame_len); | |
191 | |
192 width = get_bits(gb, 4); | |
193 if (width == 0) { | |
194 memset(coeffs + i, 0, (j - i) * sizeof(*coeffs)); | |
195 i = j; | |
196 while (s->bands[k] * 2 < i) | |
197 q = quant[k++]; | |
198 } else { | |
199 while (i < j) { | |
200 if (s->bands[k] * 2 == i) | |
201 q = quant[k++]; | |
202 coeff = get_bits(gb, width); | |
203 if (coeff) { | |
204 if (get_bits1(gb)) | |
205 coeffs[i] = -q * coeff; | |
206 else | |
207 coeffs[i] = q * coeff; | |
208 } else { | |
209 coeffs[i] = 0.0f; | |
210 } | |
211 i++; | |
212 } | |
213 } | |
214 } | |
215 | |
11337
15dd07e86519
Perform coefficient transformations in Bink Audio DCT decoder (issue1770)
pross
parents:
11264
diff
changeset
|
216 if (CONFIG_BINKAUDIO_DCT_DECODER && use_dct) { |
15dd07e86519
Perform coefficient transformations in Bink Audio DCT decoder (issue1770)
pross
parents:
11264
diff
changeset
|
217 coeffs[0] /= 0.5; |
11067 | 218 ff_dct_calc (&s->trans.dct, coeffs); |
11337
15dd07e86519
Perform coefficient transformations in Bink Audio DCT decoder (issue1770)
pross
parents:
11264
diff
changeset
|
219 s->dsp.vector_fmul_scalar(coeffs, coeffs, s->frame_len / 2, s->frame_len); |
15dd07e86519
Perform coefficient transformations in Bink Audio DCT decoder (issue1770)
pross
parents:
11264
diff
changeset
|
220 } |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
221 else if (CONFIG_BINKAUDIO_RDFT_DECODER) |
11067 | 222 ff_rdft_calc(&s->trans.rdft, coeffs); |
223 } | |
224 | |
11461
908cc63498ec
Make binkaudio work with ff_float_to_int16_interleave_c (martin at martin dot st)
pross
parents:
11391
diff
changeset
|
225 if (s->dsp.float_to_int16_interleave == ff_float_to_int16_interleave_c) { |
908cc63498ec
Make binkaudio work with ff_float_to_int16_interleave_c (martin at martin dot st)
pross
parents:
11391
diff
changeset
|
226 for (i = 0; i < s->channels; i++) |
908cc63498ec
Make binkaudio work with ff_float_to_int16_interleave_c (martin at martin dot st)
pross
parents:
11391
diff
changeset
|
227 for (j = 0; j < s->frame_len; j++) |
908cc63498ec
Make binkaudio work with ff_float_to_int16_interleave_c (martin at martin dot st)
pross
parents:
11391
diff
changeset
|
228 s->coeffs_ptr[i][j] = 385.0 + s->coeffs_ptr[i][j]*(1.0/32767.0); |
908cc63498ec
Make binkaudio work with ff_float_to_int16_interleave_c (martin at martin dot st)
pross
parents:
11391
diff
changeset
|
229 } |
11067 | 230 s->dsp.float_to_int16_interleave(out, (const float **)s->coeffs_ptr, s->frame_len, s->channels); |
231 | |
232 if (!s->first) { | |
233 int count = s->overlap_len * s->channels; | |
234 int shift = av_log2(count); | |
235 for (i = 0; i < count; i++) { | |
236 out[i] = (s->previous[i] * (count - i) + out[i] * i) >> shift; | |
237 } | |
238 } | |
239 | |
240 memcpy(s->previous, out + s->block_size, | |
241 s->overlap_len * s->channels * sizeof(*out)); | |
242 | |
243 s->first = 0; | |
244 } | |
245 | |
246 static av_cold int decode_end(AVCodecContext *avctx) | |
247 { | |
248 BinkAudioContext * s = avctx->priv_data; | |
249 av_freep(&s->bands); | |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
250 if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT) |
11067 | 251 ff_rdft_end(&s->trans.rdft); |
11216
359c8ba0698e
Fix compilation of binkaudio_rdft when dct is disabled
daniel
parents:
11069
diff
changeset
|
252 else if (CONFIG_BINKAUDIO_DCT_DECODER) |
11067 | 253 ff_dct_end(&s->trans.dct); |
254 return 0; | |
255 } | |
256 | |
257 static void get_bits_align32(GetBitContext *s) | |
258 { | |
259 int n = (-get_bits_count(s)) & 31; | |
260 if (n) skip_bits(s, n); | |
261 } | |
262 | |
263 static int decode_frame(AVCodecContext *avctx, | |
264 void *data, int *data_size, | |
265 AVPacket *avpkt) | |
266 { | |
267 BinkAudioContext *s = avctx->priv_data; | |
268 const uint8_t *buf = avpkt->data; | |
269 int buf_size = avpkt->size; | |
270 short *samples = data; | |
271 short *samples_end = (short*)((uint8_t*)data + *data_size); | |
272 int reported_size; | |
273 GetBitContext *gb = &s->gb; | |
274 | |
275 init_get_bits(gb, buf, buf_size * 8); | |
276 | |
277 reported_size = get_bits_long(gb, 32); | |
278 while (get_bits_count(gb) / 8 < buf_size && | |
279 samples + s->block_size <= samples_end) { | |
280 decode_block(s, samples, avctx->codec->id == CODEC_ID_BINKAUDIO_DCT); | |
281 samples += s->block_size; | |
282 get_bits_align32(gb); | |
283 } | |
284 | |
11264
bfffb50b80bc
Use reported_size to truncate final Bink Audio frame
pross
parents:
11216
diff
changeset
|
285 *data_size = FFMIN(reported_size, (uint8_t*)samples - (uint8_t*)data); |
11067 | 286 return buf_size; |
287 } | |
288 | |
289 AVCodec binkaudio_rdft_decoder = { | |
290 "binkaudio_rdft", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11461
diff
changeset
|
291 AVMEDIA_TYPE_AUDIO, |
11067 | 292 CODEC_ID_BINKAUDIO_RDFT, |
293 sizeof(BinkAudioContext), | |
294 decode_init, | |
295 NULL, | |
296 decode_end, | |
297 decode_frame, | |
298 .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)") | |
299 }; | |
300 | |
301 AVCodec binkaudio_dct_decoder = { | |
302 "binkaudio_dct", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11461
diff
changeset
|
303 AVMEDIA_TYPE_AUDIO, |
11067 | 304 CODEC_ID_BINKAUDIO_DCT, |
305 sizeof(BinkAudioContext), | |
306 decode_init, | |
307 NULL, | |
308 decode_end, | |
309 decode_frame, | |
310 .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)") | |
311 }; |