History

avcodec/binkaudio: add support for >2 channels dct codec

As presented in .binka files.

Paul B Mahol committed 4 years ago

Commit 902ee9c1 parent fa989df1 file · +33 −18Browse files

Unified · Split

libavcodec/binkaudio.c+33−18
@@ -44,6 +44,7 @@ · 43 unmodified lines
44#include "rdft.h"44#include "rdft.h"
45#include "wma_freqs.h"45#include "wma_freqs.h"
46 46
47#define MAX_DCT_CHANNELS 6
47#define MAX_CHANNELS 248#define MAX_CHANNELS 2
48#define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11)49#define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11)
49 50
@@ -52,13 +53,14 @@ typedef struct BinkAudioContext { · 2 unmodified lines
52 int version_b; ///< Bink version 'b'53 int version_b; ///< Bink version 'b'
53 int first;54 int first;
54 int channels;55 int channels;
56 int ch_offset;
55 int frame_len; ///< transform size (samples)57 int frame_len; ///< transform size (samples)
56 int overlap_len; ///< overlap size (samples)58 int overlap_len; ///< overlap size (samples)
57 int block_size;59 int block_size;
58 int num_bands;60 int num_bands;
59 float root;61 float root;
60 unsigned int bands[26];62 unsigned int bands[26];
61 float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block63 float previous[MAX_DCT_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block
62 float quant_table[96];64 float quant_table[96];
63 AVPacket *pkt;65 AVPacket *pkt;
64 union {66 union {
@@ -75,6 +77,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 10 unmodified lines
75 int sample_rate_half;77 int sample_rate_half;
76 int i, ret;78 int i, ret;
77 int frame_len_bits;79 int frame_len_bits;
80 int max_channels = avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT ? MAX_CHANNELS : MAX_DCT_CHANNELS;
78 int channels = avctx->ch_layout.nb_channels;81 int channels = avctx->ch_layout.nb_channels;
79 82
80 /* determine frame length */83 /* determine frame length */
@@ -86,7 +89,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 5 unmodified lines
86 frame_len_bits = 11;89 frame_len_bits = 11;
87 }90 }
88 91
89 if (channels < 1 || channels > MAX_CHANNELS) {92 if (channels < 1 || channels > max_channels) {
90 av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", channels);93 av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", channels);
91 return AVERROR_INVALIDDATA;94 return AVERROR_INVALIDDATA;
92 }95 }
@@ -111,7 +114,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 18 unmodified lines
111 114
112 s->frame_len = 1 << frame_len_bits;115 s->frame_len = 1 << frame_len_bits;
113 s->overlap_len = s->frame_len / 16;116 s->overlap_len = s->frame_len / 16;
114 s->block_size = (s->frame_len - s->overlap_len) * s->channels;117 s->block_size = (s->frame_len - s->overlap_len) * FFMIN(MAX_CHANNELS, s->channels);
115 sample_rate_half = (sample_rate + 1LL) / 2;118 sample_rate_half = (sample_rate + 1LL) / 2;
116 if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT)119 if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT)
117 s->root = 2.0 / (sqrt(s->frame_len) * 32768.0);120 s->root = 2.0 / (sqrt(s->frame_len) * 32768.0);
@@ -167,7 +170,8 @@ static const uint8_t rle_length_tab[16] = { · 49 unmodified lines
167 * @param[out] out Output buffer (must contain s->block_size elements)170 * @param[out] out Output buffer (must contain s->block_size elements)
168 * @return 0 on success, negative error code on failure171 * @return 0 on success, negative error code on failure
169 */172 */
170static int decode_block(BinkAudioContext *s, float **out, int use_dct)173static int decode_block(BinkAudioContext *s, float **out, int use_dct,
174 int channels, int ch_offset)
171{175{
172 int ch, i, j, k;176 int ch, i, j, k;
173 float q, quant[25];177 float q, quant[25];
@@ -177,8 +181,8 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) · 3 unmodified lines
177 if (use_dct)181 if (use_dct)
178 skip_bits(gb, 2);182 skip_bits(gb, 2);
179 183
180 for (ch = 0; ch < s->channels; ch++) {184 for (ch = 0; ch < channels; ch++) {
181 FFTSample *coeffs = out[ch];185 FFTSample *coeffs = out[ch + ch_offset];
182 186
183 if (s->version_b) {187 if (s->version_b) {
184 if (get_bits_left(gb) < 64)188 if (get_bits_left(gb) < 64)
@@ -253,17 +257,17 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) · 68 unmodified lines
253 s->trans.rdft.rdft_calc(&s->trans.rdft, coeffs);257 s->trans.rdft.rdft_calc(&s->trans.rdft, coeffs);
254 }258 }
255 259
256 for (ch = 0; ch < s->channels; ch++) {260 for (ch = 0; ch < channels; ch++) {
257 int j;261 int j;
258 int count = s->overlap_len * s->channels;262 int count = s->overlap_len * channels;
259 if (!s->first) {263 if (!s->first) {
260 j = ch;264 j = ch;
261 for (i = 0; i < s->overlap_len; i++, j += s->channels)265 for (i = 0; i < s->overlap_len; i++, j += channels)
262 out[ch][i] = (s->previous[ch][i] * (count - j) +266 out[ch + ch_offset][i] = (s->previous[ch + ch_offset][i] * (count - j) +
263 out[ch][i] * j) / count;267 out[ch + ch_offset][i] * j) / count;
264 }268 }
265 memcpy(s->previous[ch], &out[ch][s->frame_len - s->overlap_len],269 memcpy(s->previous[ch + ch_offset], &out[ch + ch_offset][s->frame_len - s->overlap_len],
266 s->overlap_len * sizeof(*s->previous[ch]));270 s->overlap_len * sizeof(*s->previous[ch + ch_offset]));
267 }271 }
268 272
269 s->first = 0;273 s->first = 0;
@@ -294,6 +298,7 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) · 24 unmodified lines
294 GetBitContext *gb = &s->gb;298 GetBitContext *gb = &s->gb;
295 int ret;299 int ret;
296 300
301again:
297 if (!s->pkt->data) {302 if (!s->pkt->data) {
298 ret = ff_decode_get_packet(avctx, s->pkt);303 ret = ff_decode_get_packet(avctx, s->pkt);
299 if (ret < 0)304 if (ret < 0)
@@ -314,22 +319,31 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) · 14 unmodified lines
314 }319 }
315 320
316 /* get output buffer */321 /* get output buffer */
317 frame->nb_samples = s->frame_len;322 if (s->ch_offset == 0) {
318 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)323 frame->nb_samples = s->frame_len;
319 return ret;324 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
325 return ret;
326 }
320 327
321 if (decode_block(s, (float **)frame->extended_data,328 if (decode_block(s, (float **)frame->extended_data,
322 avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT)) {329 avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT,
330 FFMIN(MAX_CHANNELS, s->channels - s->ch_offset), s->ch_offset)) {
323 av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n");331 av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n");
324 return AVERROR_INVALIDDATA;332 return AVERROR_INVALIDDATA;
325 }333 }
334 s->ch_offset += MAX_CHANNELS;
326 get_bits_align32(gb);335 get_bits_align32(gb);
327 if (!get_bits_left(gb)) {336 if (!get_bits_left(gb)) {
328 memset(gb, 0, sizeof(*gb));337 memset(gb, 0, sizeof(*gb));
329 av_packet_unref(s->pkt);338 av_packet_unref(s->pkt);
330 }339 }
340 if (s->ch_offset >= s->channels) {
341 s->ch_offset = 0;
342 } else {
343 goto again;
344 }
331 345
332 frame->nb_samples = s->block_size / avctx->ch_layout.nb_channels;346 frame->nb_samples = s->block_size / FFMIN(avctx->ch_layout.nb_channels, MAX_CHANNELS);
333 347
334 return 0;348 return 0;
335fail:349fail:
@@ -344,6 +358,7 @@ static void decode_flush(AVCodecContext *avctx) · 8 unmodified lines
344 /* s->pkt coincides with avctx->internal->in_pkt358 /* s->pkt coincides with avctx->internal->in_pkt
345 * and is unreferenced generically when flushing. */359 * and is unreferenced generically when flushing. */
346 s->first = 1;360 s->first = 1;
361 s->ch_offset = 0;
347}362}
348 363
349const FFCodec ff_binkaudio_rdft_decoder = {364const FFCodec ff_binkaudio_rdft_decoder = {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t