view binkaudio.c @ 11211:dfeaae916502 libavcodec

Since WavPack chunk can contain more samples than FFmpeg is guaranteed to hold, decode it in several iterations outputting as many samples as possible.
author kostya
date Fri, 19 Feb 2010 14:05:41 +0000
parents 28f00789adcd
children 359c8ba0698e
line wrap: on
line source

/*
 * Bink Audio decoder
 * Copyright (c) 2007-2010 Peter Ross (pross@xvid.org)
 * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file libavcodec/binkaudio.c
 * Bink Audio decoder
 *
 * Technical details here:
 *  http://wiki.multimedia.cx/index.php?title=Bink_Audio
 */

#include "avcodec.h"
#define ALT_BITSTREAM_READER_LE
#include "get_bits.h"
#include "dsputil.h"
extern const uint16_t ff_wma_critical_freqs[25];

#define MAX_CHANNELS 2
#define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11)

typedef struct {
    AVCodecContext *avctx;
    GetBitContext gb;
    DSPContext dsp;
    int first;
    int channels;
    int frame_len;          ///< transform size (samples)
    int overlap_len;        ///< overlap size (samples)
    int block_size;
    int num_bands;
    unsigned int *bands;
    float root;
    DECLARE_ALIGNED_16(FFTSample, coeffs)[BINK_BLOCK_MAX_SIZE];
    DECLARE_ALIGNED_16(short, previous)[BINK_BLOCK_MAX_SIZE / 16];  ///< coeffs from previous audio block
    float *coeffs_ptr[MAX_CHANNELS]; ///< pointers to the coeffs arrays for float_to_int16_interleave
    union {
        RDFTContext rdft;
        DCTContext dct;
    } trans;
} BinkAudioContext;


static av_cold int decode_init(AVCodecContext *avctx)
{
    BinkAudioContext *s = avctx->priv_data;
    int sample_rate = avctx->sample_rate;
    int sample_rate_half;
    int i;
    int frame_len_bits;

    s->avctx = avctx;
    dsputil_init(&s->dsp, avctx);

    /* determine frame length */
    if (avctx->sample_rate < 22050) {
        frame_len_bits = 9;
    } else if (avctx->sample_rate < 44100) {
        frame_len_bits = 10;
    } else {
        frame_len_bits = 11;
    }
    s->frame_len = 1 << frame_len_bits;

    if (s->channels > MAX_CHANNELS) {
        av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels);
        return -1;
    }

    if (avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT) {
        // audio is already interleaved for the RDFT format variant
        sample_rate  *= avctx->channels;
        s->frame_len *= avctx->channels;
        s->channels = 1;
        if (avctx->channels == 2)
            frame_len_bits++;
    } else {
        s->channels = avctx->channels;
    }

    s->overlap_len   = s->frame_len / 16;
    s->block_size    = (s->frame_len - s->overlap_len) * s->channels;
    sample_rate_half = (sample_rate + 1) / 2;
    s->root          = 2.0 / sqrt(s->frame_len);

    /* calculate number of bands */
    for (s->num_bands = 1; s->num_bands < 25; s->num_bands++)
        if (sample_rate_half <= ff_wma_critical_freqs[s->num_bands - 1])
            break;

    s->bands = av_malloc((s->num_bands + 1) * sizeof(*s->bands));
    if (!s->bands)
        return AVERROR(ENOMEM);

    /* populate bands data */
    s->bands[0] = 1;
    for (i = 1; i < s->num_bands; i++)
        s->bands[i] = ff_wma_critical_freqs[i - 1] * (s->frame_len / 2) / sample_rate_half;
    s->bands[s->num_bands] = s->frame_len / 2;

    s->first = 1;
    avctx->sample_fmt = SAMPLE_FMT_S16;

    for (i = 0; i < s->channels; i++)
        s->coeffs_ptr[i] = s->coeffs + i * s->frame_len;

    if (avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT)
        ff_rdft_init(&s->trans.rdft, frame_len_bits, IRIDFT);
    else
        ff_dct_init(&s->trans.dct, frame_len_bits, 0);

    return 0;
}

static float get_float(GetBitContext *gb)
{
    int power = get_bits(gb, 5);
    float f = ldexpf(get_bits_long(gb, 23), power - 23);
    if (get_bits1(gb))
        f = -f;
    return f;
}

static const uint8_t rle_length_tab[16] = {
    2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64
};

/**
 * Decode Bink Audio block
 * @param[out] out Output buffer (must contain s->block_size elements)
 */
static void decode_block(BinkAudioContext *s, short *out, int use_dct)
{
    int ch, i, j, k;
    float q, quant[25];
    int width, coeff;
    GetBitContext *gb = &s->gb;

    if (use_dct)
        skip_bits(gb, 2);

    for (ch = 0; ch < s->channels; ch++) {
        FFTSample *coeffs = s->coeffs_ptr[ch];
        q = 0.0f;
        coeffs[0] = get_float(gb) * s->root;
        coeffs[1] = get_float(gb) * s->root;

        for (i = 0; i < s->num_bands; i++) {
            /* constant is result of 0.066399999/log10(M_E) */
            int value = get_bits(gb, 8);
            quant[i] = expf(FFMIN(value, 95) * 0.15289164787221953823f) * s->root;
        }

        // find band (k)
        for (k = 0; s->bands[k] < 1; k++) {
            q = quant[k];
        }

        // parse coefficients
        i = 2;
        while (i < s->frame_len) {
            if (get_bits1(gb)) {
                j = i + rle_length_tab[get_bits(gb, 4)] * 8;
            } else {
                j = i + 8;
            }

            j = FFMIN(j, s->frame_len);

            width = get_bits(gb, 4);
            if (width == 0) {
                memset(coeffs + i, 0, (j - i) * sizeof(*coeffs));
                i = j;
                while (s->bands[k] * 2 < i)
                    q = quant[k++];
            } else {
                while (i < j) {
                    if (s->bands[k] * 2 == i)
                        q = quant[k++];
                    coeff = get_bits(gb, width);
                    if (coeff) {
                        if (get_bits1(gb))
                            coeffs[i] = -q * coeff;
                        else
                            coeffs[i] =  q * coeff;
                    } else {
                        coeffs[i] = 0.0f;
                    }
                    i++;
                }
            }
        }

        if (use_dct)
            ff_dct_calc (&s->trans.dct,  coeffs);
        else
            ff_rdft_calc(&s->trans.rdft, coeffs);
    }

    s->dsp.float_to_int16_interleave(out, (const float **)s->coeffs_ptr, s->frame_len, s->channels);

    if (!s->first) {
        int count = s->overlap_len * s->channels;
        int shift = av_log2(count);
        for (i = 0; i < count; i++) {
            out[i] = (s->previous[i] * (count - i) + out[i] * i) >> shift;
        }
    }

    memcpy(s->previous, out + s->block_size,
           s->overlap_len * s->channels * sizeof(*out));

    s->first = 0;
}

static av_cold int decode_end(AVCodecContext *avctx)
{
    BinkAudioContext * s = avctx->priv_data;
    av_freep(&s->bands);
    if (avctx->codec->id == CODEC_ID_BINKAUDIO_RDFT)
        ff_rdft_end(&s->trans.rdft);
    else
        ff_dct_end(&s->trans.dct);
    return 0;
}

static void get_bits_align32(GetBitContext *s)
{
    int n = (-get_bits_count(s)) & 31;
    if (n) skip_bits(s, n);
}

static int decode_frame(AVCodecContext *avctx,
                        void *data, int *data_size,
                        AVPacket *avpkt)
{
    BinkAudioContext *s = avctx->priv_data;
    const uint8_t *buf  = avpkt->data;
    int buf_size        = avpkt->size;
    short *samples      = data;
    short *samples_end  = (short*)((uint8_t*)data + *data_size);
    int reported_size;
    GetBitContext *gb = &s->gb;

    init_get_bits(gb, buf, buf_size * 8);

    reported_size = get_bits_long(gb, 32);
    while (get_bits_count(gb) / 8 < buf_size &&
           samples + s->block_size <= samples_end) {
        decode_block(s, samples, avctx->codec->id == CODEC_ID_BINKAUDIO_DCT);
        samples += s->block_size;
        get_bits_align32(gb);
    }

    *data_size = (uint8_t*)samples - (uint8_t*)data;
    if (reported_size != *data_size) {
        av_log(avctx, AV_LOG_WARNING, "reported data size (%d) does not match output data size (%d)\n",
             reported_size, *data_size);
    }
    return buf_size;
}

AVCodec binkaudio_rdft_decoder = {
    "binkaudio_rdft",
    CODEC_TYPE_AUDIO,
    CODEC_ID_BINKAUDIO_RDFT,
    sizeof(BinkAudioContext),
    decode_init,
    NULL,
    decode_end,
    decode_frame,
    .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)")
};

AVCodec binkaudio_dct_decoder = {
    "binkaudio_dct",
    CODEC_TYPE_AUDIO,
    CODEC_ID_BINKAUDIO_DCT,
    sizeof(BinkAudioContext),
    decode_init,
    NULL,
    decode_end,
    decode_frame,
    .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)")
};