Mercurial > libavcodec.hg
annotate atrac1.c @ 12043:f9a0bd0888a4 libavcodec
mpegaudio: call ff_mpegaudiodec_init_mmx() only from float decoder
The mmx code is floating-point only, and this function does not know
from which decoder it is called. Without this change, the integer
decoder only "works" because the size of the context struct is smaller
in this case, and the mmx init function writes the function pointer
outside the allocated context.
author | mru |
---|---|
date | Thu, 01 Jul 2010 23:21:17 +0000 |
parents | 8b6f3d3b55cb |
children |
rev | line source |
---|---|
10157 | 1 /* |
2 * Atrac 1 compatible decoder | |
3 * Copyright (c) 2009 Maxim Poliakovski | |
4 * Copyright (c) 2009 Benjamin Larsson | |
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:
11560
diff
changeset
|
24 * @file |
10157 | 25 * Atrac 1 compatible decoder. |
10225
d884c0b7af2f
Mention SDDS so search engines will pick it up for when someone
banan
parents:
10224
diff
changeset
|
26 * This decoder handles raw ATRAC1 data and probably SDDS data. |
10157 | 27 */ |
28 | |
29 /* Many thanks to Tim Craig for all the help! */ | |
30 | |
31 #include <math.h> | |
32 #include <stddef.h> | |
33 #include <stdio.h> | |
34 | |
35 #include "avcodec.h" | |
36 #include "get_bits.h" | |
37 #include "dsputil.h" | |
11370 | 38 #include "fft.h" |
10157 | 39 |
40 #include "atrac.h" | |
41 #include "atrac1data.h" | |
42 | |
43 #define AT1_MAX_BFU 52 ///< max number of block floating units in a sound unit | |
44 #define AT1_SU_SIZE 212 ///< number of bytes in a sound unit | |
45 #define AT1_SU_SAMPLES 512 ///< number of samples in a sound unit | |
46 #define AT1_FRAME_SIZE AT1_SU_SIZE * 2 | |
47 #define AT1_SU_MAX_BITS AT1_SU_SIZE * 8 | |
48 #define AT1_MAX_CHANNELS 2 | |
49 | |
50 #define AT1_QMF_BANDS 3 | |
51 #define IDX_LOW_BAND 0 | |
52 #define IDX_MID_BAND 1 | |
53 #define IDX_HIGH_BAND 2 | |
54 | |
55 /** | |
56 * Sound unit struct, one unit is used per channel | |
57 */ | |
58 typedef struct { | |
59 int log2_block_count[AT1_QMF_BANDS]; ///< log2 number of blocks in a band | |
60 int num_bfus; ///< number of Block Floating Units | |
61 float* spectrum[2]; | |
11369 | 62 DECLARE_ALIGNED(16, float, spec1)[AT1_SU_SAMPLES]; ///< mdct buffer |
63 DECLARE_ALIGNED(16, float, spec2)[AT1_SU_SAMPLES]; ///< mdct buffer | |
64 DECLARE_ALIGNED(16, float, fst_qmf_delay)[46]; ///< delay line for the 1st stacked QMF filter | |
65 DECLARE_ALIGNED(16, float, snd_qmf_delay)[46]; ///< delay line for the 2nd stacked QMF filter | |
66 DECLARE_ALIGNED(16, float, last_qmf_delay)[256+23]; ///< delay line for the last stacked QMF filter | |
10157 | 67 } AT1SUCtx; |
68 | |
69 /** | |
70 * The atrac1 context, holds all needed parameters for decoding | |
71 */ | |
72 typedef struct { | |
73 AT1SUCtx SUs[AT1_MAX_CHANNELS]; ///< channel sound unit | |
11369 | 74 DECLARE_ALIGNED(16, float, spec)[AT1_SU_SAMPLES]; ///< the mdct spectrum buffer |
10185 | 75 |
11369 | 76 DECLARE_ALIGNED(16, float, low)[256]; |
77 DECLARE_ALIGNED(16, float, mid)[256]; | |
78 DECLARE_ALIGNED(16, float, high)[512]; | |
10157 | 79 float* bands[3]; |
11369 | 80 DECLARE_ALIGNED(16, float, out_samples)[AT1_MAX_CHANNELS][AT1_SU_SAMPLES]; |
10199 | 81 FFTContext mdct_ctx[3]; |
10157 | 82 int channels; |
83 DSPContext dsp; | |
84 } AT1Ctx; | |
85 | |
86 /** size of the transform in samples in the long mode for each QMF band */ | |
87 static const uint16_t samples_per_band[3] = {128, 128, 256}; | |
88 static const uint8_t mdct_long_nbits[3] = {7, 7, 8}; | |
89 | |
90 | |
10170 | 91 static void at1_imdct(AT1Ctx *q, float *spec, float *out, int nbits, |
92 int rev_spec) | |
10157 | 93 { |
10216 | 94 FFTContext* mdct_context = &q->mdct_ctx[nbits - 5 - (nbits > 6)]; |
10157 | 95 int transf_size = 1 << nbits; |
96 | |
97 if (rev_spec) { | |
98 int i; | |
10197 | 99 for (i = 0; i < transf_size / 2; i++) |
10170 | 100 FFSWAP(float, spec[i], spec[transf_size - 1 - i]); |
10157 | 101 } |
10170 | 102 ff_imdct_half(mdct_context, out, spec); |
10157 | 103 } |
104 | |
105 | |
106 static int at1_imdct_block(AT1SUCtx* su, AT1Ctx *q) | |
107 { | |
10197 | 108 int band_num, band_samples, log2_block_count, nbits, num_blocks, block_size; |
10198
78af613fc316
Fix embarassing typo in last commit: Restore mistakenly removed ','.
diego
parents:
10197
diff
changeset
|
109 unsigned int start_pos, ref_pos = 0, pos = 0; |
10157 | 110 |
10197 | 111 for (band_num = 0; band_num < AT1_QMF_BANDS; band_num++) { |
10266 | 112 float *prev_buf; |
113 int j; | |
114 | |
10157 | 115 band_samples = samples_per_band[band_num]; |
116 log2_block_count = su->log2_block_count[band_num]; | |
117 | |
118 /* number of mdct blocks in the current QMF band: 1 - for long mode */ | |
119 /* 4 for short mode(low/middle bands) and 8 for short mode(high band)*/ | |
120 num_blocks = 1 << log2_block_count; | |
121 | |
10266 | 122 if (num_blocks == 1) { |
10267 | 123 /* mdct block size in samples: 128 (long mode, low & mid bands), */ |
124 /* 256 (long mode, high band) and 32 (short mode, all bands) */ | |
125 block_size = band_samples >> log2_block_count; | |
10157 | 126 |
10267 | 127 /* calc transform size in bits according to the block_size_mode */ |
128 nbits = mdct_long_nbits[band_num] - log2_block_count; | |
10157 | 129 |
10267 | 130 if (nbits != 5 && nbits != 7 && nbits != 8) |
131 return -1; | |
10266 | 132 } else { |
133 block_size = 32; | |
134 nbits = 5; | |
135 } | |
10185 | 136 |
10267 | 137 start_pos = 0; |
138 prev_buf = &su->spectrum[1][ref_pos + band_samples - 16]; | |
139 for (j=0; j < num_blocks; j++) { | |
140 at1_imdct(q, &q->spec[pos], &su->spectrum[0][ref_pos + start_pos], nbits, band_num); | |
10157 | 141 |
10267 | 142 /* overlap and window */ |
143 q->dsp.vector_fmul_window(&q->bands[band_num][start_pos], prev_buf, | |
144 &su->spectrum[0][ref_pos + start_pos], ff_sine_32, 0, 16); | |
10185 | 145 |
10267 | 146 prev_buf = &su->spectrum[0][ref_pos+start_pos + 16]; |
147 start_pos += block_size; | |
148 pos += block_size; | |
149 } | |
10266 | 150 |
151 if (num_blocks == 1) | |
152 memcpy(q->bands[band_num] + 32, &su->spectrum[0][ref_pos + 16], 240 * sizeof(float)); | |
153 | |
10157 | 154 ref_pos += band_samples; |
155 } | |
156 | |
157 /* Swap buffers so the mdct overlap works */ | |
158 FFSWAP(float*, su->spectrum[0], su->spectrum[1]); | |
159 | |
160 return 0; | |
161 } | |
162 | |
10170 | 163 /** |
164 * Parse the block size mode byte | |
165 */ | |
10157 | 166 |
10170 | 167 static int at1_parse_bsm(GetBitContext* gb, int log2_block_cnt[AT1_QMF_BANDS]) |
10157 | 168 { |
169 int log2_block_count_tmp, i; | |
170 | |
10197 | 171 for (i = 0; i < 2; i++) { |
10157 | 172 /* low and mid band */ |
173 log2_block_count_tmp = get_bits(gb, 2); | |
174 if (log2_block_count_tmp & 1) | |
175 return -1; | |
10170 | 176 log2_block_cnt[i] = 2 - log2_block_count_tmp; |
10157 | 177 } |
178 | |
179 /* high band */ | |
180 log2_block_count_tmp = get_bits(gb, 2); | |
181 if (log2_block_count_tmp != 0 && log2_block_count_tmp != 3) | |
182 return -1; | |
10170 | 183 log2_block_cnt[IDX_HIGH_BAND] = 3 - log2_block_count_tmp; |
10157 | 184 |
185 skip_bits(gb, 2); | |
186 return 0; | |
187 } | |
188 | |
189 | |
10170 | 190 static int at1_unpack_dequant(GetBitContext* gb, AT1SUCtx* su, |
191 float spec[AT1_SU_SAMPLES]) | |
10157 | 192 { |
193 int bits_used, band_num, bfu_num, i; | |
10215
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
194 uint8_t idwls[AT1_MAX_BFU]; ///< the word length indexes for each BFU |
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
195 uint8_t idsfs[AT1_MAX_BFU]; ///< the scalefactor indexes for each BFU |
10157 | 196 |
197 /* parse the info byte (2nd byte) telling how much BFUs were coded */ | |
198 su->num_bfus = bfu_amount_tab1[get_bits(gb, 3)]; | |
199 | |
200 /* calc number of consumed bits: | |
201 num_BFUs * (idwl(4bits) + idsf(6bits)) + log2_block_count(8bits) + info_byte(8bits) | |
202 + info_byte_copy(8bits) + log2_block_count_copy(8bits) */ | |
203 bits_used = su->num_bfus * 10 + 32 + | |
204 bfu_amount_tab2[get_bits(gb, 2)] + | |
205 (bfu_amount_tab3[get_bits(gb, 3)] << 1); | |
206 | |
207 /* get word length index (idwl) for each BFU */ | |
10197 | 208 for (i = 0; i < su->num_bfus; i++) |
10215
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
209 idwls[i] = get_bits(gb, 4); |
10157 | 210 |
211 /* get scalefactor index (idsf) for each BFU */ | |
10197 | 212 for (i = 0; i < su->num_bfus; i++) |
10215
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
213 idsfs[i] = get_bits(gb, 6); |
10157 | 214 |
215 /* zero idwl/idsf for empty BFUs */ | |
216 for (i = su->num_bfus; i < AT1_MAX_BFU; i++) | |
10215
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
217 idwls[i] = idsfs[i] = 0; |
10157 | 218 |
219 /* read in the spectral data and reconstruct MDCT spectrum of this channel */ | |
10197 | 220 for (band_num = 0; band_num < AT1_QMF_BANDS; band_num++) { |
221 for (bfu_num = bfu_bands_t[band_num]; bfu_num < bfu_bands_t[band_num+1]; bfu_num++) { | |
10157 | 222 int pos; |
223 | |
224 int num_specs = specs_per_bfu[bfu_num]; | |
10215
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
225 int word_len = !!idwls[bfu_num] + idwls[bfu_num]; |
a43faa684a20
Move the scale factor and word length indexes to the stack.
banan
parents:
10199
diff
changeset
|
226 float scale_factor = sf_table[idsfs[bfu_num]]; |
10217 | 227 bits_used += word_len * num_specs; /* add number of bits consumed by current BFU */ |
10157 | 228 |
229 /* check for bitstream overflow */ | |
230 if (bits_used > AT1_SU_MAX_BITS) | |
231 return -1; | |
232 | |
233 /* get the position of the 1st spec according to the block size mode */ | |
234 pos = su->log2_block_count[band_num] ? bfu_start_short[bfu_num] : bfu_start_long[bfu_num]; | |
235 | |
236 if (word_len) { | |
10170 | 237 float max_quant = 1.0 / (float)((1 << (word_len - 1)) - 1); |
10157 | 238 |
10197 | 239 for (i = 0; i < num_specs; i++) { |
10157 | 240 /* read in a quantized spec and convert it to |
241 * signed int and then inverse quantization | |
242 */ | |
243 spec[pos+i] = get_sbits(gb, word_len) * scale_factor * max_quant; | |
244 } | |
245 } else { /* word_len = 0 -> empty BFU, zero all specs in the emty BFU */ | |
10197 | 246 memset(&spec[pos], 0, num_specs * sizeof(float)); |
10157 | 247 } |
248 } | |
249 } | |
250 | |
251 return 0; | |
252 } | |
253 | |
254 | |
11374 | 255 static void at1_subband_synthesis(AT1Ctx *q, AT1SUCtx* su, float *pOut) |
10157 | 256 { |
10197 | 257 float temp[256]; |
258 float iqmf_temp[512 + 46]; | |
10157 | 259 |
260 /* combine low and middle bands */ | |
261 atrac_iqmf(q->bands[0], q->bands[1], 128, temp, su->fst_qmf_delay, iqmf_temp); | |
262 | |
263 /* delay the signal of the high band by 23 samples */ | |
10197 | 264 memcpy( su->last_qmf_delay, &su->last_qmf_delay[256], sizeof(float) * 23); |
265 memcpy(&su->last_qmf_delay[23], q->bands[2], sizeof(float) * 256); | |
10157 | 266 |
267 /* combine (low + middle) and high bands */ | |
268 atrac_iqmf(temp, su->last_qmf_delay, 256, pOut, su->snd_qmf_delay, iqmf_temp); | |
269 } | |
270 | |
271 | |
10170 | 272 static int atrac1_decode_frame(AVCodecContext *avctx, void *data, |
273 int *data_size, AVPacket *avpkt) | |
10157 | 274 { |
275 const uint8_t *buf = avpkt->data; | |
10170 | 276 int buf_size = avpkt->size; |
277 AT1Ctx *q = avctx->priv_data; | |
10157 | 278 int ch, ret, i; |
279 GetBitContext gb; | |
280 float* samples = data; | |
281 | |
282 | |
283 if (buf_size < 212 * q->channels) { | |
284 av_log(q,AV_LOG_ERROR,"Not enought data to decode!\n"); | |
285 return -1; | |
286 } | |
287 | |
10197 | 288 for (ch = 0; ch < q->channels; ch++) { |
10157 | 289 AT1SUCtx* su = &q->SUs[ch]; |
290 | |
10197 | 291 init_get_bits(&gb, &buf[212 * ch], 212 * 8); |
10157 | 292 |
293 /* parse block_size_mode, 1st byte */ | |
10170 | 294 ret = at1_parse_bsm(&gb, su->log2_block_count); |
10157 | 295 if (ret < 0) |
296 return ret; | |
297 | |
298 ret = at1_unpack_dequant(&gb, su, q->spec); | |
299 if (ret < 0) | |
300 return ret; | |
301 | |
302 ret = at1_imdct_block(su, q); | |
303 if (ret < 0) | |
304 return ret; | |
305 at1_subband_synthesis(q, su, q->out_samples[ch]); | |
306 } | |
307 | |
11652
8b6f3d3b55cb
Move clipping of audio samples (for those codecs outputting float) from decoder
rbultje
parents:
11644
diff
changeset
|
308 /* interleave; FIXME, should create/use a DSP function */ |
10157 | 309 if (q->channels == 1) { |
310 /* mono */ | |
11652
8b6f3d3b55cb
Move clipping of audio samples (for those codecs outputting float) from decoder
rbultje
parents:
11644
diff
changeset
|
311 memcpy(samples, q->out_samples[0], AT1_SU_SAMPLES * 4); |
10157 | 312 } else { |
313 /* stereo */ | |
314 for (i = 0; i < AT1_SU_SAMPLES; i++) { | |
11652
8b6f3d3b55cb
Move clipping of audio samples (for those codecs outputting float) from decoder
rbultje
parents:
11644
diff
changeset
|
315 samples[i * 2] = q->out_samples[0][i]; |
8b6f3d3b55cb
Move clipping of audio samples (for those codecs outputting float) from decoder
rbultje
parents:
11644
diff
changeset
|
316 samples[i * 2 + 1] = q->out_samples[1][i]; |
10157 | 317 } |
318 } | |
319 | |
320 *data_size = q->channels * AT1_SU_SAMPLES * sizeof(*samples); | |
321 return avctx->block_align; | |
322 } | |
323 | |
324 | |
325 static av_cold int atrac1_decode_init(AVCodecContext *avctx) | |
326 { | |
327 AT1Ctx *q = avctx->priv_data; | |
328 | |
329 avctx->sample_fmt = SAMPLE_FMT_FLT; | |
330 | |
331 q->channels = avctx->channels; | |
332 | |
333 /* Init the mdct transforms */ | |
10197 | 334 ff_mdct_init(&q->mdct_ctx[0], 6, 1, -1.0/ (1 << 15)); |
335 ff_mdct_init(&q->mdct_ctx[1], 8, 1, -1.0/ (1 << 15)); | |
336 ff_mdct_init(&q->mdct_ctx[2], 9, 1, -1.0/ (1 << 15)); | |
10185 | 337 |
10827
3d011a01a6a0
Add support for hard-coded MDCT-related ff_sine_windows tables.
reimar
parents:
10267
diff
changeset
|
338 ff_init_ff_sine_windows(5); |
10157 | 339 |
340 atrac_generate_tables(); | |
341 | |
342 dsputil_init(&q->dsp, avctx); | |
343 | |
344 q->bands[0] = q->low; | |
345 q->bands[1] = q->mid; | |
346 q->bands[2] = q->high; | |
347 | |
348 /* Prepare the mdct overlap buffers */ | |
349 q->SUs[0].spectrum[0] = q->SUs[0].spec1; | |
350 q->SUs[0].spectrum[1] = q->SUs[0].spec2; | |
351 q->SUs[1].spectrum[0] = q->SUs[1].spec1; | |
352 q->SUs[1].spectrum[1] = q->SUs[1].spec2; | |
353 | |
354 return 0; | |
355 } | |
356 | |
10218 | 357 |
358 static av_cold int atrac1_decode_end(AVCodecContext * avctx) { | |
359 AT1Ctx *q = avctx->priv_data; | |
360 | |
361 ff_mdct_end(&q->mdct_ctx[0]); | |
362 ff_mdct_end(&q->mdct_ctx[1]); | |
363 ff_mdct_end(&q->mdct_ctx[2]); | |
364 return 0; | |
365 } | |
366 | |
367 | |
10157 | 368 AVCodec atrac1_decoder = { |
369 .name = "atrac1", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11374
diff
changeset
|
370 .type = AVMEDIA_TYPE_AUDIO, |
10157 | 371 .id = CODEC_ID_ATRAC1, |
372 .priv_data_size = sizeof(AT1Ctx), | |
373 .init = atrac1_decode_init, | |
10218 | 374 .close = atrac1_decode_end, |
10157 | 375 .decode = atrac1_decode_frame, |
376 .long_name = NULL_IF_CONFIG_SMALL("Atrac 1 (Adaptive TRansform Acoustic Coding)"), | |
377 }; |