1 |
|
|
/* |
2 |
|
|
* ATRAC3+ compatible decoder |
3 |
|
|
* |
4 |
|
|
* Copyright (c) 2010-2013 Maxim Poliakovski |
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 |
|
|
/** |
24 |
|
|
* @file |
25 |
|
|
* Sony ATRAC3+ compatible decoder. |
26 |
|
|
* |
27 |
|
|
* Container formats used to store its data: |
28 |
|
|
* RIFF WAV (.at3) and Sony OpenMG (.oma, .aa3). |
29 |
|
|
* |
30 |
|
|
* Technical description of this codec can be found here: |
31 |
|
|
* http://wiki.multimedia.cx/index.php?title=ATRAC3plus |
32 |
|
|
* |
33 |
|
|
* Kudos to Benjamin Larsson and Michael Karcher |
34 |
|
|
* for their precious technical help! |
35 |
|
|
*/ |
36 |
|
|
|
37 |
|
|
#include <stdint.h> |
38 |
|
|
#include <string.h> |
39 |
|
|
|
40 |
|
|
#include "libavutil/channel_layout.h" |
41 |
|
|
#include "libavutil/float_dsp.h" |
42 |
|
|
#include "libavutil/mem_internal.h" |
43 |
|
|
#include "libavutil/thread.h" |
44 |
|
|
#include "avcodec.h" |
45 |
|
|
#include "get_bits.h" |
46 |
|
|
#include "internal.h" |
47 |
|
|
#include "atrac.h" |
48 |
|
|
#include "atrac3plus.h" |
49 |
|
|
|
50 |
|
|
typedef struct ATRAC3PContext { |
51 |
|
|
GetBitContext gb; |
52 |
|
|
AVFloatDSPContext *fdsp; |
53 |
|
|
|
54 |
|
|
DECLARE_ALIGNED(32, float, samples)[2][ATRAC3P_FRAME_SAMPLES]; ///< quantized MDCT spectrum |
55 |
|
|
DECLARE_ALIGNED(32, float, mdct_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the IMDCT |
56 |
|
|
DECLARE_ALIGNED(32, float, time_buf)[2][ATRAC3P_FRAME_SAMPLES]; ///< output of the gain compensation |
57 |
|
|
DECLARE_ALIGNED(32, float, outp_buf)[2][ATRAC3P_FRAME_SAMPLES]; |
58 |
|
|
|
59 |
|
|
AtracGCContext gainc_ctx; ///< gain compensation context |
60 |
|
|
FFTContext mdct_ctx; |
61 |
|
|
FFTContext ipqf_dct_ctx; ///< IDCT context used by IPQF |
62 |
|
|
|
63 |
|
|
Atrac3pChanUnitCtx *ch_units; ///< global channel units |
64 |
|
|
|
65 |
|
|
int num_channel_blocks; ///< number of channel blocks |
66 |
|
|
uint8_t channel_blocks[5]; ///< channel configuration descriptor |
67 |
|
|
uint64_t my_channel_layout; ///< current channel layout |
68 |
|
|
} ATRAC3PContext; |
69 |
|
|
|
70 |
|
4 |
static av_cold int atrac3p_decode_close(AVCodecContext *avctx) |
71 |
|
|
{ |
72 |
|
4 |
ATRAC3PContext *ctx = avctx->priv_data; |
73 |
|
|
|
74 |
|
4 |
av_freep(&ctx->ch_units); |
75 |
|
4 |
av_freep(&ctx->fdsp); |
76 |
|
|
|
77 |
|
4 |
ff_mdct_end(&ctx->mdct_ctx); |
78 |
|
4 |
ff_mdct_end(&ctx->ipqf_dct_ctx); |
79 |
|
|
|
80 |
|
4 |
return 0; |
81 |
|
|
} |
82 |
|
|
|
83 |
|
4 |
static av_cold int set_channel_params(ATRAC3PContext *ctx, |
84 |
|
|
AVCodecContext *avctx) |
85 |
|
|
{ |
86 |
|
4 |
memset(ctx->channel_blocks, 0, sizeof(ctx->channel_blocks)); |
87 |
|
|
|
88 |
✗✓✗✗ ✗✗✗✗
|
4 |
switch (avctx->channels) { |
89 |
|
|
case 1: |
90 |
|
|
if (avctx->channel_layout != AV_CH_FRONT_LEFT) |
91 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_MONO; |
92 |
|
|
|
93 |
|
|
ctx->num_channel_blocks = 1; |
94 |
|
|
ctx->channel_blocks[0] = CH_UNIT_MONO; |
95 |
|
|
break; |
96 |
|
4 |
case 2: |
97 |
|
4 |
avctx->channel_layout = AV_CH_LAYOUT_STEREO; |
98 |
|
4 |
ctx->num_channel_blocks = 1; |
99 |
|
4 |
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
100 |
|
4 |
break; |
101 |
|
|
case 3: |
102 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_SURROUND; |
103 |
|
|
ctx->num_channel_blocks = 2; |
104 |
|
|
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
105 |
|
|
ctx->channel_blocks[1] = CH_UNIT_MONO; |
106 |
|
|
break; |
107 |
|
|
case 4: |
108 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_4POINT0; |
109 |
|
|
ctx->num_channel_blocks = 3; |
110 |
|
|
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
111 |
|
|
ctx->channel_blocks[1] = CH_UNIT_MONO; |
112 |
|
|
ctx->channel_blocks[2] = CH_UNIT_MONO; |
113 |
|
|
break; |
114 |
|
|
case 6: |
115 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; |
116 |
|
|
ctx->num_channel_blocks = 4; |
117 |
|
|
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
118 |
|
|
ctx->channel_blocks[1] = CH_UNIT_MONO; |
119 |
|
|
ctx->channel_blocks[2] = CH_UNIT_STEREO; |
120 |
|
|
ctx->channel_blocks[3] = CH_UNIT_MONO; |
121 |
|
|
break; |
122 |
|
|
case 7: |
123 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_6POINT1_BACK; |
124 |
|
|
ctx->num_channel_blocks = 5; |
125 |
|
|
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
126 |
|
|
ctx->channel_blocks[1] = CH_UNIT_MONO; |
127 |
|
|
ctx->channel_blocks[2] = CH_UNIT_STEREO; |
128 |
|
|
ctx->channel_blocks[3] = CH_UNIT_MONO; |
129 |
|
|
ctx->channel_blocks[4] = CH_UNIT_MONO; |
130 |
|
|
break; |
131 |
|
|
case 8: |
132 |
|
|
avctx->channel_layout = AV_CH_LAYOUT_7POINT1; |
133 |
|
|
ctx->num_channel_blocks = 5; |
134 |
|
|
ctx->channel_blocks[0] = CH_UNIT_STEREO; |
135 |
|
|
ctx->channel_blocks[1] = CH_UNIT_MONO; |
136 |
|
|
ctx->channel_blocks[2] = CH_UNIT_STEREO; |
137 |
|
|
ctx->channel_blocks[3] = CH_UNIT_STEREO; |
138 |
|
|
ctx->channel_blocks[4] = CH_UNIT_MONO; |
139 |
|
|
break; |
140 |
|
|
default: |
141 |
|
|
av_log(avctx, AV_LOG_ERROR, |
142 |
|
|
"Unsupported channel count: %d!\n", avctx->channels); |
143 |
|
|
return AVERROR_INVALIDDATA; |
144 |
|
|
} |
145 |
|
|
|
146 |
|
4 |
return 0; |
147 |
|
|
} |
148 |
|
|
|
149 |
|
2 |
static av_cold void atrac3p_init_static(void) |
150 |
|
|
{ |
151 |
|
2 |
ff_atrac3p_init_vlcs(); |
152 |
|
2 |
ff_atrac3p_init_dsp_static(); |
153 |
|
2 |
} |
154 |
|
|
|
155 |
|
4 |
static av_cold int atrac3p_decode_init(AVCodecContext *avctx) |
156 |
|
|
{ |
157 |
|
|
static AVOnce init_static_once = AV_ONCE_INIT; |
158 |
|
4 |
ATRAC3PContext *ctx = avctx->priv_data; |
159 |
|
|
int i, ch, ret; |
160 |
|
|
|
161 |
✗✓ |
4 |
if (!avctx->block_align) { |
162 |
|
|
av_log(avctx, AV_LOG_ERROR, "block_align is not set\n"); |
163 |
|
|
return AVERROR(EINVAL); |
164 |
|
|
} |
165 |
|
|
|
166 |
|
|
/* initialize IPQF */ |
167 |
|
4 |
ff_mdct_init(&ctx->ipqf_dct_ctx, 5, 1, 32.0 / 32768.0); |
168 |
|
|
|
169 |
|
4 |
ff_atrac3p_init_imdct(avctx, &ctx->mdct_ctx); |
170 |
|
|
|
171 |
|
4 |
ff_atrac_init_gain_compensation(&ctx->gainc_ctx, 6, 2); |
172 |
|
|
|
173 |
✗✓ |
4 |
if ((ret = set_channel_params(ctx, avctx)) < 0) |
174 |
|
|
return ret; |
175 |
|
|
|
176 |
|
4 |
ctx->my_channel_layout = avctx->channel_layout; |
177 |
|
|
|
178 |
|
4 |
ctx->ch_units = av_mallocz_array(ctx->num_channel_blocks, sizeof(*ctx->ch_units)); |
179 |
|
4 |
ctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); |
180 |
|
|
|
181 |
✓✗✗✓
|
4 |
if (!ctx->ch_units || !ctx->fdsp) { |
182 |
|
|
return AVERROR(ENOMEM); |
183 |
|
|
} |
184 |
|
|
|
185 |
✓✓ |
8 |
for (i = 0; i < ctx->num_channel_blocks; i++) { |
186 |
✓✓ |
12 |
for (ch = 0; ch < 2; ch++) { |
187 |
|
8 |
ctx->ch_units[i].channels[ch].ch_num = ch; |
188 |
|
8 |
ctx->ch_units[i].channels[ch].wnd_shape = &ctx->ch_units[i].channels[ch].wnd_shape_hist[0][0]; |
189 |
|
8 |
ctx->ch_units[i].channels[ch].wnd_shape_prev = &ctx->ch_units[i].channels[ch].wnd_shape_hist[1][0]; |
190 |
|
8 |
ctx->ch_units[i].channels[ch].gain_data = &ctx->ch_units[i].channels[ch].gain_data_hist[0][0]; |
191 |
|
8 |
ctx->ch_units[i].channels[ch].gain_data_prev = &ctx->ch_units[i].channels[ch].gain_data_hist[1][0]; |
192 |
|
8 |
ctx->ch_units[i].channels[ch].tones_info = &ctx->ch_units[i].channels[ch].tones_info_hist[0][0]; |
193 |
|
8 |
ctx->ch_units[i].channels[ch].tones_info_prev = &ctx->ch_units[i].channels[ch].tones_info_hist[1][0]; |
194 |
|
|
} |
195 |
|
|
|
196 |
|
4 |
ctx->ch_units[i].waves_info = &ctx->ch_units[i].wave_synth_hist[0]; |
197 |
|
4 |
ctx->ch_units[i].waves_info_prev = &ctx->ch_units[i].wave_synth_hist[1]; |
198 |
|
|
} |
199 |
|
|
|
200 |
|
4 |
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; |
201 |
|
|
|
202 |
|
4 |
ff_thread_once(&init_static_once, atrac3p_init_static); |
203 |
|
|
|
204 |
|
4 |
return 0; |
205 |
|
|
} |
206 |
|
|
|
207 |
|
813 |
static void decode_residual_spectrum(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit, |
208 |
|
|
float out[2][ATRAC3P_FRAME_SAMPLES], |
209 |
|
|
int num_channels, |
210 |
|
|
AVCodecContext *avctx) |
211 |
|
|
{ |
212 |
|
|
int i, sb, ch, qu, nspeclines, RNG_index; |
213 |
|
|
float *dst, q; |
214 |
|
|
int16_t *src; |
215 |
|
|
/* calculate RNG table index for each subband */ |
216 |
|
813 |
int sb_RNG_index[ATRAC3P_SUBBANDS] = { 0 }; |
217 |
|
|
|
218 |
✗✓ |
813 |
if (ch_unit->mute_flag) { |
219 |
|
|
for (ch = 0; ch < num_channels; ch++) |
220 |
|
|
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch])); |
221 |
|
|
return; |
222 |
|
|
} |
223 |
|
|
|
224 |
✓✓ |
22793 |
for (qu = 0, RNG_index = 0; qu < ch_unit->used_quant_units; qu++) |
225 |
|
21980 |
RNG_index += ch_unit->channels[0].qu_sf_idx[qu] + |
226 |
|
21980 |
ch_unit->channels[1].qu_sf_idx[qu]; |
227 |
|
|
|
228 |
✓✓ |
10377 |
for (sb = 0; sb < ch_unit->num_coded_subbands; sb++, RNG_index += 128) |
229 |
|
9564 |
sb_RNG_index[sb] = RNG_index & 0x3FC; |
230 |
|
|
|
231 |
|
|
/* inverse quant and power compensation */ |
232 |
✓✓ |
2439 |
for (ch = 0; ch < num_channels; ch++) { |
233 |
|
|
/* clear channel's residual spectrum */ |
234 |
|
1626 |
memset(out[ch], 0, ATRAC3P_FRAME_SAMPLES * sizeof(*out[ch])); |
235 |
|
|
|
236 |
✓✓ |
45586 |
for (qu = 0; qu < ch_unit->used_quant_units; qu++) { |
237 |
|
43960 |
src = &ch_unit->channels[ch].spectrum[ff_atrac3p_qu_to_spec_pos[qu]]; |
238 |
|
43960 |
dst = &out[ch][ff_atrac3p_qu_to_spec_pos[qu]]; |
239 |
|
43960 |
nspeclines = ff_atrac3p_qu_to_spec_pos[qu + 1] - |
240 |
|
43960 |
ff_atrac3p_qu_to_spec_pos[qu]; |
241 |
|
|
|
242 |
✓✗ |
43960 |
if (ch_unit->channels[ch].qu_wordlen[qu] > 0) { |
243 |
|
43960 |
q = ff_atrac3p_sf_tab[ch_unit->channels[ch].qu_sf_idx[qu]] * |
244 |
|
43960 |
ff_atrac3p_mant_tab[ch_unit->channels[ch].qu_wordlen[qu]]; |
245 |
✓✓ |
2492344 |
for (i = 0; i < nspeclines; i++) |
246 |
|
2448384 |
dst[i] = src[i] * q; |
247 |
|
|
} |
248 |
|
|
} |
249 |
|
|
|
250 |
✓✓ |
20754 |
for (sb = 0; sb < ch_unit->num_coded_subbands; sb++) |
251 |
|
19128 |
ff_atrac3p_power_compensation(ch_unit, ctx->fdsp, ch, &out[ch][0], |
252 |
|
|
sb_RNG_index[sb], sb); |
253 |
|
|
} |
254 |
|
|
|
255 |
✓✗ |
813 |
if (ch_unit->unit_type == CH_UNIT_STEREO) { |
256 |
✓✓ |
10377 |
for (sb = 0; sb < ch_unit->num_coded_subbands; sb++) { |
257 |
✗✓ |
9564 |
if (ch_unit->swap_channels[sb]) { |
258 |
|
|
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++) |
259 |
|
|
FFSWAP(float, out[0][sb * ATRAC3P_SUBBAND_SAMPLES + i], |
260 |
|
|
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]); |
261 |
|
|
} |
262 |
|
|
|
263 |
|
|
/* flip coefficients' sign if requested */ |
264 |
✗✓ |
9564 |
if (ch_unit->negate_coeffs[sb]) |
265 |
|
|
for (i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++) |
266 |
|
|
out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i] = -(out[1][sb * ATRAC3P_SUBBAND_SAMPLES + i]); |
267 |
|
|
} |
268 |
|
|
} |
269 |
|
|
} |
270 |
|
|
|
271 |
|
813 |
static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit, |
272 |
|
|
int num_channels, AVCodecContext *avctx) |
273 |
|
|
{ |
274 |
|
|
int ch, sb; |
275 |
|
|
|
276 |
✓✓ |
2439 |
for (ch = 0; ch < num_channels; ch++) { |
277 |
✓✓ |
23298 |
for (sb = 0; sb < ch_unit->num_subbands; sb++) { |
278 |
|
|
/* inverse transform and windowing */ |
279 |
|
21672 |
ff_atrac3p_imdct(ctx->fdsp, &ctx->mdct_ctx, |
280 |
|
21672 |
&ctx->samples[ch][sb * ATRAC3P_SUBBAND_SAMPLES], |
281 |
|
21672 |
&ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES], |
282 |
|
21672 |
(ch_unit->channels[ch].wnd_shape_prev[sb] << 1) + |
283 |
|
21672 |
ch_unit->channels[ch].wnd_shape[sb], sb); |
284 |
|
|
|
285 |
|
|
/* gain compensation and overlapping */ |
286 |
|
21672 |
ff_atrac_gain_compensation(&ctx->gainc_ctx, |
287 |
|
21672 |
&ctx->mdct_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES], |
288 |
|
21672 |
&ch_unit->prev_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES], |
289 |
|
21672 |
&ch_unit->channels[ch].gain_data_prev[sb], |
290 |
|
21672 |
&ch_unit->channels[ch].gain_data[sb], |
291 |
|
|
ATRAC3P_SUBBAND_SAMPLES, |
292 |
|
21672 |
&ctx->time_buf[ch][sb * ATRAC3P_SUBBAND_SAMPLES]); |
293 |
|
|
} |
294 |
|
|
|
295 |
|
|
/* zero unused subbands in both output and overlapping buffers */ |
296 |
|
1626 |
memset(&ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES], |
297 |
|
|
0, |
298 |
|
1626 |
(ATRAC3P_SUBBANDS - ch_unit->num_subbands) * |
299 |
|
|
ATRAC3P_SUBBAND_SAMPLES * |
300 |
|
|
sizeof(ch_unit->prev_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES])); |
301 |
|
1626 |
memset(&ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES], |
302 |
|
|
0, |
303 |
|
1626 |
(ATRAC3P_SUBBANDS - ch_unit->num_subbands) * |
304 |
|
|
ATRAC3P_SUBBAND_SAMPLES * |
305 |
|
|
sizeof(ctx->time_buf[ch][ch_unit->num_subbands * ATRAC3P_SUBBAND_SAMPLES])); |
306 |
|
|
|
307 |
|
|
/* resynthesize and add tonal signal */ |
308 |
✓✗ |
1626 |
if (ch_unit->waves_info->tones_present || |
309 |
✗✓ |
1626 |
ch_unit->waves_info_prev->tones_present) { |
310 |
|
|
for (sb = 0; sb < ch_unit->num_subbands; sb++) |
311 |
|
|
if (ch_unit->channels[ch].tones_info[sb].num_wavs || |
312 |
|
|
ch_unit->channels[ch].tones_info_prev[sb].num_wavs) { |
313 |
|
|
ff_atrac3p_generate_tones(ch_unit, ctx->fdsp, ch, sb, |
314 |
|
|
&ctx->time_buf[ch][sb * 128]); |
315 |
|
|
} |
316 |
|
|
} |
317 |
|
|
|
318 |
|
|
/* subband synthesis and acoustic signal output */ |
319 |
|
1626 |
ff_atrac3p_ipqf(&ctx->ipqf_dct_ctx, &ch_unit->ipqf_ctx[ch], |
320 |
|
1626 |
&ctx->time_buf[ch][0], &ctx->outp_buf[ch][0]); |
321 |
|
|
} |
322 |
|
|
|
323 |
|
|
/* swap window shape and gain control buffers. */ |
324 |
✓✓ |
2439 |
for (ch = 0; ch < num_channels; ch++) { |
325 |
|
1626 |
FFSWAP(uint8_t *, ch_unit->channels[ch].wnd_shape, |
326 |
|
|
ch_unit->channels[ch].wnd_shape_prev); |
327 |
|
1626 |
FFSWAP(AtracGainInfo *, ch_unit->channels[ch].gain_data, |
328 |
|
|
ch_unit->channels[ch].gain_data_prev); |
329 |
|
1626 |
FFSWAP(Atrac3pWavesData *, ch_unit->channels[ch].tones_info, |
330 |
|
|
ch_unit->channels[ch].tones_info_prev); |
331 |
|
|
} |
332 |
|
|
|
333 |
|
813 |
FFSWAP(Atrac3pWaveSynthParams *, ch_unit->waves_info, ch_unit->waves_info_prev); |
334 |
|
813 |
} |
335 |
|
|
|
336 |
|
813 |
static int atrac3p_decode_frame(AVCodecContext *avctx, void *data, |
337 |
|
|
int *got_frame_ptr, AVPacket *avpkt) |
338 |
|
|
{ |
339 |
|
813 |
ATRAC3PContext *ctx = avctx->priv_data; |
340 |
|
813 |
AVFrame *frame = data; |
341 |
|
813 |
int i, ret, ch_unit_id, ch_block = 0, out_ch_index = 0, channels_to_process; |
342 |
|
813 |
float **samples_p = (float **)frame->extended_data; |
343 |
|
|
|
344 |
|
813 |
frame->nb_samples = ATRAC3P_FRAME_SAMPLES; |
345 |
✗✓ |
813 |
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
346 |
|
|
return ret; |
347 |
|
|
|
348 |
✗✓ |
813 |
if ((ret = init_get_bits8(&ctx->gb, avpkt->data, avpkt->size)) < 0) |
349 |
|
|
return ret; |
350 |
|
|
|
351 |
✗✓ |
813 |
if (get_bits1(&ctx->gb)) { |
352 |
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid start bit!\n"); |
353 |
|
|
return AVERROR_INVALIDDATA; |
354 |
|
|
} |
355 |
|
|
|
356 |
✓✓ |
1626 |
while (get_bits_left(&ctx->gb) >= 2 && |
357 |
✓✓ |
1625 |
(ch_unit_id = get_bits(&ctx->gb, 2)) != CH_UNIT_TERMINATOR) { |
358 |
✗✓ |
813 |
if (ch_unit_id == CH_UNIT_EXTENSION) { |
359 |
|
|
avpriv_report_missing_feature(avctx, "Channel unit extension"); |
360 |
|
|
return AVERROR_PATCHWELCOME; |
361 |
|
|
} |
362 |
✓✗ |
813 |
if (ch_block >= ctx->num_channel_blocks || |
363 |
✗✓ |
813 |
ctx->channel_blocks[ch_block] != ch_unit_id) { |
364 |
|
|
av_log(avctx, AV_LOG_ERROR, |
365 |
|
|
"Frame data doesn't match channel configuration!\n"); |
366 |
|
|
return AVERROR_INVALIDDATA; |
367 |
|
|
} |
368 |
|
|
|
369 |
|
813 |
ctx->ch_units[ch_block].unit_type = ch_unit_id; |
370 |
|
813 |
channels_to_process = ch_unit_id + 1; |
371 |
|
|
|
372 |
✗✓ |
813 |
if ((ret = ff_atrac3p_decode_channel_unit(&ctx->gb, |
373 |
|
813 |
&ctx->ch_units[ch_block], |
374 |
|
|
channels_to_process, |
375 |
|
|
avctx)) < 0) |
376 |
|
|
return ret; |
377 |
|
|
|
378 |
|
813 |
decode_residual_spectrum(ctx, &ctx->ch_units[ch_block], ctx->samples, |
379 |
|
|
channels_to_process, avctx); |
380 |
|
813 |
reconstruct_frame(ctx, &ctx->ch_units[ch_block], |
381 |
|
|
channels_to_process, avctx); |
382 |
|
|
|
383 |
✓✓ |
2439 |
for (i = 0; i < channels_to_process; i++) |
384 |
|
1626 |
memcpy(samples_p[out_ch_index + i], ctx->outp_buf[i], |
385 |
|
|
ATRAC3P_FRAME_SAMPLES * sizeof(**samples_p)); |
386 |
|
|
|
387 |
|
813 |
ch_block++; |
388 |
|
813 |
out_ch_index += channels_to_process; |
389 |
|
|
} |
390 |
|
|
|
391 |
|
813 |
*got_frame_ptr = 1; |
392 |
|
|
|
393 |
✓✗ |
813 |
return avctx->codec_id == AV_CODEC_ID_ATRAC3P ? FFMIN(avctx->block_align, avpkt->size) : avpkt->size; |
394 |
|
|
} |
395 |
|
|
|
396 |
|
|
AVCodec ff_atrac3p_decoder = { |
397 |
|
|
.name = "atrac3plus", |
398 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), |
399 |
|
|
.type = AVMEDIA_TYPE_AUDIO, |
400 |
|
|
.id = AV_CODEC_ID_ATRAC3P, |
401 |
|
|
.capabilities = AV_CODEC_CAP_DR1, |
402 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, |
403 |
|
|
.priv_data_size = sizeof(ATRAC3PContext), |
404 |
|
|
.init = atrac3p_decode_init, |
405 |
|
|
.close = atrac3p_decode_close, |
406 |
|
|
.decode = atrac3p_decode_frame, |
407 |
|
|
}; |
408 |
|
|
|
409 |
|
|
AVCodec ff_atrac3pal_decoder = { |
410 |
|
|
.name = "atrac3plusal", |
411 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), |
412 |
|
|
.type = AVMEDIA_TYPE_AUDIO, |
413 |
|
|
.id = AV_CODEC_ID_ATRAC3PAL, |
414 |
|
|
.capabilities = AV_CODEC_CAP_DR1, |
415 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, |
416 |
|
|
.priv_data_size = sizeof(ATRAC3PContext), |
417 |
|
|
.init = atrac3p_decode_init, |
418 |
|
|
.close = atrac3p_decode_close, |
419 |
|
|
.decode = atrac3p_decode_frame, |
420 |
|
|
}; |