On 03/18/2012 03:43 AM, Kostya Shishkov wrote:

> Here's the new version (again with ralfdata.h cut out).
> 
> 
> 0001-RealAudio-Lossless-decoder.patch
> 
> 
>>From 5ca870c71f05f39008bc38ffaa94cf791421809e Mon Sep 17 00:00:00 2001
> From: Kostya Shishkov <[email protected]>
> Date: Sat, 17 Mar 2012 08:48:57 +0100
> Subject: [PATCH] RealAudio Lossless decoder
> 
> ---
>  Changelog              |    1 +
>  doc/general.texi       |    1 +
>  libavcodec/Makefile    |    1 +
>  libavcodec/allcodecs.c |    1 +
>  libavcodec/avcodec.h   |    1 +
>  libavcodec/ralf.c      |  536 +++
>  libavcodec/ralfdata.h  | 9920 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  libavformat/rm.c       |    1 +
>  libavformat/rmdec.c    |    9 +
>  9 files changed, 10471 insertions(+), 0 deletions(-)
>  create mode 100644 libavcodec/ralf.c
>  create mode 100644 libavcodec/ralfdata.h
> 
[...]
> +/**
> + * @file
> + * This is a decoder for Retarded Audio Lossless format.
> + * Dedicated to the mastermind behind it, Ralph Wiggum.
> + */


Please leave out the "Retarded" part.

> +
> +#include "avcodec.h"
> +#include "get_bits.h"
> +#include "golomb.h"
> +#include "unary.h"
> +#include "libavutil/audioconvert.h"
> +#include "ralfdata.h"
> +
> +#define FILTER_NONE 0
> +#define FILTER_RAW  642
> +
> +typedef struct VLCSet {
> +    VLC filter_params;
> +    VLC bias;
> +    VLC coding_mode;
> +    VLC filter_coeffs[10][11];
> +    VLC short_codes[15];
> +    VLC long_codes[125];
> +} VLCSet;
> +
> +#define RALF_MAX_PKT_SIZE 8192
> +
> +typedef struct RALFContext {
> +    AVFrame frame;
> +
> +    int version;
> +    int max_frame_size;
> +    VLCSet sets[3];
> +    int channel_data[2][4096];


could you make that int32_t for more reliable size if we want to add asm
optimizations at some point?

> +
> +    int filter_params;
> +    int filter_length;
> +    int filter_bits;
> +    int filter[64];
> +
> +    int bias[2];
> +
> +    int num_blocks;
> +    int sample_offset;
> +    int block_size[1 << 12];
> +    int block_pts[1 << 12];
> +
> +    uint8_t pkt[16384];
> +    int has_pkt;
> +} RALFContext;


would you mind documenting some of those fields?

[...]
> +static int decode_block(AVCodecContext *avctx, GetBitContext *gb, int16_t 
> *dst)
> +{
> +    RALFContext *ctx = avctx->priv_data;
> +    int len, ch, ret;
> +    int dmode, mode[2], bits[2];
> +    int *ch0, *ch1;
> +    int i, t, t2;
> +
> +    len = 12 - get_unary(gb, 0, 6);
> +
> +    if (len <= 7) len ^= 1; // codes for length = 6 and 7 are swapped
> +    len = 1 << len;
> +
> +    if (ctx->sample_offset + len > ctx->max_frame_size)
> +        return AVERROR_INVALIDDATA;


maybe add some log message about sum of block durations exceeding the
maximum frame duration

> +
> +    if (avctx->channels > 1)
> +        dmode = get_bits(gb, 2) + 1;
> +    else
> +        dmode = 0;
> +
> +    mode[0] = (dmode == 4) ? 1 : 0;
> +    mode[1] = (dmode >= 2) ? 2 : 0;
> +    bits[0] = 16;
> +    bits[1] = (mode[1] == 2) ? 17 : 16;
> +
> +    if (ctx->sample_offset + len > ctx->max_frame_size)
> +        return -1;


didn't you just check that above?

[...]
> +    if (ctx->has_pkt) {
> +        ctx->has_pkt = 0;
> +        table_bytes = (AV_RB16(avpkt->data) + 7) >> 3;
> +        if (table_bytes + 3 > avpkt->size || avpkt->size > 
> RALF_MAX_PKT_SIZE) {
> +            av_log(avctx, AV_LOG_ERROR, "Wrong packet's breath smells of 
> wrong data!\n");
> +            return AVERROR_INVALIDDATA;
> +        }
> +        if (memcmp(ctx->pkt, avpkt->data, 2 + table_bytes)) {
> +            av_log(avctx, AV_LOG_ERROR, "Wrong packets are wrong!\n");
> +            return AVERROR_INVALIDDATA;
> +        }


a better message might be something like "second partial packet does not
match the first. discarding packet."

> +
> +        src      = ctx->pkt;
> +        src_size = RALF_MAX_PKT_SIZE + avpkt->size;
> +        memcpy(ctx->pkt + RALF_MAX_PKT_SIZE, avpkt->data + 2 + table_bytes,
> +               avpkt->size - 2 - table_bytes);
> +    } else {
> +        if (avpkt->size == RALF_MAX_PKT_SIZE) {
> +            memcpy(ctx->pkt, avpkt->data, avpkt->size);
> +            ctx->has_pkt   = 1;
> +            *got_frame_ptr = 0;
> +
> +            return avpkt->size;
> +        }
> +        src      = avpkt->data;
> +        src_size = avpkt->size;
> +    }


it doesn't look like you're validating that the packet is not larger
than RALF_MAX_PKT_SIZE in the single-packet case.

> +
> +    ctx->frame.nb_samples = ctx->max_frame_size;
> +    if ((ret = avctx->get_buffer(avctx, &ctx->frame)) < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Me fail get_buffer()? That's 
> unpossible!\n");
> +        return ret;
> +    }
> +    samples = (int16_t*)ctx->frame.data[0];
> +
> +    if (src_size < 5) {
> +        av_log(avctx, AV_LOG_ERROR, "too short packets are too short!\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    table_size  = AV_RB16(src);
> +    table_bytes = (table_size + 7) >> 3;
> +    if (src_size < table_bytes + 3) {
> +        av_log(avctx, AV_LOG_ERROR, "short packets are short!\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    init_get_bits(&gb, src + 2, table_size);
> +    ctx->num_blocks = 0;
> +    while (get_bits_left(&gb) > 0) {
> +        ctx->block_size[ctx->num_blocks] = get_bits(&gb, 15);
> +        if (get_bits1(&gb)) {
> +            ctx->block_pts[ctx->num_blocks] = get_bits(&gb, 9);
> +        } else {
> +            ctx->block_pts[ctx->num_blocks] = 0;
> +        }
> +        ctx->num_blocks++;
> +    }
> +
> +    block_pointer = src      + table_bytes + 2;
> +    bytes_left    = src_size - table_bytes - 2;
> +    ctx->sample_offset = 0;
> +    for (i = 0; i < ctx->num_blocks; i++) {
> +        if (bytes_left < ctx->block_size[i]) {
> +            av_log(avctx, AV_LOG_ERROR, "I'm pedaling backwards\n");
> +            break;
> +        }
> +        init_get_bits(&gb, block_pointer, ctx->block_size[i] * 8);
> +        if (decode_block(avctx, &gb, samples + ctx->sample_offset
> +                                               * avctx->channels) < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Sir, I got carsick in your 
> office\n");


This one definitely needs a better error message, especially since we're
returning truncated output instead of an error.

Cheers,
Justin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to