[FFmpeg-devel] [PATCH] ALS decoder

Michael Niedermayer michaelni
Fri Aug 28 15:15:54 CEST 2009


On Wed, Aug 26, 2009 at 08:28:43PM +0200, Thilo Borgmann wrote:
> Revision 11 attached.
[...]
> +/** Reads an ALSSpecificConfig from a buffer into the output struct.
> + */
> +static av_cold int read_specific_config(ALSDecContext *ctx)
> +{
> +    GetBitContext gb;
> +    uint64_t ht_size;
> +    int i, config_offset, crc_enabled;
> +    MPEG4AudioConfig m4ac;
> +    ALSSpecificConfig *sconf = &ctx->sconf;
> +    AVCodecContext *avctx    = ctx->avctx;
> +    const uint8_t *buffer    = avctx->extradata;
> +    uint32_t samples, als_id;
> +
> +    init_get_bits(&gb, buffer, avctx->extradata_size * 8);
> +
> +    config_offset = ff_mpeg4audio_get_config(&m4ac, buffer, avctx->extradata_size);
> +
> +    if (config_offset < 0)
> +        return -1;
> +
> +    skip_bits_long(&gb, config_offset);
> +
> +    if (get_bits_left(&gb) < (22 << 3))
> +        return -1;

is that the smallest size a valid frame can have? i would have suspect it
to be larger
Now if it where larger, several of the following checks could be removed


[...]
> +/** Reads and decodes a Rice codeword.
> + */
> +static int32_t decode_rice(GetBitContext *gb, unsigned int k)
> +{
> +    int max   = gb->size_in_bits - get_bits_count(gb) - k;
> +    int32_t q = get_unary(gb, 0, max);

i suspect int is fine for these 2 instead of int32_t ?


> +    int r     = k ? get_bits1(gb) : !(q & 1);
> +
> +    if (k > 1)
> +        q = (q << (k - 1)) + get_bits_long(gb, k - 1);
> +    else if (!k)
> +        q = (q >> 1);
> +
> +    return r ? q : ~q;
> +}
> +
> +

> +/** Converts PARCOR coefficient k to direct filter coefficient.
> + */
> +static int parcor_to_lpc(unsigned int k, int32_t *par, int32_t *cof)

par should be const


> +{
> +    int i;
> +
> +    for (i = 0; i < (k + 1) >> 1; i++) {

> +        int64_t tmp1 = cof[    i    ] + ((MUL64(par[k], cof[k - i - 1]) + (1 << 19)) >> 20);
> +        int64_t tmp2 = cof[k - i - 1] + ((MUL64(par[k], cof[    i    ]) + (1 << 19)) >> 20);
> +
> +        if (tmp1 < -INT32_MAX || tmp1 > INT32_MAX ||
> +            tmp2 < -INT32_MAX || tmp2 > INT32_MAX)
> +            return -1;
> +
> +        cof[k - i - 1] = tmp2;
> +        cof[    i    ] = tmp1;

if we didnt do overflow checks ...

int tmp1        = (MUL64(par[k], cof[k - i - 1]) + (1 << 19)) >> 20;
cof[k - i - 1] += (MUL64(par[k], cof[    i    ]) + (1 << 19)) >> 20;
cof[    i    ] += tmp1;

also, you could try: (maybe its faster

int64_t tmp1 = cof[    i    ] + ((MUL64(par[k], cof[k - i - 1]) + (1 << 19)) >> 20);
int64_t tmp2 = cof[k - i - 1] + ((MUL64(par[k], cof[    i    ]) + (1 << 19)) >> 20);

cof[k - i - 1] = tmp2;
cof[    i    ] = tmp1;

if(   cof[k - i - 1] != tmp2
   || cof[    i    ] != tmp1)
    return -1;


[...]
> +
> +/** Reads the block data for a non-constant block
> + */
> +static int read_var_block(ALSDecContext *ctx, unsigned int ra_block,
> +                          int32_t *raw_samples, unsigned int block_length,
> +                          unsigned int *js_blocks, int32_t *raw_other,
> +                          unsigned int *shift_lsbs)
> +{
> +    ALSSpecificConfig *sconf = &ctx->sconf;
> +    AVCodecContext *avctx    = ctx->avctx;
> +    GetBitContext *gb        = &ctx->gb;
> +    unsigned int k;
> +    unsigned int s[8];
> +    unsigned int sub_blocks, sb_length;
> +    unsigned int opt_order  = 1;
> +    int32_t      *quant_cof = ctx->quant_cof;
> +    int32_t      *lpc_cof   = ctx->lpc_cof;
> +    unsigned int start      = 0;
> +    int          sb, smp;
> +    int64_t      y;
> +
> +    *js_blocks  = get_bits1(gb);
> +
> +    // determine the number of sub blocks for entropy decoding
> +    if (!sconf->bgmc && !sconf->sb_part)
> +        sub_blocks = 1;
> +    else if (sconf->bgmc && sconf->sb_part)
> +        sub_blocks = 1 << get_bits(gb, 2);
> +    else
> +        sub_blocks = 1 << (2 * get_bits1(gb));
> +
> +    // do not continue in case of a damaged stream since
> +    // block_length must be evenly divisible by sub_blocks
> +    if (block_length % sub_blocks) {
> +        av_log(avctx, AV_LOG_WARNING,
> +               "Block length is not evenly divisible by the number of sub blocks.\n");
> +        return -1;
> +    }
> +
> +    sb_length = block_length / sub_blocks;
> +
> +
> +    if (sconf->bgmc) {
> +        // TODO: BGMC mode
> +    } else {
> +        s[0] = get_bits(gb, (sconf->resolution > 1) ? 5 : 4);
> +        for (k = 1; k < sub_blocks; k++)
> +            s[k] = s[k - 1] + decode_rice(gb, 0);
> +    }
> +
> +    if (get_bits1(gb))
> +        *shift_lsbs = get_bits(gb, 4) + 1;
> +
> +
> +    if (!sconf->rlslms) {
> +        if (sconf->adapt_order) {
> +            int opt_order_length = FFMAX(av_ceil_log2((block_length >> 3) - 1), 1);
> +            opt_order_length     = FFMIN(av_ceil_log2(sconf->max_order+1), opt_order_length);
> +            opt_order            = get_bits(gb, opt_order_length);
> +        } else {
> +            opt_order = sconf->max_order;
> +        }
> +
> +        if (opt_order) {
> +            if (sconf->coef_table == 3) {
> +                // read coefficient 0
> +                quant_cof[0] = parcor_scaled_values[get_bits(gb, 7)];
> +
> +                // read coefficient 1
> +                quant_cof[1] = -parcor_scaled_values[get_bits(gb, 7)];
> +
> +                // read coefficients 2 to opt_order
> +                for (k = 2; k < opt_order; k++)
> +                    quant_cof[k] = (get_bits(gb, 7) << 14) - (0x7F << 13);
> +            } else {
> +                int offset, rice_param, k_max;
> +                int64_t quant_index;
> +
> +
> +                // read coefficient 0 to 19
> +                k_max = FFMIN(20, opt_order);
> +                for (k = 0; k < k_max; k++) {
> +                    offset       = parcor_rice_table[sconf->coef_table][k][0];
> +                    rice_param   = parcor_rice_table[sconf->coef_table][k][1];
> +                    quant_cof[k] = decode_rice(gb, rice_param) + offset;
> +                }
> +
> +                quant_cof[0] =  parcor_scaled_values[quant_cof[0] + 64];
> +                quant_cof[1] = -parcor_scaled_values[quant_cof[1] + 64];
> +
> +                for (k = 2; k < k_max; k++)
> +                    quant_cof[k] = (quant_cof[k] << 14) + (1 << 13);
> +
> +                // read coefficients 20 to 126
> +                k_max = FFMIN(127, opt_order);
> +                for (; k < k_max; k++) {
> +                    offset       = k & 1;
> +                    rice_param   = 2;
> +                    quant_index  = decode_rice(gb, rice_param) + offset;
> +                    quant_cof[k] = (quant_index << 14) + (1 << 13);
> +                }
> +
> +                // read coefficients 127 to opt_order
> +                for (; k < opt_order; k++) {
> +                    offset       = 0;
> +                    rice_param   = 1;
> +                    quant_index  = decode_rice(gb, rice_param) + offset;
> +                    quant_cof[k] = (quant_index << 14) + (1 << 13);
> +                }

// read coefficient 0 to 19
k_max = FFMIN( 20, opt_order);
for (k = 0; k < k_max; k++) {
    int offset     = parcor_rice_table[sconf->coef_table][k][0];
    int rice_param = parcor_rice_table[sconf->coef_table][k][1];
    quant_cof[k] = decode_rice(gb, rice_param) + offset;
}

// read coefficients 20 to 126
k_max = FFMIN(127, opt_order);
for (; k < k_max; k++)
    quant_cof[k] = decode_rice(gb, 2) + (k&1);

// read coefficients 127 to opt_order
for (; k < opt_order; k++)
    quant_cof[k] = decode_rice(gb, 1);

quant_cof[0] =  parcor_scaled_values[quant_cof[0] + 64];
quant_cof[1] = -parcor_scaled_values[quant_cof[1] + 64];

for (k = 2; k < opt_order; k++)
    quant_cof[k] = (quant_cof[k] << 14) + (1 << 13);


and this likely can be factored with the sconf->coef_table == 3 case


[...]
> +/** Reads the block data.
> + */
> +static int read_block_data(ALSDecContext *ctx, unsigned int ra_block,
> +                           int32_t *raw_samples, unsigned int block_length,
> +                           unsigned int *js_blocks, int32_t *raw_other)
> +{
> +    ALSSpecificConfig *sconf = &ctx->sconf;
> +    GetBitContext *gb        = &ctx->gb;
> +    unsigned int shift_lsbs  = 0;
> +    unsigned int k;
> +
> +    // read block type flag and read the accordingly
> +    if (!get_bits1(gb)) {
> +        read_const_block(ctx, raw_samples, block_length, js_blocks);
> +    } else {
> +        if (read_var_block(ctx, ra_block, raw_samples, block_length, js_blocks,
> +                           raw_other, &shift_lsbs))
> +            return -1;
> +    }

if(x)
else

is simpler than

if(!x)
else


[...]
> +/** Computes the bytes left to decode for the current frame
> + */
> +static void zero_remaining(unsigned int b, unsigned int b_max,
> +                           unsigned int *div_blocks, int32_t *buf)
> +{

div_blocks should be const, also this likel applies to other arguments of
other functions


[...]
> +/** Reads the frame data.
> + */
> +static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame)
> +{
> +    ALSSpecificConfig *sconf = &ctx->sconf;
> +    AVCodecContext *avctx    = ctx->avctx;
> +    GetBitContext *gb = &ctx->gb;
> +    unsigned int div_blocks[32];                ///< Block sizes.
> +    unsigned int c, b, ra_block;
> +    int32_t *raw_samples_L;
> +    unsigned int js_blocks[2];
> +
> +    uint32_t bs_info = 0;
> +    unsigned int *ptr_div_blocks;
> +

> +    // skip ra_unit_size if present
> +    if (sconf->ra_flag == RA_FLAG_FRAMES && ra_frame)
> +        skip_bits_long(gb, 32);

what do these skiped bits represent?


> +
> +    if (sconf->mc_coding && sconf->joint_stereo) {
> +        ctx->js_switch = get_bits1(gb);
> +        align_get_bits(gb);
> +    }
> +
> +    if (!sconf->mc_coding || ctx->js_switch) {
> +        int independent_bs = !sconf->joint_stereo;
> +
> +        for (c = 0; c < avctx->channels; c++) {
> +            js_blocks[0] = 0;
> +            js_blocks[1] = 0;
> +
> +            if (sconf->block_switching) {
> +                unsigned int bs_info_len = 1 << (sconf->block_switching + 2);
> +                bs_info = get_bits_long(gb, bs_info_len);
> +                bs_info <<= (32 - bs_info_len);
> +            }
> +
> +            ctx->num_blocks = 0;
> +            ptr_div_blocks = &div_blocks[0];
> +            parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks);
> +            reconstruct_block_sizes(ctx, div_blocks);
> +
> +            // if joint_stereo and block_switching is set, independent decoding
> +            // is signaled via the first bit of bs_info
> +            if (sconf->joint_stereo && sconf->block_switching) {
> +                if (bs_info >> 31)
> +                    independent_bs = 2;
> +            }
> +
> +            // if this is the last channel, it has to be decoded independently
> +            if (c == avctx->channels - 1)
> +                independent_bs = 1;
> +
> +            if (independent_bs) {
> +                if (decode_blocks_ind(ctx, ra_frame, c, div_blocks, js_blocks))
> +                    return -1;
> +
> +                if (independent_bs)
> +                    independent_bs--;
> +            } else {
> +                if (decode_blocks(ctx, ra_frame, c, div_blocks, js_blocks))
> +                    return -1;
> +
> +                c++;
> +            }
> +
> +        // store carryover raw samples
> +        memmove((ctx->raw_samples[c]) - sconf->max_order,
> +                (ctx->raw_samples[c]) - sconf->max_order + sconf->frame_length,
> +                sizeof(*ctx->raw_samples[c]) * sconf->max_order);
> +        }
> +    } else { // multi-channel coding
> +        if (sconf->block_switching) {
> +            unsigned int bs_info_len = 1 << (sconf->block_switching + 2);
> +            bs_info = get_bits_long(gb, bs_info_len);
> +            bs_info <<= (32 - bs_info_len);
> +        }
> +
> +        ctx->num_blocks = 0;
> +        ptr_div_blocks = &div_blocks[0];
> +        parse_bs_info(bs_info, 0, 0, &ptr_div_blocks, &ctx->num_blocks);
> +        reconstruct_block_sizes(ctx, div_blocks);
> +
> +        // TODO: multi channel coding might use a temporary buffer instead as
> +        //       the actual channel is not known when read_block-data is called
> +        raw_samples_L = ctx->raw_samples[0];
> +
> +        for (b = 0; b < ctx->num_blocks; b++) {
> +            ra_block = !b && ra_frame;

ra_block= ra_frame;
for(){
    ...
    ra_block= 0;
}



[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

I do not agree with what you have to say, but I'll defend to the death your
right to say it. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090828/2bf61cd5/attachment.pgp>



More information about the ffmpeg-devel mailing list