[FFmpeg-devel] [PATCH] Add a G.722 encoder
Michael Niedermayer
michaelni
Tue Sep 14 23:53:34 CEST 2010
On Sat, Sep 11, 2010 at 10:18:38PM +0300, Martin Storsj? wrote:
> On Fri, 10 Sep 2010, Martin Storsj? wrote:
>
> > On Fri, 10 Sep 2010, Martin Storsj? wrote:
> >
> > > On Fri, 10 Sep 2010, Michael Niedermayer wrote:
> > >
> > > > On Fri, Sep 10, 2010 at 04:24:00PM +0300, Martin Storsj? wrote:
> > > > > Hi,
> > > > >
> > > > > As in $subj, the first patch adds a straightforward encoder that produces
> > > > > bitexact output matching the reference test vectors. The second patch adds
> > > > > trellis support to the encoder, closely modelled after the code in
> > > > > libavcodec/adpcm.c.
> > > > >
> > > > > I'm only doing trellis on the lower sub-band, since the higher only is
> > > > > encoded with 2 bits. And if I'd want to do trellis for both of them at the
> > > > > same time, I'd have to run the QMF on the output from both subbands in
> > > > > order to get one decoded sample values, in order to have one difference
> > > > > instead of two to compare.
> > > >
> > > > why not comapare 2 ?
> > > >
> > > > diff= (a0-a1)^2 + C*(b0-b1)^2
> > >
> > > I guess that's doable, too, I'll try that.
> >
> > This actually turned out to work quite well, thanks! New version attached
> > that does trellis for both of them at the same time.
>
> Updated patches attached - I tuned the testing range for the lower subband
> a bit to achieve even better results.
>
> // Martin
> Changelog | 2 -
> doc/general.texi | 2 -
> libavcodec/Makefile | 1
> libavcodec/allcodecs.c | 2 -
> libavcodec/g722.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++--
> 5 files changed, 84 insertions(+), 5 deletions(-)
> bec600bc0d23482505cc14b4147d6408dc0b1829 0001-Add-a-G.722-encoder.patch
> From 2ba47a682860c43d342ee2053a3daae3498cdd20 Mon Sep 17 00:00:00 2001
> From: Martin Storsjo <martin at martin.st>
> Date: Fri, 6 Aug 2010 23:06:37 +0300
> Subject: [PATCH 1/2] Add a G.722 encoder
>
> ---
> Changelog | 2 +-
> doc/general.texi | 2 +-
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 2 +-
> libavcodec/g722.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-
> 5 files changed, 84 insertions(+), 5 deletions(-)
>
> diff --git a/Changelog b/Changelog
> index 70849ea..59dabbf 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -33,7 +33,7 @@ version <next>:
> - Apple HTTP Live Streaming demuxer
> - a64 codec
> - MMS-HTTP support
> -- G.722 ADPCM audio decoder
> +- G.722 ADPCM audio encoder/decoder
>
>
> version 0.6:
> diff --git a/doc/general.texi b/doc/general.texi
> index a692e04..42b9e92 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -535,7 +535,7 @@ following image formats are supported:
> @item ADPCM Electronic Arts R2 @tab @tab X
> @item ADPCM Electronic Arts R3 @tab @tab X
> @item ADPCM Electronic Arts XAS @tab @tab X
> - at item ADPCM G.722 @tab @tab X
> + at item ADPCM G.722 @tab X @tab X
> @item ADPCM G.726 @tab X @tab X
> @item ADPCM IMA AMV @tab @tab X
> @tab Used in AMV files
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index e0d7028..a4ee523 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -476,6 +476,7 @@ OBJS-$(CONFIG_ADPCM_EA_R2_DECODER) += adpcm.o
> OBJS-$(CONFIG_ADPCM_EA_R3_DECODER) += adpcm.o
> OBJS-$(CONFIG_ADPCM_EA_XAS_DECODER) += adpcm.o
> OBJS-$(CONFIG_ADPCM_G722_DECODER) += g722.o
> +OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o
> OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o
> OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o
> OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 31cfadd..ab2dcd3 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -317,7 +317,7 @@ void avcodec_register_all(void)
> REGISTER_DECODER (ADPCM_EA_R2, adpcm_ea_r2);
> REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3);
> REGISTER_DECODER (ADPCM_EA_XAS, adpcm_ea_xas);
> - REGISTER_DECODER (ADPCM_G722, adpcm_g722);
> + REGISTER_ENCDEC (ADPCM_G722, adpcm_g722);
> REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
> REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv);
> REGISTER_DECODER (ADPCM_IMA_DK3, adpcm_ima_dk3);
> diff --git a/libavcodec/g722.c b/libavcodec/g722.c
> index 8707d16..b893d22 100644
> --- a/libavcodec/g722.c
> +++ b/libavcodec/g722.c
> @@ -1,5 +1,5 @@
> /*
> - * G.722 ADPCM audio decoder
> + * G.722 ADPCM audio encoder/decoder
> *
> * Copyright (c) CMU 1993 Computer Science, Speech Group
> * Chengxiang Lu and Alex Hauptmann
> @@ -213,12 +213,13 @@ static av_cold int g722_init(AVCodecContext * avctx)
> c->band[1].scale_factor = 2;
> c->prev_samples_pos = 22;
>
> - if (avctx->lowres)
> + if (avctx->lowres && avctx->codec->decode)
> avctx->sample_rate /= 2;
>
> return 0;
> }
>
> +#if CONFIG_ADPCM_G722_DECODER
> static const int16_t low_inv_quant5[32] = {
> -35, -35, -2919, -2195, -1765, -1458, -1219, -1023,
> -858, -714, -587, -473, -370, -276, -190, -110,
> @@ -301,4 +302,81 @@ AVCodec adpcm_g722_decoder = {
> .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"),
> .max_lowres = 1,
> };
> +#endif
> +
> +#if CONFIG_ADPCM_G722_ENCODER
> +static const int16_t low_quant[29] = {
> + 35, 72, 110, 150, 190, 233, 276, 323,
> + 370, 422, 473, 530, 587, 650, 714, 786,
> + 858, 940, 1023, 1121, 1219, 1339, 1458, 1612,
> + 1765, 1980, 2195, 2557, 2919
> +};
> +
> +static inline void filter_samples(G722Context *c, const int16_t *samples,
> + int *xlow, int *xhigh)
> +{
> + int xout1, xout2;
> + c->prev_samples[c->prev_samples_pos++] = samples[0];
> + c->prev_samples[c->prev_samples_pos++] = samples[1];
> + apply_qmf(c->prev_samples + c->prev_samples_pos - 24, &xout1, &xout2);
> + *xlow = xout1 + xout2 >> 13;
> + *xhigh = xout1 - xout2 >> 13;
> + if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) {
> + memmove(c->prev_samples,
> + c->prev_samples + c->prev_samples_pos - 22,
> + 22 * sizeof(c->prev_samples[0]));
> + c->prev_samples_pos = 22;
> + }
> +}
> +
> +static inline int encode_high(G722Context *c, int xhigh)
> +{
> + int diff = av_clip_int16(xhigh - c->band[1].s_predictor);
> + int pred = 564 * c->band[1].scale_factor >> 10;
*141 >> 8
> + int index = diff >= 0 ? (diff < pred) + 2 : diff >= -pred;
> +
> + update_high_predictor(&c->band[1], c->band[1].scale_factor *
> + high_inv_quant[index] >> 10, index);
> + return index;
> +}
> +
> +static inline int encode_low(const struct G722Band* state, int xlow)
> +{
> + int diff = av_clip_int16(xlow - state->s_predictor);
> + int limit = diff >= 0 ? diff : -(diff + 1);
> + int i = 0;
> + while (i < 29 && limit >= (low_quant[i] * state->scale_factor) >> 10)
> + i++;
that doesnt look efficient
limit >= (low_quant[i] * state->scale_factor) >> 10)
can be changed to
C > low_quant[i]
also a LUT could be tried if this matters speed wise
trellis patch not reviewed yet
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Complexity theory is the science of finding the exact solution to an
approximation. Benchmarking OTOH is finding an approximation of the exact
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100914/917e56dc/attachment.pgp>
More information about the ffmpeg-devel
mailing list