[FFmpeg-devel] [PATCH] QCELP decoder

Vitor Sessak vitor1001
Thu Oct 2 23:25:17 CEST 2008


Kenan Gillet wrote:
> Hi,
> On Sep 30, 2008, at 11:30 AM, Vitor Sessak wrote:
> 
>> Kenan Gillet wrote:
>>> +static int qcelp_decode_frame(AVCodecContext *avctx,
>>> +                              void *data, int *data_size,
>>> +                              uint8_t *buf, const int buf_size) {
>>> +    QCELPContext      *q = avctx->priv_data;
>>> +    const QCELPBitmap *order = NULL;
>>> +    int16_t           *outbuffer = data;
>>> +    int               i, bits;
>>> +    float             qtzd_lspf[10], lpc[10];
>>> +    float             cdn_vector[160], ppf_vector[160];
>>> +    float             *formant_mem;
>>> +
>>> +    if (determine_rate(avctx, q, buf_size, &buf) < 0) {
>>> +        av_log(avctx, AV_LOG_ERROR, "frame #%d: unknown framerate,  
>>> unsupported size: %d\n",
>>> +               q->frame_num++, buf_size);
>>> +        return -1;
>>> +    }
>>> +
>>> +    if (q->rate == RATE_OCTAVE && buf[0] == 0xFF && buf[1] ==  
>>> 0xFF) {
>>> +        warn_insufficient_frame_quality(avctx, "rate is 1/8 and  
>>> first 16 bits are on.");
>>> +        goto erasure;
>>> +    }
>>> +
>>> +    order = qcelp_unpacking_bitmpap_per_rate[q->rate];
>>> +    if (order) {
>>> +        bits = qcelp_bits_per_rate[q->rate];
>>> +
>>> +        init_get_bits(&q->gb, buf, buf_size*8);
>>> +
>>> +        memset(q->data, 0, sizeof(q->data));
>>> +        for (i=0; i < bits; i++) {
>>> +            q->data[ order[i].index ] |= get_bits1(&q- 
>>>> gb)<<order[i].bitpos;
>>> +        }
>>> +
>>> +        // Check for erasures/blanks on rates 1, 1/4 and 1/8
>>> +        if (q->data[QCELP_RSRVD_POS]) {
>>> +            warn_insufficient_frame_quality(avctx, "wrong data in  
>>> reserved frame area.");
>>> +              goto erasure;
>>> +        }
>>> +    }
>>> +
>>> +    if (decode_scaled_codebook_vector(q, cdn_vector) < 0) {
>>> +        warn_insufficient_frame_quality(avctx, "sanity check of  
>>> the codebook gain failed.");
>>> +        goto erasure;
>>> +    }
>>> +
>>> +    if (decode_lspf(q, qtzd_lspf) < 0) {
>>> +        warn_insufficient_frame_quality(avctx, "badly received  
>>> packets in frame.");
>>> +        goto erasure;
>>> +    }
>>> +
>>> +
>>> +    if (apply_pitch_filters(q, cdn_vector, ppf_vector)) {
>>> +        warn_insufficient_frame_quality(avctx, "cannot initiliaze  
>>> pitch filter.");
>>> +        goto erasure;
>>> +    }
>>> +
>>> +    if (q->rate == I_F_Q) {
>>> +erasure:
>>> +        q->rate = I_F_Q;
>>> +        q->erasure_count++;
>>> +        decode_scaled_codebook_vector(q, cdn_vector);
>>> +        decode_lspf(q, qtzd_lspf);
>>> +        apply_pitch_filters(q, cdn_vector, ppf_vector);
>>> +    }
>>> +
>>> +    formant_mem = q->formant_mem;
>>> +    for (i=0; i<4; i++) {
>>> +        interpolate_lpc(q, qtzd_lspf, lpc, i);
>>> +
>>> +        do_formant(ppf_vector+i*40, lpc, formant_mem);
>>> +
>>> +        // WIP Adaptive postfilter should be here
>>> +
>>> +         formant_mem = ppf_vector + i * 40 + 30;
>>> +    }
>>> +    memcpy(q->formant_mem, ppf_vector + 150, 10 * sizeof(float));
>>> +
>>> +    if (q->rate != I_F_Q) {
>>> +        q->erasure_count = 0;
>>> +    }
>>> +
>>> +    for (i=0; i<160; i++) {
>>> +        outbuffer[i]=av_clip_int16(lrintf(4*ppf_vector[i]));
>>> +    }
>> You could avoid this copying and get rid of the ppf_vector if you make
>> the decoder output floats. See
>> http://thread.gmane.org/gmane.comp.video.ffmpeg.cvs/17802 to see how  
>> it
>> was done in the RA288 decoder.
> 
> I've been able to output float, but i had to divide each float value  
> by a 'big' constant value
> (I settle on 4096) to make it work normally.
> something like
> 
>      for (i = 0; i < 160; i++) {
>          outbuffer[i] /= 4096.;
>      }
> 
> 
> 
> I looked at the sample for ra288, welcome288.ra and it seems the  
> decoder ouptut float bewtween -1 and 1.
> So I was wondering if the output float needs to be in a certain range ?

For codecs that were supposed to be converted to signed 16-bit at some 
point should be indeed between -1. and 1.. A good way to test if did not 
do something wrong is to decode a sample to wav and see if your change 
changes the result. It should either don't change or change a negligible 
amount (see tests/tiny_psnr for evaluating how much it has changed).

-Vitor




More information about the ffmpeg-devel mailing list