1314 lines · 45.2 KB · C
RawDownload
/* * COOK compatible decoder * Copyright (c) 2003 Sascha Sommer * Copyright (c) 2005 Benjamin Larsson * * 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 * Cook compatible decoder. Bastardization of the G.722.1 standard. * This decoder handles RealNetworks, RealAudio G2 data. * Cook is identified by the codec name cook in RM files. * * To use this decoder, a calling application must supply the extradata * bytes provided from the RM container; 8+ bytes for mono streams and * 16+ for stereo streams (maybe more). * * Codec technicalities (all this assume a buffer length of 1024): * Cook works with several different techniques to achieve its compression. * In the timedomain the buffer is divided into 8 pieces and quantized. If * two neighboring pieces have different quantization index a smooth * quantization curve is used to get a smooth overlap between the different * pieces. * To get to the transformdomain Cook uses a modulated lapped transform. * The transform domain has 50 subbands with 20 elements each. This * means only a maximum of 50*20=1000 coefficients are used out of the 1024 * available. */ #include "libavutil/channel_layout.h"#include "libavutil/lfg.h"#include "libavutil/mem.h"#include "libavutil/mem_internal.h"#include "libavutil/thread.h"#include "libavutil/tx.h" #include "audiodsp.h"#include "avcodec.h"#include "get_bits.h"#include "bytestream.h"#include "codec_internal.h"#include "decode.h"#include "sinewin.h"#include "unary.h" #include "cookdata.h" /* the different Cook versions */#define MONO            0x1000001#define STEREO          0x1000002#define JOINT_STEREO    0x1000003#define MC_COOK         0x2000000 #define SUBBAND_SIZE    20#define MAX_SUBPACKETS   5 #define QUANT_VLC_BITS    9#define COUPLING_VLC_BITS 6 typedef struct cook_gains {    int *now;    int *previous;} cook_gains; typedef struct COOKSubpacket {    int                 ch_idx;    int                 size;    int                 num_channels;    int                 cookversion;    int                 subbands;    int                 js_subband_start;    int                 js_vlc_bits;    int                 samples_per_channel;    int                 log2_numvector_size;    unsigned int        channel_mask;    VLC                 channel_coupling;    int                 joint_stereo;    int                 bits_per_subpacket;    int                 bits_per_subpdiv;    int                 total_subbands;    int                 numvector_size;       // 1 << log2_numvector_size;     float               mono_previous_buffer1[1024];    float               mono_previous_buffer2[1024];     cook_gains          gains1;    cook_gains          gains2;    int                 gain_1[9];    int                 gain_2[9];    int                 gain_3[9];    int                 gain_4[9];} COOKSubpacket; typedef struct cook {    /*     * The following 5 functions provide the lowlevel arithmetic on     * the internal audio buffers.     */    void (*scalar_dequant)(struct cook *q, int index, int quant_index,                           int *subband_coef_index, int *subband_coef_sign,                           float *mlt_p);     void (*decouple)(struct cook *q,                     COOKSubpacket *p,                     int subband,                     float f1, float f2,                     float *decode_buffer,                     float *mlt_buffer1, float *mlt_buffer2);     void (*imlt_window)(struct cook *q, float *buffer1,                        cook_gains *gains_ptr, float *previous_buffer);     void (*interpolate)(struct cook *q, float *buffer,                        int gain_index, int gain_index_next);     void (*saturate_output)(struct cook *q, float *out);     AVCodecContext*     avctx;    AudioDSPContext     adsp;    GetBitContext       gb;    /* stream data */    int                 num_vectors;    int                 samples_per_channel;    /* states */    AVLFG               random_state;    int                 discarded_packets;     /* transform data */    AVTXContext        *mdct_ctx;    av_tx_fn            mdct_fn;    float*              mlt_window;     /* VLC data */    VLC                 envelope_quant_index[13];    VLC                 sqvh[7];          // scalar quantization     /* generate tables and related variables */    int                 gain_size_factor;    float               gain_table[31];     /* data buffers */     uint8_t*            decoded_bytes_buffer;    DECLARE_ALIGNED(32, float, mono_mdct_output)[2048];    float               decode_buffer_1[1024];    float               decode_buffer_2[1024];    float               decode_buffer_0[1060]; /* static allocation for joint decode */     const float         *cplscales[5];    int                 num_subpackets;    COOKSubpacket       subpacket[MAX_SUBPACKETS];} COOKContext; static float     pow2tab[127];static float rootpow2tab[127]; /*************** init functions ***************/ /* table generator */static av_cold void init_pow2table(void){    /* fast way of computing 2^i and 2^(0.5*i) for -63 <= i < 64 */    int i;    static const float exp2_tab[2] = {1, M_SQRT2};    float exp2_val = powf(2, -63);    float root_val = powf(2, -32);    for (i = -63; i < 64; i++) {        if (!(i & 1))            root_val *= 2;        pow2tab[63 + i] = exp2_val;        rootpow2tab[63 + i] = root_val * exp2_tab[i & 1];        exp2_val *= 2;    }} /* table generator */static av_cold void init_gain_table(COOKContext *q){    int i;    q->gain_size_factor = q->samples_per_channel / 8;    for (i = 0; i < 31; i++)        q->gain_table[i] = pow(pow2tab[i + 48],                               (1.0 / (double) q->gain_size_factor));} static av_cold int build_vlc(VLC *vlc, int nb_bits, const uint8_t counts[16],                             const void *syms, int symbol_size, int offset,                             void *logctx){    uint8_t lens[MAX_COOK_VLC_ENTRIES];    unsigned num = 0;     for (int i = 0; i < 16; i++)        for (unsigned count = num + counts[i]; num < count; num++)            lens[num] = i + 1;     return ff_vlc_init_from_lengths(vlc, nb_bits, num, lens, 1,                                    syms, symbol_size, symbol_size,                                    offset, 0, logctx);} static av_cold int init_cook_vlc_tables(COOKContext *q){    int i, result;     result = 0;    for (i = 0; i < 13; i++) {        result |= build_vlc(&q->envelope_quant_index[i], QUANT_VLC_BITS,                            envelope_quant_index_huffcounts[i],                            envelope_quant_index_huffsyms[i], 1, -12, q->avctx);    }    av_log(q->avctx, AV_LOG_DEBUG, "sqvh VLC init\n");    for (i = 0; i < 7; i++) {        int sym_size = 1 + (i == 3);        result |= build_vlc(&q->sqvh[i], vhvlcsize_tab[i],                            cvh_huffcounts[i],                            cvh_huffsyms[i], sym_size, 0, q->avctx);    }     for (i = 0; i < q->num_subpackets; i++) {        if (q->subpacket[i].joint_stereo == 1) {            result |= build_vlc(&q->subpacket[i].channel_coupling, COUPLING_VLC_BITS,                                ccpl_huffcounts[q->subpacket[i].js_vlc_bits - 2],                                ccpl_huffsyms[q->subpacket[i].js_vlc_bits - 2], 1,                                0, q->avctx);            av_log(q->avctx, AV_LOG_DEBUG, "subpacket %i Joint-stereo VLC used.\n", i);        }    }     av_log(q->avctx, AV_LOG_DEBUG, "VLC tables initialized.\n");    return result;} static av_cold int init_cook_mlt(COOKContext *q){    int j, ret;    int mlt_size = q->samples_per_channel;    const float scale = 1.0 / 32768.0;     if (!(q->mlt_window = av_malloc_array(mlt_size, sizeof(*q->mlt_window))))        return AVERROR(ENOMEM);     /* Initialize the MLT window: simple sine window. */    ff_sine_window_init(q->mlt_window, mlt_size);    for (j = 0; j < mlt_size; j++)        q->mlt_window[j] *= sqrt(2.0 / q->samples_per_channel);     /* Initialize the MDCT. */    ret = av_tx_init(&q->mdct_ctx, &q->mdct_fn, AV_TX_FLOAT_MDCT,                     1, mlt_size, &scale, AV_TX_FULL_IMDCT);    if (ret < 0)        return ret;     return 0;} static av_cold void init_cplscales_table(COOKContext *q){    int i;    for (i = 0; i < 5; i++)        q->cplscales[i] = cplscales[i];} /*************** init functions end ***********/ #define DECODE_BYTES_PAD1(bytes) (3 - ((bytes) + 3) % 4)#define DECODE_BYTES_PAD2(bytes) ((bytes) % 4 + DECODE_BYTES_PAD1(2 * (bytes))) /** * Cook indata decoding, every 32 bits are XORed with 0x37c511f2. * Why? No idea, some checksum/error detection method maybe. * * Out buffer size: extra bytes are needed to cope with * padding/misalignment. * Subpackets passed to the decoder can contain two, consecutive * half-subpackets, of identical but arbitrary size. *          1234 1234 1234 1234  extraA extraB * Case 1:  AAAA BBBB              0      0 * Case 2:  AAAA ABBB BB--         3      3 * Case 3:  AAAA AABB BBBB         2      2 * Case 4:  AAAA AAAB BBBB BB--    1      5 * * Nice way to waste CPU cycles. * * @param inbuffer  pointer to byte array of indata * @param out       pointer to byte array of outdata * @param bytes     number of bytes */static inline int decode_bytes(const uint8_t *inbuffer, uint8_t *out, int bytes){    static const uint32_t tab[4] = {        AV_BE2NE32C(0x37c511f2u), AV_BE2NE32C(0xf237c511u),        AV_BE2NE32C(0x11f237c5u), AV_BE2NE32C(0xc511f237u),    };    int i, off;    uint32_t c;    const uint32_t *buf;    uint32_t *obuf = (uint32_t *) out;    /* FIXME: 64 bit platforms would be able to do 64 bits at a time.     * I'm too lazy though, should be something like     * for (i = 0; i < bitamount / 64; i++)     *     (int64_t) out[i] = 0x37c511f237c511f2 ^ av_be2ne64(int64_t) in[i]);     * Buffer alignment needs to be checked. */     off = (intptr_t) inbuffer & 3;    buf = (const uint32_t *) (inbuffer - off);    c = tab[off];    bytes += 3 + off;    for (i = 0; i < bytes / 4; i++)        obuf[i] = c ^ buf[i];     return off;} static av_cold int cook_decode_close(AVCodecContext *avctx){    int i;    COOKContext *q = avctx->priv_data;    av_log(avctx, AV_LOG_DEBUG, "Deallocating memory.\n");     /* Free allocated memory buffers. */    av_freep(&q->mlt_window);    av_freep(&q->decoded_bytes_buffer);     /* Free the transform. */    av_tx_uninit(&q->mdct_ctx);     /* Free the VLC tables. */    for (i = 0; i < 13; i++)        ff_vlc_free(&q->envelope_quant_index[i]);    for (i = 0; i < 7; i++)        ff_vlc_free(&q->sqvh[i]);    for (i = 0; i < q->num_subpackets; i++)        ff_vlc_free(&q->subpacket[i].channel_coupling);     av_log(avctx, AV_LOG_DEBUG, "Memory deallocated.\n");     return 0;} /** * Fill the gain array for the timedomain quantization. * * @param gb          pointer to the GetBitContext * @param gaininfo    array[9] of gain indexes */static void decode_gain_info(GetBitContext *gb, int *gaininfo){    int i, n;     n = get_unary(gb, 0, get_bits_left(gb));     // amount of elements*2 to update     i = 0;    while (n--) {        int index = get_bits(gb, 3);        int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1;         while (i <= index)            gaininfo[i++] = gain;    }    while (i <= 8)        gaininfo[i++] = 0;} /** * Create the quant index table needed for the envelope. * * @param q                 pointer to the COOKContext * @param quant_index_table pointer to the array */static int decode_envelope(COOKContext *q, COOKSubpacket *p,                           int *quant_index_table){    int i, j, vlc_index;     quant_index_table[0] = get_bits(&q->gb, 6) - 6; // This is used later in categorize     for (i = 1; i < p->total_subbands; i++) {        vlc_index = i;        if (i >= p->js_subband_start * 2) {            vlc_index -= p->js_subband_start;        } else {            vlc_index /= 2;            if (vlc_index < 1)                vlc_index = 1;        }        if (vlc_index > 13)            vlc_index = 13; // the VLC tables >13 are identical to No. 13         j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index - 1].table,                     QUANT_VLC_BITS, 2);        quant_index_table[i] = quant_index_table[i - 1] + j; // differential encoding        if (quant_index_table[i] > 63 || quant_index_table[i] < -63) {            av_log(q->avctx, AV_LOG_ERROR,                   "Invalid quantizer %d at position %d, outside [-63, 63] range\n",                   quant_index_table[i], i);            return AVERROR_INVALIDDATA;        }    }     return 0;} /** * Calculate the category and category_index vector. * * @param q                     pointer to the COOKContext * @param quant_index_table     pointer to the array * @param category              pointer to the category array * @param category_index        pointer to the category_index array */static void categorize(COOKContext *q, COOKSubpacket *p, const int *quant_index_table,                       int *category, int *category_index){    int exp_idx, bias, tmpbias1, tmpbias2, bits_left, num_bits, index, v, i, j;    int exp_index2[102] = { 0 };    int exp_index1[102] = { 0 };     int tmp_categorize_array[128 * 2] = { 0 };    int tmp_categorize_array1_idx = p->numvector_size;    int tmp_categorize_array2_idx = p->numvector_size;     bits_left = p->bits_per_subpacket - get_bits_count(&q->gb);     if (bits_left > q->samples_per_channel)        bits_left = q->samples_per_channel +                    ((bits_left - q->samples_per_channel) * 5) / 8;     bias = -32;     /* Estimate bias. */    for (i = 32; i > 0; i = i / 2) {        num_bits = 0;        index    = 0;        for (j = p->total_subbands; j > 0; j--) {            exp_idx = av_clip_uintp2((i - quant_index_table[index] + bias) / 2, 3);            index++;            num_bits += expbits_tab[exp_idx];        }        if (num_bits >= bits_left - 32)            bias += i;    }     /* Calculate total number of bits. */    num_bits = 0;    for (i = 0; i < p->total_subbands; i++) {        exp_idx = av_clip_uintp2((bias - quant_index_table[i]) / 2, 3);        num_bits += expbits_tab[exp_idx];        exp_index1[i] = exp_idx;        exp_index2[i] = exp_idx;    }    tmpbias1 = tmpbias2 = num_bits;     for (j = 1; j < p->numvector_size; j++) {        if (tmpbias1 + tmpbias2 > 2 * bits_left) {  /* ---> */            int max = -999999;            index = -1;            for (i = 0; i < p->total_subbands; i++) {                if (exp_index1[i] < 7) {                    v = (-2 * exp_index1[i]) - quant_index_table[i] + bias;                    if (v >= max) {                        max   = v;                        index = i;                    }                }            }            if (index == -1)                break;            tmp_categorize_array[tmp_categorize_array1_idx++] = index;            tmpbias1 -= expbits_tab[exp_index1[index]] -                        expbits_tab[exp_index1[index] + 1];            ++exp_index1[index];        } else {  /* <--- */            int min = 999999;            index = -1;            for (i = 0; i < p->total_subbands; i++) {                if (exp_index2[i] > 0) {                    v = (-2 * exp_index2[i]) - quant_index_table[i] + bias;                    if (v < min) {                        min   = v;                        index = i;                    }                }            }            if (index == -1)

Lines 1–500 of 1314.

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