Commit | Line | Data |
---|---|---|
a24c4a2a AB |
1 | /* |
2 | * TTA (The Lossless True Audio) decoder | |
3 | * Copyright (c) 2006 Alex Beregszaszi | |
4 | * | |
2912e87a | 5 | * This file is part of Libav. |
b78e7197 | 6 | * |
2912e87a | 7 | * Libav is free software; you can redistribute it and/or |
a24c4a2a AB |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
a24c4a2a | 11 | * |
2912e87a | 12 | * Libav is distributed in the hope that it will be useful, |
a24c4a2a AB |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
2912e87a | 18 | * License along with Libav; if not, write to the Free Software |
e5a389a1 | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
a24c4a2a AB |
20 | */ |
21 | ||
22 | /** | |
ba87f080 | 23 | * @file |
a24c4a2a | 24 | * TTA (The Lossless True Audio) decoder |
ad4cd0c2 DB |
25 | * @see http://www.true-audio.com/ |
26 | * @see http://tta.corecodec.org/ | |
a24c4a2a | 27 | * @author Alex Beregszaszi |
a24c4a2a AB |
28 | */ |
29 | ||
aaf47bcd | 30 | #define BITSTREAM_READER_LE |
a24c4a2a AB |
31 | //#define DEBUG |
32 | #include <limits.h> | |
33 | #include "avcodec.h" | |
9106a698 | 34 | #include "get_bits.h" |
594d4d5d | 35 | #include "internal.h" |
2af3dc86 | 36 | #include "libavutil/crc.h" |
a24c4a2a | 37 | |
b16960a8 JR |
38 | #define FORMAT_SIMPLE 1 |
39 | #define FORMAT_ENCRYPTED 2 | |
a24c4a2a | 40 | |
5113b3bd MR |
41 | #define MAX_ORDER 16 |
42 | typedef struct TTAFilter { | |
323b9da9 | 43 | int32_t shift, round, error; |
5113b3bd MR |
44 | int32_t qm[MAX_ORDER]; |
45 | int32_t dx[MAX_ORDER]; | |
46 | int32_t dl[MAX_ORDER]; | |
47 | } TTAFilter; | |
48 | ||
49 | typedef struct TTARice { | |
50 | uint32_t k0, k1, sum0, sum1; | |
51 | } TTARice; | |
52 | ||
53 | typedef struct TTAChannel { | |
54 | int32_t predictor; | |
55 | TTAFilter filter; | |
56 | TTARice rice; | |
57 | } TTAChannel; | |
58 | ||
a24c4a2a AB |
59 | typedef struct TTAContext { |
60 | AVCodecContext *avctx; | |
61 | GetBitContext gb; | |
2af3dc86 | 62 | const AVCRC *crc_table; |
a24c4a2a | 63 | |
ac80b812 RB |
64 | int format, channels, bps; |
65 | unsigned data_length; | |
5778299c | 66 | int frame_length, last_frame_length; |
a24c4a2a | 67 | |
79a32e3b | 68 | int32_t *decode_buffer; |
5113b3bd | 69 | |
c058dc22 | 70 | TTAChannel *ch_ctx; |
a24c4a2a AB |
71 | } TTAContext; |
72 | ||
79a32e3b | 73 | static const uint32_t shift_1[] = { |
a24c4a2a AB |
74 | 0x00000001, 0x00000002, 0x00000004, 0x00000008, |
75 | 0x00000010, 0x00000020, 0x00000040, 0x00000080, | |
76 | 0x00000100, 0x00000200, 0x00000400, 0x00000800, | |
77 | 0x00001000, 0x00002000, 0x00004000, 0x00008000, | |
78 | 0x00010000, 0x00020000, 0x00040000, 0x00080000, | |
79 | 0x00100000, 0x00200000, 0x00400000, 0x00800000, | |
80 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, | |
81 | 0x10000000, 0x20000000, 0x40000000, 0x80000000, | |
82 | 0x80000000, 0x80000000, 0x80000000, 0x80000000, | |
83 | 0x80000000, 0x80000000, 0x80000000, 0x80000000 | |
84 | }; | |
85 | ||
cf2baeb3 | 86 | static const uint32_t * const shift_16 = shift_1 + 4; |
a24c4a2a | 87 | |
323b9da9 PM |
88 | static const int32_t ttafilter_configs[4] = { |
89 | 10, | |
90 | 9, | |
91 | 10, | |
92 | 12 | |
a24c4a2a AB |
93 | }; |
94 | ||
323b9da9 | 95 | static void ttafilter_init(TTAFilter *c, int32_t shift) { |
a24c4a2a AB |
96 | memset(c, 0, sizeof(TTAFilter)); |
97 | c->shift = shift; | |
98 | c->round = shift_1[shift-1]; | |
99 | // c->round = 1 << (shift - 1); | |
a24c4a2a AB |
100 | } |
101 | ||
102 | // FIXME: copy paste from original | |
79a32e3b | 103 | static inline void memshl(register int32_t *a, register int32_t *b) { |
a24c4a2a AB |
104 | *a++ = *b++; |
105 | *a++ = *b++; | |
106 | *a++ = *b++; | |
107 | *a++ = *b++; | |
108 | *a++ = *b++; | |
109 | *a++ = *b++; | |
110 | *a++ = *b++; | |
111 | *a = *b; | |
112 | } | |
113 | ||
323b9da9 PM |
114 | static inline void ttafilter_process(TTAFilter *c, int32_t *in) |
115 | { | |
79a32e3b | 116 | register int32_t *dl = c->dl, *qm = c->qm, *dx = c->dx, sum = c->round; |
a24c4a2a AB |
117 | |
118 | if (!c->error) { | |
119 | sum += *dl++ * *qm, qm++; | |
120 | sum += *dl++ * *qm, qm++; | |
121 | sum += *dl++ * *qm, qm++; | |
122 | sum += *dl++ * *qm, qm++; | |
123 | sum += *dl++ * *qm, qm++; | |
124 | sum += *dl++ * *qm, qm++; | |
125 | sum += *dl++ * *qm, qm++; | |
126 | sum += *dl++ * *qm, qm++; | |
127 | dx += 8; | |
128 | } else if(c->error < 0) { | |
129 | sum += *dl++ * (*qm -= *dx++), qm++; | |
130 | sum += *dl++ * (*qm -= *dx++), qm++; | |
131 | sum += *dl++ * (*qm -= *dx++), qm++; | |
132 | sum += *dl++ * (*qm -= *dx++), qm++; | |
133 | sum += *dl++ * (*qm -= *dx++), qm++; | |
134 | sum += *dl++ * (*qm -= *dx++), qm++; | |
135 | sum += *dl++ * (*qm -= *dx++), qm++; | |
136 | sum += *dl++ * (*qm -= *dx++), qm++; | |
137 | } else { | |
138 | sum += *dl++ * (*qm += *dx++), qm++; | |
139 | sum += *dl++ * (*qm += *dx++), qm++; | |
140 | sum += *dl++ * (*qm += *dx++), qm++; | |
141 | sum += *dl++ * (*qm += *dx++), qm++; | |
142 | sum += *dl++ * (*qm += *dx++), qm++; | |
143 | sum += *dl++ * (*qm += *dx++), qm++; | |
144 | sum += *dl++ * (*qm += *dx++), qm++; | |
145 | sum += *dl++ * (*qm += *dx++), qm++; | |
146 | } | |
147 | ||
148 | *(dx-0) = ((*(dl-1) >> 30) | 1) << 2; | |
149 | *(dx-1) = ((*(dl-2) >> 30) | 1) << 1; | |
150 | *(dx-2) = ((*(dl-3) >> 30) | 1) << 1; | |
151 | *(dx-3) = ((*(dl-4) >> 30) | 1); | |
152 | ||
323b9da9 PM |
153 | c->error = *in; |
154 | *in += (sum >> c->shift); | |
155 | *dl = *in; | |
a24c4a2a | 156 | |
323b9da9 PM |
157 | *(dl-1) = *dl - *(dl-1); |
158 | *(dl-2) = *(dl-1) - *(dl-2); | |
159 | *(dl-3) = *(dl-2) - *(dl-3); | |
a24c4a2a AB |
160 | |
161 | memshl(c->dl, c->dl + 1); | |
162 | memshl(c->dx, c->dx + 1); | |
163 | } | |
164 | ||
79a32e3b | 165 | static void rice_init(TTARice *c, uint32_t k0, uint32_t k1) |
a24c4a2a AB |
166 | { |
167 | c->k0 = k0; | |
168 | c->k1 = k1; | |
169 | c->sum0 = shift_16[k0]; | |
170 | c->sum1 = shift_16[k1]; | |
171 | } | |
172 | ||
173 | static int tta_get_unary(GetBitContext *gb) | |
174 | { | |
175 | int ret = 0; | |
176 | ||
177 | // count ones | |
35f9d8c2 | 178 | while (get_bits_left(gb) > 0 && get_bits1(gb)) |
a24c4a2a AB |
179 | ret++; |
180 | return ret; | |
181 | } | |
182 | ||
2af3dc86 PM |
183 | static int tta_check_crc(TTAContext *s, const uint8_t *buf, int buf_size) |
184 | { | |
185 | uint32_t crc, CRC; | |
186 | ||
187 | CRC = AV_RL32(buf + buf_size); | |
188 | crc = av_crc(s->crc_table, 0xFFFFFFFFU, buf, buf_size); | |
189 | if (CRC != (crc ^ 0xFFFFFFFFU)) { | |
190 | av_log(s->avctx, AV_LOG_ERROR, "CRC error\n"); | |
191 | return AVERROR_INVALIDDATA; | |
192 | } | |
193 | ||
194 | return 0; | |
195 | } | |
196 | ||
98a6fff9 | 197 | static av_cold int tta_decode_init(AVCodecContext * avctx) |
a24c4a2a AB |
198 | { |
199 | TTAContext *s = avctx->priv_data; | |
5778299c | 200 | int total_frames; |
a24c4a2a AB |
201 | |
202 | s->avctx = avctx; | |
203 | ||
204 | // 30bytes includes a seektable with one frame | |
205 | if (avctx->extradata_size < 30) | |
206 | return -1; | |
207 | ||
b59efc94 | 208 | init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size * 8); |
2bb6eba2 | 209 | if (show_bits_long(&s->gb, 32) == AV_RL32("TTA1")) |
a24c4a2a | 210 | { |
2af3dc86 PM |
211 | if (avctx->err_recognition & AV_EF_CRCCHECK) { |
212 | s->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); | |
ea1d64ab | 213 | tta_check_crc(s, avctx->extradata, 18); |
2af3dc86 PM |
214 | } |
215 | ||
a24c4a2a | 216 | /* signature */ |
9aff2d17 | 217 | skip_bits_long(&s->gb, 32); |
a24c4a2a | 218 | |
b16960a8 JR |
219 | s->format = get_bits(&s->gb, 16); |
220 | if (s->format > 2) { | |
221 | av_log(s->avctx, AV_LOG_ERROR, "Invalid format\n"); | |
a24c4a2a AB |
222 | return -1; |
223 | } | |
b16960a8 JR |
224 | if (s->format == FORMAT_ENCRYPTED) { |
225 | av_log_missing_feature(s->avctx, "Encrypted TTA", 0); | |
717addec | 226 | return AVERROR_PATCHWELCOME; |
b16960a8 | 227 | } |
1a174c28 | 228 | avctx->channels = s->channels = get_bits(&s->gb, 16); |
dd1c8f3e LA |
229 | avctx->bits_per_coded_sample = get_bits(&s->gb, 16); |
230 | s->bps = (avctx->bits_per_coded_sample + 7) / 8; | |
1a174c28 | 231 | avctx->sample_rate = get_bits_long(&s->gb, 32); |
1a174c28 | 232 | s->data_length = get_bits_long(&s->gb, 32); |
9aff2d17 | 233 | skip_bits_long(&s->gb, 32); // CRC32 of header |
a24c4a2a | 234 | |
8bd1f1a4 SG |
235 | if (s->channels == 0) { |
236 | av_log(s->avctx, AV_LOG_ERROR, "Invalid number of channels\n"); | |
237 | return AVERROR_INVALIDDATA; | |
7416d610 RB |
238 | } else if (avctx->sample_rate == 0) { |
239 | av_log(s->avctx, AV_LOG_ERROR, "Invalid samplerate\n"); | |
240 | return AVERROR_INVALIDDATA; | |
8bd1f1a4 SG |
241 | } |
242 | ||
b16960a8 | 243 | switch(s->bps) { |
c6056d40 JR |
244 | case 2: |
245 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; | |
246 | avctx->bits_per_raw_sample = 16; | |
247 | break; | |
248 | case 3: | |
249 | avctx->sample_fmt = AV_SAMPLE_FMT_S32; | |
250 | avctx->bits_per_raw_sample = 24; | |
251 | break; | |
252 | default: | |
253 | av_log(avctx, AV_LOG_ERROR, "Invalid/unsupported sample format.\n"); | |
254 | return AVERROR_INVALIDDATA; | |
a24c4a2a AB |
255 | } |
256 | ||
b5050539 | 257 | // prevent overflow |
ac80b812 | 258 | if (avctx->sample_rate > 0x7FFFFFu) { |
b5050539 JR |
259 | av_log(avctx, AV_LOG_ERROR, "sample_rate too large\n"); |
260 | return AVERROR(EINVAL); | |
261 | } | |
262 | s->frame_length = 256 * avctx->sample_rate / 245; | |
a24c4a2a AB |
263 | |
264 | s->last_frame_length = s->data_length % s->frame_length; | |
5778299c JR |
265 | total_frames = s->data_length / s->frame_length + |
266 | (s->last_frame_length ? 1 : 0); | |
a24c4a2a | 267 | |
b16960a8 JR |
268 | av_log(s->avctx, AV_LOG_DEBUG, "format: %d chans: %d bps: %d rate: %d block: %d\n", |
269 | s->format, avctx->channels, avctx->bits_per_coded_sample, avctx->sample_rate, | |
a24c4a2a AB |
270 | avctx->block_align); |
271 | av_log(s->avctx, AV_LOG_DEBUG, "data_length: %d frame_length: %d last: %d total: %d\n", | |
5778299c | 272 | s->data_length, s->frame_length, s->last_frame_length, total_frames); |
a24c4a2a AB |
273 | |
274 | // FIXME: seek table | |
5778299c JR |
275 | if (avctx->extradata_size <= 26 || total_frames > INT_MAX / 4 || |
276 | avctx->extradata_size - 26 < total_frames * 4) | |
2af3dc86 PM |
277 | av_log(avctx, AV_LOG_WARNING, "Seek table missing or too small\n"); |
278 | else if (avctx->err_recognition & AV_EF_CRCCHECK) { | |
5778299c | 279 | if (tta_check_crc(s, avctx->extradata + 22, total_frames * 4)) |
2af3dc86 PM |
280 | return AVERROR_INVALIDDATA; |
281 | } | |
5778299c | 282 | skip_bits_long(&s->gb, 32 * total_frames); |
9aff2d17 | 283 | skip_bits_long(&s->gb, 32); // CRC32 of seektable |
a24c4a2a | 284 | |
3a1a7e32 MN |
285 | if(s->frame_length >= UINT_MAX / (s->channels * sizeof(int32_t))){ |
286 | av_log(avctx, AV_LOG_ERROR, "frame_length too large\n"); | |
287 | return -1; | |
288 | } | |
289 | ||
c6056d40 JR |
290 | if (s->bps == 2) { |
291 | s->decode_buffer = av_mallocz(sizeof(int32_t)*s->frame_length*s->channels); | |
2f1d212f JR |
292 | if (!s->decode_buffer) |
293 | return AVERROR(ENOMEM); | |
c6056d40 | 294 | } |
5113b3bd | 295 | s->ch_ctx = av_malloc(avctx->channels * sizeof(*s->ch_ctx)); |
2f1d212f JR |
296 | if (!s->ch_ctx) { |
297 | av_freep(&s->decode_buffer); | |
5113b3bd | 298 | return AVERROR(ENOMEM); |
2f1d212f | 299 | } |
a24c4a2a AB |
300 | } else { |
301 | av_log(avctx, AV_LOG_ERROR, "Wrong extradata present\n"); | |
302 | return -1; | |
303 | } | |
304 | ||
305 | return 0; | |
306 | } | |
307 | ||
0eea2129 JR |
308 | static int tta_decode_frame(AVCodecContext *avctx, void *data, |
309 | int *got_frame_ptr, AVPacket *avpkt) | |
a24c4a2a | 310 | { |
ad2104ba | 311 | AVFrame *frame = data; |
7a00bbad TB |
312 | const uint8_t *buf = avpkt->data; |
313 | int buf_size = avpkt->size; | |
a24c4a2a | 314 | TTAContext *s = avctx->priv_data; |
0eea2129 | 315 | int i, ret; |
7b7a74a1 JR |
316 | int cur_chan = 0, framelen = s->frame_length; |
317 | int32_t *p; | |
a24c4a2a | 318 | |
2af3dc86 PM |
319 | if (avctx->err_recognition & AV_EF_CRCCHECK) { |
320 | if (buf_size < 4 || tta_check_crc(s, buf, buf_size - 4)) | |
321 | return AVERROR_INVALIDDATA; | |
322 | } | |
323 | ||
a24c4a2a | 324 | init_get_bits(&s->gb, buf, buf_size*8); |
a24c4a2a | 325 | |
0eea2129 | 326 | /* get output buffer */ |
ad2104ba | 327 | frame->nb_samples = framelen; |
759001c5 | 328 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { |
0eea2129 JR |
329 | av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
330 | return ret; | |
8664682d JR |
331 | } |
332 | ||
c6056d40 JR |
333 | // decode directly to output buffer for 24-bit sample format |
334 | if (s->bps == 3) | |
ad2104ba | 335 | s->decode_buffer = (int32_t *)frame->data[0]; |
c6056d40 | 336 | |
8664682d JR |
337 | // init per channel states |
338 | for (i = 0; i < s->channels; i++) { | |
339 | s->ch_ctx[i].predictor = 0; | |
323b9da9 | 340 | ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1]); |
8664682d JR |
341 | rice_init(&s->ch_ctx[i].rice, 10, 10); |
342 | } | |
e6923f68 | 343 | |
5778299c | 344 | i = 0; |
8664682d JR |
345 | for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) { |
346 | int32_t *predictor = &s->ch_ctx[cur_chan].predictor; | |
347 | TTAFilter *filter = &s->ch_ctx[cur_chan].filter; | |
348 | TTARice *rice = &s->ch_ctx[cur_chan].rice; | |
349 | uint32_t unary, depth, k; | |
350 | int32_t value; | |
351 | ||
352 | unary = tta_get_unary(&s->gb); | |
353 | ||
354 | if (unary == 0) { | |
355 | depth = 0; | |
356 | k = rice->k0; | |
357 | } else { | |
358 | depth = 1; | |
359 | k = rice->k1; | |
360 | unary--; | |
a24c4a2a AB |
361 | } |
362 | ||
6ab681a4 JR |
363 | if (get_bits_left(&s->gb) < k) { |
364 | ret = AVERROR_INVALIDDATA; | |
365 | goto error; | |
366 | } | |
a24c4a2a | 367 | |
8664682d | 368 | if (k) { |
6ab681a4 JR |
369 | if (k > MIN_CACHE_BITS) { |
370 | ret = AVERROR_INVALIDDATA; | |
371 | goto error; | |
372 | } | |
8664682d JR |
373 | value = (unary << k) + get_bits(&s->gb, k); |
374 | } else | |
375 | value = unary; | |
376 | ||
377 | // FIXME: copy paste from original | |
378 | switch (depth) { | |
379 | case 1: | |
380 | rice->sum1 += value - (rice->sum1 >> 4); | |
381 | if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) | |
382 | rice->k1--; | |
383 | else if(rice->sum1 > shift_16[rice->k1 + 1]) | |
384 | rice->k1++; | |
385 | value += shift_1[rice->k0]; | |
386 | default: | |
387 | rice->sum0 += value - (rice->sum0 >> 4); | |
388 | if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) | |
389 | rice->k0--; | |
390 | else if(rice->sum0 > shift_16[rice->k0 + 1]) | |
391 | rice->k0++; | |
392 | } | |
a9837b58 | 393 | |
8664682d | 394 | // extract coded value |
f2a4559c | 395 | *p = 1 + ((value >> 1) ^ ((value & 1) - 1)); |
a24c4a2a | 396 | |
8664682d | 397 | // run hybrid filter |
323b9da9 | 398 | ttafilter_process(filter, p); |
a24c4a2a | 399 | |
8664682d | 400 | // fixed order prediction |
79a32e3b | 401 | #define PRED(x, k) (int32_t)((((uint64_t)x << k) - x) >> k) |
8664682d | 402 | switch (s->bps) { |
e04ca1d4 PM |
403 | case 1: *p += PRED(*predictor, 4); break; |
404 | case 2: | |
405 | case 3: *p += PRED(*predictor, 5); break; | |
406 | case 4: *p += *predictor; break; | |
8664682d JR |
407 | } |
408 | *predictor = *p; | |
409 | ||
410 | // flip channels | |
411 | if (cur_chan < (s->channels-1)) | |
412 | cur_chan++; | |
413 | else { | |
46ea4635 | 414 | // decorrelate in case of multiple channels |
8664682d JR |
415 | if (s->channels > 1) { |
416 | int32_t *r = p - 1; | |
417 | for (*p += *r / 2; r > p - s->channels; r--) | |
418 | *r = *(r + 1) - *r; | |
a24c4a2a | 419 | } |
8664682d | 420 | cur_chan = 0; |
5778299c JR |
421 | i++; |
422 | // check for last frame | |
423 | if (i == s->last_frame_length && get_bits_left(&s->gb) / 8 == 4) { | |
ad2104ba | 424 | frame->nb_samples = framelen = s->last_frame_length; |
5778299c JR |
425 | break; |
426 | } | |
a24c4a2a | 427 | } |
8664682d | 428 | } |
a24c4a2a | 429 | |
5778299c | 430 | align_get_bits(&s->gb); |
6ab681a4 JR |
431 | if (get_bits_left(&s->gb) < 32) { |
432 | ret = AVERROR_INVALIDDATA; | |
433 | goto error; | |
434 | } | |
9aff2d17 | 435 | skip_bits_long(&s->gb, 32); // frame crc |
8664682d JR |
436 | |
437 | // convert to output buffer | |
c6056d40 | 438 | if (s->bps == 2) { |
ad2104ba | 439 | int16_t *samples = (int16_t *)frame->data[0]; |
c6056d40 JR |
440 | for (p = s->decode_buffer; p < s->decode_buffer + (framelen * s->channels); p++) |
441 | *samples++ = *p; | |
442 | } else { | |
443 | // shift samples for 24-bit sample format | |
ad2104ba | 444 | int32_t *samples = (int32_t *)frame->data[0]; |
b656c4d0 | 445 | for (i = 0; i < framelen * s->channels; i++) |
c6056d40 JR |
446 | *samples++ <<= 8; |
447 | // reset decode buffer | |
448 | s->decode_buffer = NULL; | |
8664682d | 449 | } |
a24c4a2a | 450 | |
ad2104ba | 451 | *got_frame_ptr = 1; |
c6056d40 | 452 | |
a24c4a2a | 453 | return buf_size; |
6ab681a4 JR |
454 | error: |
455 | // reset decode buffer | |
456 | if (s->bps == 3) | |
457 | s->decode_buffer = NULL; | |
458 | return ret; | |
a24c4a2a AB |
459 | } |
460 | ||
98a6fff9 | 461 | static av_cold int tta_decode_close(AVCodecContext *avctx) { |
a24c4a2a AB |
462 | TTAContext *s = avctx->priv_data; |
463 | ||
437fb1c8 | 464 | av_free(s->decode_buffer); |
5113b3bd | 465 | av_freep(&s->ch_ctx); |
a24c4a2a AB |
466 | |
467 | return 0; | |
468 | } | |
469 | ||
d36beb3f | 470 | AVCodec ff_tta_decoder = { |
ec6402b7 AK |
471 | .name = "tta", |
472 | .type = AVMEDIA_TYPE_AUDIO, | |
36ef5369 | 473 | .id = AV_CODEC_ID_TTA, |
ec6402b7 AK |
474 | .priv_data_size = sizeof(TTAContext), |
475 | .init = tta_decode_init, | |
476 | .close = tta_decode_close, | |
477 | .decode = tta_decode_frame, | |
0eea2129 | 478 | .capabilities = CODEC_CAP_DR1, |
0177b7d2 | 479 | .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), |
a24c4a2a | 480 | }; |