[FFmpeg-devel] [PATCH 4/5] Add the G723.1 demuxer and decoder
Vitor Sessak
vitor1001 at gmail.com
Sat Mar 19 15:02:32 CET 2011
On 03/17/2011 11:56 PM, banan at ludd.ltu.se wrote:
> From: Mohamed Naufal Basheer<naufal11 at gmail.com>
> --- /dev/null
> +++ b/libavcodec/g723_1.c
> @@ -0,0 +1,1081 @@
> +/*
> + * G.723.1 compatible decoder
> + * Copyright (c) 2006 Benjamin Larsson
> + * Copyright (c) 2010 Mohamed Naufal Basheer
> + *
> + * 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
> + */
First question: is it bitexact to the reference decoder?
> +/**
> + * @file
> + * G.723.1 compatible decoder
> + */
> +
> +#include "avcodec.h"
> +#define ALT_BITSTREAM_READER_LE
> +#include "get_bits.h"
> +#include "acelp_vectors.h"
> +#include "celp_filters.h"
> +#include "celp_math.h"
> +#include "lsp.h"
> +#include "libavutil/lzo.h"
> +#include "g723_1_data.h"
> +
> +typedef struct g723_1_context {
> + G723_1_Subframe subframe[4];
> + FrameType cur_frame_type;
> + FrameType past_frame_type;
> + Rate cur_rate;
> + uint8_t lsp_index[LSP_BANDS];
> + int pitch_lag[2];
> + int erased_frames;
> +
> + int16_t prev_lsp[LPC_ORDER];
> + int16_t prev_excitation[PITCH_MAX];
> + int16_t excitation[PITCH_MAX + FRAME_LEN];
> + int16_t synth_mem[LPC_ORDER];
> + int16_t fir_mem[LPC_ORDER];
> + int iir_mem[LPC_ORDER];
> +
> + int random_seed;
> + int interp_index;
> + int interp_gain;
> + int sid_gain;
> + int cur_gain;
> + int reflection_coef;
> + int pf_gain; ///< formant postfilter
> + ///< gain scaling unit memory
> +} G723_1_Context;
> +
> +static av_cold int g723_1_decode_init(AVCodecContext *avctx)
> +{
> + G723_1_Context *p = avctx->priv_data;
> +
> + avctx->sample_fmt = SAMPLE_FMT_S16;
> + p->pf_gain = 1<< 12;
> + memcpy(p->prev_lsp, dc_lsp, LPC_ORDER * sizeof(int16_t));
> +
> + return 0;
> +}
> +
> +/**
> + * Unpack the frame into parameters.
> + *
> + * @param p the context
> + * @param buf pointer to the input buffer
> + * @param buf_size size of the input buffer
> + */
> +static int unpack_bitstream(G723_1_Context *p, const uint8_t *buf,
> + int buf_size)
> +{
> + GetBitContext gb;
> + int ad_cb_len;
> + int temp, info_bits, i;
> +
> + init_get_bits(&gb, buf, buf_size * 8);
> +
> + /* Extract frame type and rate info */
> + info_bits = get_bits(&gb, 2);
> +
> + if (info_bits == 3) {
> + p->cur_frame_type = UntransmittedFrame;
> + return 0;
> + }
> +
> + /* Extract 24 bit lsp indices, 8 bit for each band */
> + p->lsp_index[2] = get_bits(&gb, 8);
> + p->lsp_index[1] = get_bits(&gb, 8);
> + p->lsp_index[0] = get_bits(&gb, 8);
> +
> + if (info_bits == 2) {
> + p->cur_frame_type = SIDFrame;
> + p->subframe[0].amp_index = get_bits(&gb, 6);
> + return 0;
> + }
> +
> + /* Extract the info common to both rates */
> + p->cur_rate = info_bits ? Rate5k3 : Rate6k3;
> + p->cur_frame_type = ActiveFrame;
> +
> + p->pitch_lag[0] = get_bits(&gb, 7);
> + if (p->pitch_lag[0]> 123) /* test if forbidden code */
> + return -1;
> + p->pitch_lag[0] += PITCH_MIN;
> + p->subframe[1].ad_cb_lag = get_bits(&gb, 2);
> +
> + p->pitch_lag[1] = get_bits(&gb, 7);
> + if (p->pitch_lag[1]> 123)
> + return -1;
> + p->pitch_lag[1] += PITCH_MIN;
> + p->subframe[3].ad_cb_lag = get_bits(&gb, 2);
> + p->subframe[0].ad_cb_lag = 1;
> + p->subframe[2].ad_cb_lag = 1;
> +
> + for (i = 0; i< SUBFRAMES; i++) {
> + /* Extract combined gain */
> + temp = get_bits(&gb, 12);
> + ad_cb_len = 170;
> + p->subframe[i].dirac_train = 0;
> + if (p->cur_rate == Rate6k3&& p->pitch_lag[i>> 1]< SUBFRAME_LEN - 2) {
> + p->subframe[i].dirac_train = temp>> 11;
> + temp&= 0x7ff;
> + ad_cb_len = 85;
> + }
> + p->subframe[i].ad_cb_gain = FASTDIV(temp, GAIN_LEVELS);
> + if (p->subframe[i].ad_cb_gain< ad_cb_len) {
> + p->subframe[i].amp_index = temp - p->subframe[i].ad_cb_gain *
> + GAIN_LEVELS;
> + } else {
> + return -1;
> + }
> + }
> +
> + p->subframe[0].grid_index = get_bits(&gb, 1);
> + p->subframe[1].grid_index = get_bits(&gb, 1);
> + p->subframe[2].grid_index = get_bits(&gb, 1);
> + p->subframe[3].grid_index = get_bits(&gb, 1);
get_bits1()
> +
> + if (p->cur_rate == Rate6k3) {
> + skip_bits(&gb, 1); /* skip reserved bit */
skip_bits1()
> + /* Compute pulse_pos index using the 13-bit combined position index */
> + temp = get_bits(&gb, 13);
> + p->subframe[0].pulse_pos = temp / 810;
> +
> + temp -= p->subframe[0].pulse_pos * 810;
> + p->subframe[1].pulse_pos = FASTDIV(temp, 90);
> +
> + temp -= p->subframe[1].pulse_pos * 90;
> + p->subframe[2].pulse_pos = FASTDIV(temp, 9);
> + p->subframe[3].pulse_pos = temp - p->subframe[2].pulse_pos * 9;
> +
> + p->subframe[0].pulse_pos = (p->subframe[0].pulse_pos<< 16) +
> + get_bits(&gb, 16);
> + p->subframe[1].pulse_pos = (p->subframe[1].pulse_pos<< 14) +
> + get_bits(&gb, 14);
> + p->subframe[2].pulse_pos = (p->subframe[2].pulse_pos<< 16) +
> + get_bits(&gb, 16);
> + p->subframe[3].pulse_pos = (p->subframe[3].pulse_pos<< 14) +
> + get_bits(&gb, 14);
> +
> + p->subframe[0].pulse_sign = get_bits(&gb, 6);
> + p->subframe[1].pulse_sign = get_bits(&gb, 5);
> + p->subframe[2].pulse_sign = get_bits(&gb, 6);
> + p->subframe[3].pulse_sign = get_bits(&gb, 5);
> + } else { /* Rate5k3 */
> + p->subframe[0].pulse_pos = get_bits(&gb, 12);
> + p->subframe[1].pulse_pos = get_bits(&gb, 12);
> + p->subframe[2].pulse_pos = get_bits(&gb, 12);
> + p->subframe[3].pulse_pos = get_bits(&gb, 12);
> +
> + p->subframe[0].pulse_sign = get_bits(&gb, 4);
> + p->subframe[1].pulse_sign = get_bits(&gb, 4);
> + p->subframe[2].pulse_sign = get_bits(&gb, 4);
> + p->subframe[3].pulse_sign = get_bits(&gb, 4);
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * Bitexact implementation of sqrt(val/2).
> + */
> +static int16_t square_root(int val)
> +{
> + int16_t res = 0;
> + int16_t exp = 0x4000;
> + int i;
> +
> + for (i = 0; i< 14; i ++) {
> + int res_exp = res + exp;
> + if (val>= res_exp * res_exp<< 1)
> + res += exp;
> + exp>>= 1;
> + }
> + return res;
> +}
Isn't this the same as ((ff_sqrt(i << 1) >> 1) & (~1)))?
> +/**
> + * Calculate the number of left-shifts required for normalizing the input.
> + *
> + * @param num input number
> + * @param width width of the input, 16 bits(0) / 32 bits(1)
> + */
> +static int normalize_bits(int num, int width)
> +{
> + int i = 0;
> + int bits = (width) ? 31 : 15;
> + int limit = 1<< (bits - 1);
> +
> + if (num) {
> + if (num == -1)
> + return bits;
> + if (num< 0)
> + num = ~num;
> + for (i = 0; num< limit; i++)
> + num<<= 1;
> + }
> + return i;
> +}
I'm pretty sure the loop can be replaced by an av_log2()...
> +/**
> + * Scale vector contents based on the largest of their absolutes.
> + */
* @return ....
> +static int scale_vector(int16_t *vector, int length)
> +{
> + int bits, scale, max = 0;
> + int i;
> +
> + const int16_t shift_table[16] = {
> + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
> + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x7fff
> + };
> +
> + for (i = 0; i< length; i++)
> + max = FFMAX(max, FFABS(vector[i]));
> +
> + bits = normalize_bits(max, 0);
> + scale = shift_table[bits];
> +
> + for (i = 0; i< length; i++)
> + vector[i] = (int16_t)(av_clipl_int32(vector[i] * scale<< 1)>> 4);
What is the point of clipping a 32-bit value to 32-bits?
I'll do a more in-depth review soon...
-Vitor
More information about the ffmpeg-devel
mailing list