/src/ffmpeg/libavcodec/apac.c
Line | Count | Source |
1 | | /* |
2 | | * APAC audio decoder |
3 | | * |
4 | | * This file is part of FFmpeg. |
5 | | * |
6 | | * FFmpeg is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * FFmpeg is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with FFmpeg; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #include "libavutil/audio_fifo.h" |
22 | | #include "libavutil/mem.h" |
23 | | #include "avcodec.h" |
24 | | #include "codec_internal.h" |
25 | | #include "decode.h" |
26 | | #include "get_bits.h" |
27 | | |
28 | | typedef struct ChContext { |
29 | | int have_code; |
30 | | int last_sample; |
31 | | int last_delta; |
32 | | int bit_length; |
33 | | int block_length; |
34 | | uint8_t block[32 * 2]; |
35 | | AVAudioFifo *samples; |
36 | | } ChContext; |
37 | | |
38 | | typedef struct APACContext { |
39 | | GetBitContext gb; |
40 | | int skip; |
41 | | |
42 | | int cur_ch; |
43 | | ChContext ch[2]; |
44 | | |
45 | | uint8_t *bitstream; |
46 | | int64_t max_framesize; |
47 | | int bitstream_size; |
48 | | int bitstream_index; |
49 | | } APACContext; |
50 | | |
51 | | static av_cold int apac_close(AVCodecContext *avctx) |
52 | 903 | { |
53 | 903 | APACContext *s = avctx->priv_data; |
54 | | |
55 | 903 | av_freep(&s->bitstream); |
56 | 903 | s->bitstream_size = 0; |
57 | | |
58 | 2.70k | for (int ch = 0; ch < 2; ch++) { |
59 | 1.80k | ChContext *c = &s->ch[ch]; |
60 | | |
61 | 1.80k | av_audio_fifo_free(c->samples); |
62 | 1.80k | } |
63 | | |
64 | 903 | return 0; |
65 | 903 | } |
66 | | |
67 | | static av_cold int apac_init(AVCodecContext *avctx) |
68 | 903 | { |
69 | 903 | APACContext *s = avctx->priv_data; |
70 | | |
71 | 903 | if (avctx->bits_per_coded_sample > 8) |
72 | 614 | avctx->sample_fmt = AV_SAMPLE_FMT_S16P; |
73 | 289 | else |
74 | 289 | avctx->sample_fmt = AV_SAMPLE_FMT_U8P; |
75 | | |
76 | 903 | if (avctx->ch_layout.nb_channels < 1 || |
77 | 903 | avctx->ch_layout.nb_channels > 2 || |
78 | 838 | avctx->bits_per_coded_sample < 8 || |
79 | 801 | avctx->bits_per_coded_sample > 16 |
80 | 903 | ) |
81 | 132 | return AVERROR_INVALIDDATA; |
82 | | |
83 | 1.86k | for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { |
84 | 1.09k | ChContext *c = &s->ch[ch]; |
85 | | |
86 | 1.09k | c->bit_length = avctx->bits_per_coded_sample; |
87 | 1.09k | c->block_length = 8; |
88 | 1.09k | c->have_code = 0; |
89 | 1.09k | c->samples = av_audio_fifo_alloc(avctx->sample_fmt, 1, 1024); |
90 | 1.09k | if (!c->samples) |
91 | 0 | return AVERROR(ENOMEM); |
92 | 1.09k | } |
93 | | |
94 | 771 | s->max_framesize = 1024; |
95 | 771 | s->bitstream = av_realloc_f(s->bitstream, s->max_framesize + AV_INPUT_BUFFER_PADDING_SIZE, sizeof(*s->bitstream)); |
96 | 771 | if (!s->bitstream) |
97 | 0 | return AVERROR(ENOMEM); |
98 | | |
99 | 771 | return 0; |
100 | 771 | } |
101 | | |
102 | | static int get_code(ChContext *c, GetBitContext *gb) |
103 | 107M | { |
104 | 107M | if (get_bits1(gb)) { |
105 | 676k | int code = get_bits(gb, 2); |
106 | | |
107 | 676k | switch (code) { |
108 | 201k | case 0: |
109 | 201k | c->bit_length--; |
110 | 201k | break; |
111 | 191k | case 1: |
112 | 191k | c->bit_length++; |
113 | 191k | break; |
114 | 215k | case 2: |
115 | 215k | c->bit_length = get_bits(gb, 5); |
116 | 215k | break; |
117 | 68.6k | case 3: |
118 | 68.6k | c->block_length = get_bits(gb, 4); |
119 | 68.6k | return 1; |
120 | 676k | } |
121 | 676k | } |
122 | | |
123 | 107M | return 0; |
124 | 107M | } |
125 | | |
126 | | static int apac_decode(AVCodecContext *avctx, AVFrame *frame, |
127 | | int *got_frame_ptr, AVPacket *pkt) |
128 | 345k | { |
129 | 345k | APACContext *s = avctx->priv_data; |
130 | 345k | GetBitContext *gb = &s->gb; |
131 | 345k | int ret, n, buf_size, input_buf_size; |
132 | 345k | uint8_t *buf; |
133 | 345k | int nb_samples; |
134 | | |
135 | 345k | if (!pkt->size && s->bitstream_size <= 0) { |
136 | 290 | *got_frame_ptr = 0; |
137 | 290 | return 0; |
138 | 290 | } |
139 | | |
140 | 345k | buf_size = pkt->size; |
141 | 345k | input_buf_size = buf_size; |
142 | | |
143 | 345k | if (s->bitstream_index > 0 && s->bitstream_size > 0) { |
144 | 47.5k | memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size); |
145 | 47.5k | s->bitstream_index = 0; |
146 | 47.5k | } |
147 | | |
148 | 345k | if (s->bitstream_index + s->bitstream_size + buf_size > s->max_framesize) { |
149 | 11.3k | s->bitstream = av_realloc_f(s->bitstream, s->bitstream_index + |
150 | 11.3k | s->bitstream_size + |
151 | 11.3k | buf_size + AV_INPUT_BUFFER_PADDING_SIZE, |
152 | 11.3k | sizeof(*s->bitstream)); |
153 | 11.3k | if (!s->bitstream) |
154 | 0 | return AVERROR(ENOMEM); |
155 | 11.3k | s->max_framesize = s->bitstream_index + s->bitstream_size + buf_size; |
156 | 11.3k | } |
157 | 345k | if (pkt->data) |
158 | 344k | memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], pkt->data, buf_size); |
159 | 345k | buf = &s->bitstream[s->bitstream_index]; |
160 | 345k | buf_size += s->bitstream_size; |
161 | 345k | s->bitstream_size = buf_size; |
162 | 345k | memset(buf + buf_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
163 | | |
164 | 345k | frame->nb_samples = s->bitstream_size * 16 * 8; |
165 | 345k | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) |
166 | 10.7k | return ret; |
167 | | |
168 | 334k | if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) |
169 | 0 | return ret; |
170 | | |
171 | 334k | skip_bits(gb, s->skip); |
172 | 334k | s->skip = 0; |
173 | | |
174 | 104M | while (get_bits_left(gb) > 0) { |
175 | 211M | for (int ch = s->cur_ch; ch < avctx->ch_layout.nb_channels; ch++) { |
176 | 108M | ChContext *c = &s->ch[ch]; |
177 | 108M | int16_t *dst16 = (int16_t *)c->block; |
178 | 108M | uint8_t *dst8 = (uint8_t *)c->block; |
179 | 108M | void *samples[4]; |
180 | | |
181 | 108M | samples[0] = &c->block[0]; |
182 | 108M | if (get_bits_left(gb) < 16 && pkt->size) { |
183 | 56.8k | s->cur_ch = ch; |
184 | 56.8k | goto end; |
185 | 56.8k | } |
186 | | |
187 | 108M | if (!c->have_code && get_code(c, gb)) |
188 | 59.1k | get_code(c, gb); |
189 | 108M | c->have_code = 0; |
190 | | |
191 | 108M | if (c->block_length <= 0) |
192 | 1.85M | continue; |
193 | | |
194 | 106M | if (c->bit_length < 0 || |
195 | 106M | c->bit_length > 17) { |
196 | 8.09k | c->bit_length = avctx->bits_per_coded_sample; |
197 | 8.09k | s->bitstream_index = 0; |
198 | 8.09k | s->bitstream_size = 0; |
199 | 8.09k | return AVERROR_INVALIDDATA; |
200 | 8.09k | } |
201 | | |
202 | 106M | if (get_bits_left(gb) < c->block_length * c->bit_length) { |
203 | 278k | if (pkt->size) { |
204 | 265k | c->have_code = 1; |
205 | 265k | s->cur_ch = ch; |
206 | 265k | goto end; |
207 | 265k | } else { |
208 | 12.7k | break; |
209 | 12.7k | } |
210 | 278k | } |
211 | | |
212 | 1.67G | for (int i = 0; i < c->block_length; i++) { |
213 | 1.56G | int val = get_bits_long(gb, c->bit_length); |
214 | 1.56G | unsigned delta = (val & 1) ? ~(val >> 1) : (val >> 1); |
215 | 1.56G | int sample; |
216 | | |
217 | 1.56G | delta += c->last_delta; |
218 | 1.56G | sample = c->last_sample + delta; |
219 | 1.56G | c->last_delta = delta; |
220 | 1.56G | c->last_sample = sample; |
221 | | |
222 | 1.56G | switch (avctx->sample_fmt) { |
223 | 1.56G | case AV_SAMPLE_FMT_S16P: |
224 | 1.56G | dst16[i] = sample; |
225 | 1.56G | break; |
226 | 4.29M | case AV_SAMPLE_FMT_U8P: |
227 | 4.29M | dst8[i] = sample; |
228 | 4.29M | break; |
229 | 1.56G | } |
230 | 1.56G | } |
231 | | |
232 | 105M | av_audio_fifo_write(c->samples, samples, c->block_length); |
233 | 105M | } |
234 | | |
235 | 103M | s->cur_ch = 0; |
236 | 103M | } |
237 | 326k | end: |
238 | 326k | nb_samples = frame->nb_samples; |
239 | 676k | for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) |
240 | 350k | nb_samples = FFMIN(av_audio_fifo_size(s->ch[ch].samples), nb_samples); |
241 | | |
242 | 326k | frame->nb_samples = nb_samples; |
243 | 676k | for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { |
244 | 350k | void *samples[1] = { frame->extended_data[ch] }; |
245 | 350k | av_audio_fifo_read(s->ch[ch].samples, samples, nb_samples); |
246 | 350k | } |
247 | | |
248 | 326k | s->skip = get_bits_count(gb) - 8 * (get_bits_count(gb) / 8); |
249 | 326k | n = get_bits_count(gb) / 8; |
250 | | |
251 | 326k | if (nb_samples > 0 || pkt->size) |
252 | 326k | *got_frame_ptr = 1; |
253 | | |
254 | 326k | if (s->bitstream_size > 0) { |
255 | 326k | s->bitstream_index += n; |
256 | 326k | s->bitstream_size -= n; |
257 | 326k | return input_buf_size; |
258 | 326k | } |
259 | 0 | return n; |
260 | 326k | } |
261 | | |
262 | | const FFCodec ff_apac_decoder = { |
263 | | .p.name = "apac", |
264 | | CODEC_LONG_NAME("Marian's A-pac audio"), |
265 | | .p.type = AVMEDIA_TYPE_AUDIO, |
266 | | .p.id = AV_CODEC_ID_APAC, |
267 | | .priv_data_size = sizeof(APACContext), |
268 | | .init = apac_init, |
269 | | FF_CODEC_DECODE_CB(apac_decode), |
270 | | .close = apac_close, |
271 | | .p.capabilities = AV_CODEC_CAP_DELAY | |
272 | | AV_CODEC_CAP_DR1, |
273 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
274 | | CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P), |
275 | | }; |