[FFmpeg-devel] [PATCH] QCELP decoder

Vitor Sessak vitor1001
Tue Sep 30 20:30:56 CEST 2008


Kenan Gillet wrote:
> Hi all,
> 
> First I would like to thank the all FFmpeg community for an awesome 
> application.
> 
> I have been using FFmpeg and the SOC QCELP decoder for some time and I
> wanted to contribute back. I have not program in C in a while and feel 
> kind of rusty,
> but I hope it will up to your standard.
> 
> Anyway, enough blabla and here is a patch for decoding QCELP based on
> the last commit in SOC (r2373).
> 
> It implements:
> - the 4 main rates: 1, 1/2, 1/4, and 1/8
> - the erasure of the frame for insufficient quality
> 
> It still misses:
> - blank rate, for lack of samples
> - post-filtering because right now it creates some cracks in some of the 
> samples.
> - final gain control because it only make sense if the post-filtering is 
> done.
> 
> It works with all the samples at:
> - http://samples.mplayerhq.hu/A-codecs/qclp/
> - http://samples.mplayerhq.hu/mov/qtaudio/surge-1-16-B-Qclp.mov
> - http://samples.mplayerhq.hu/k3g/vidoo_MP4_audio_Qcelp13k.k3g

[...]

> +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.

-Vitor




More information about the ffmpeg-devel mailing list