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
4444 #include "rdft.h"
4545 #include "wma_freqs.h"
4646
47+#define MAX_DCT_CHANNELS 6
4748 #define MAX_CHANNELS 2
4849 #define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11)
4950
@@ -52,13 +53,14 @@ typedef struct BinkAudioContext { · 2 unmodified lines
5253 int version_b; ///< Bink version 'b'
5354 int first;
5455 int channels;
56+ int ch_offset;
5557 int frame_len; ///< transform size (samples)
5658 int overlap_len; ///< overlap size (samples)
5759 int block_size;
5860 int num_bands;
5961 float root;
6062 unsigned int bands[26];
61− float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block
63+ float previous[MAX_DCT_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block
6264 float quant_table[96];
6365 AVPacket *pkt;
6466 union {
@@ -75,6 +77,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 10 unmodified lines
7577 int sample_rate_half;
7678 int i, ret;
7779 int frame_len_bits;
80+ int max_channels = avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT ? MAX_CHANNELS : MAX_DCT_CHANNELS;
7881 int channels = avctx->ch_layout.nb_channels;
7982
8083 /* determine frame length */
@@ -86,7 +89,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 5 unmodified lines
8689 frame_len_bits = 11;
8790 }
8891
89− if (channels < 1 || channels > MAX_CHANNELS) {
92+ if (channels < 1 || channels > max_channels) {
9093 av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", channels);
9194 return AVERROR_INVALIDDATA;
9295 }
@@ -111,7 +114,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 18 unmodified lines
111114
112115 s->frame_len = 1 << frame_len_bits;
113116 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);
115118 sample_rate_half = (sample_rate + 1LL) / 2;
116119 if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT)
117120 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
167170 * @param[out] out Output buffer (must contain s->block_size elements)
168171 * @return 0 on success, negative error code on failure
169172 */
170−static int decode_block(BinkAudioContext *s, float **out, int use_dct)
173+static int decode_block(BinkAudioContext *s, float **out, int use_dct,
174+ int channels, int ch_offset)
171175 {
172176 int ch, i, j, k;
173177 float q, quant[25];
@@ -177,8 +181,8 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) · 3 unmodified lines
177181 if (use_dct)
178182 skip_bits(gb, 2);
179183
180− for (ch = 0; ch < s->channels; ch++) {
181− FFTSample *coeffs = out[ch];
184+ for (ch = 0; ch < channels; ch++) {
185+ FFTSample *coeffs = out[ch + ch_offset];
182186
183187 if (s->version_b) {
184188 if (get_bits_left(gb) < 64)
@@ -253,17 +257,17 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) · 68 unmodified lines
253257 s->trans.rdft.rdft_calc(&s->trans.rdft, coeffs);
254258 }
255259
256− for (ch = 0; ch < s->channels; ch++) {
260+ for (ch = 0; ch < channels; ch++) {
257261 int j;
258− int count = s->overlap_len * s->channels;
262+ int count = s->overlap_len * channels;
259263 if (!s->first) {
260264 j = ch;
261− for (i = 0; i < s->overlap_len; i++, j += s->channels)
262− out[ch][i] = (s->previous[ch][i] * (count - j) +
263− out[ch][i] * j) / count;
265+ for (i = 0; i < s->overlap_len; i++, j += channels)
266+ out[ch + ch_offset][i] = (s->previous[ch + ch_offset][i] * (count - j) +
267+ out[ch + ch_offset][i] * j) / count;
264268 }
265− memcpy(s->previous[ch], &out[ch][s->frame_len - s->overlap_len],
266− s->overlap_len * sizeof(*s->previous[ch]));
269+ memcpy(s->previous[ch + ch_offset], &out[ch + ch_offset][s->frame_len - s->overlap_len],
270+ s->overlap_len * sizeof(*s->previous[ch + ch_offset]));
267271 }
268272
269273 s->first = 0;
@@ -294,6 +298,7 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) · 24 unmodified lines
294298 GetBitContext *gb = &s->gb;
295299 int ret;
296300
301+again:
297302 if (!s->pkt->data) {
298303 ret = ff_decode_get_packet(avctx, s->pkt);
299304 if (ret < 0)
@@ -314,22 +319,31 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) · 14 unmodified lines
314319 }
315320
316321 /* get output buffer */
317− frame->nb_samples = s->frame_len;
318− if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
319− return ret;
322+ if (s->ch_offset == 0) {
323+ frame->nb_samples = s->frame_len;
324+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
325+ return ret;
326+ }
320327
321328 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)) {
323331 av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n");
324332 return AVERROR_INVALIDDATA;
325333 }
334+ s->ch_offset += MAX_CHANNELS;
326335 get_bits_align32(gb);
327336 if (!get_bits_left(gb)) {
328337 memset(gb, 0, sizeof(*gb));
329338 av_packet_unref(s->pkt);
330339 }
340+ if (s->ch_offset >= s->channels) {
341+ s->ch_offset = 0;
342+ } else {
343+ goto again;
344+ }
331345
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);
333347
334348 return 0;
335349 fail:
@@ -344,6 +358,7 @@ static void decode_flush(AVCodecContext *avctx) · 8 unmodified lines
344358 /* s->pkt coincides with avctx->internal->in_pkt
345359 * and is unreferenced generically when flushing. */
346360 s->first = 1;
361+ s->ch_offset = 0;
347362 }
348363
349364 const 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