[MPlayer-dev-eng] rtp support in mplayer
Chas Williams (CONTRACTOR)
chas at cmf.nrl.navy.mil
Mon Jun 9 19:38:26 CEST 2008
In message <20080516134500.8485095e.tempn at twmi.rr.com>,compn writes:
>libavcodec patches go to ffmpeg-devel list.
here is a patch to libavcodec for g722 audio support.
diff -u mplayer-1.0rc2.orig/libavcodec/Makefile mplayer-1.0rc2/libavcodec/Makefile
--- mplayer-1.0rc2.orig/libavcodec/Makefile 2007-10-07 15:49:37.000000000 -0400
+++ mplayer-1.0rc2/libavcodec/Makefile 2008-05-15 09:28:17.000000000 -0400
@@ -262,6 +262,7 @@
OBJS-$(CONFIG_ADPCM_CT_ENCODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_DECODER) += adpcm.o
OBJS-$(CONFIG_ADPCM_EA_ENCODER) += adpcm.o
+OBJS-$(CONFIG_ADPCM_G722_DECODER) += 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 -u mplayer-1.0rc2.orig/libavcodec/allcodecs.c mplayer-1.0rc2/libavcodec/allcodecs.c
--- mplayer-1.0rc2.orig/libavcodec/allcodecs.c 2007-10-07 15:49:37.000000000 -0400
+++ mplayer-1.0rc2/libavcodec/allcodecs.c 2008-05-15 09:30:17.000000000 -0400
@@ -247,6 +247,7 @@
REGISTER_ENCDEC (ADPCM_CT, adpcm_ct);
REGISTER_ENCDEC (ADPCM_EA, adpcm_ea);
REGISTER_ENCDEC (ADPCM_G726, adpcm_g726);
+ REGISTER_DECODER (ADPCM_G722, adpcm_g722);
REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_ENCDEC (ADPCM_IMA_DK3, adpcm_ima_dk3);
REGISTER_ENCDEC (ADPCM_IMA_DK4, adpcm_ima_dk4);
diff -u mplayer-1.0rc2.orig/libavcodec/avcodec.h mplayer-1.0rc2/libavcodec/avcodec.h
--- mplayer-1.0rc2.orig/libavcodec/avcodec.h 2007-10-07 15:49:37.000000000 -0400
+++ mplayer-1.0rc2/libavcodec/avcodec.h 2008-05-15 10:13:39.000000000 -0400
@@ -273,6 +273,8 @@
CODEC_ID_MPEG2TS= 0x20000, /* _FAKE_ codec to indicate a raw MPEG-2 TS
* stream (only used by libavformat) */
+
+ CODEC_ID_ADPCM_G722
};
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
diff -u mplayer-1.0rc2.orig/libavcodec/g722.c mplayer-1.0rc2/libavcodec/g722.c
--- mplayer-1.0rc2.orig/libavcodec/g722.c 2008-06-09 13:28:35.000000000 -0400
+++ mplayer-1.0rc2/libavcodec/g722.c 2008-06-09 13:31:01.000000000 -0400
@@ -0,0 +1,609 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722.h - The ITU G.722 codec.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * Despite my general liking of the GPL, I place my own contributions
+ * to this code in the public domain for the benefit of all mankind -
+ * even the slimy ones who might try to proprietize my work and use it
+ * to my detriment.
+ *
+ * Based on a single channel G.722 codec which is:
+ *
+ ***** Copyright (c) CMU 1993 *****
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id$
+ */
+
+
+/*! \file */
+
+#if !defined(_G722_H_)
+#define _G722_H_
+
+#include <inttypes.h>
+
+/*! \page g722_page G.722 encoding and decoding
+\section g722_page_sec_1 What does it do?
+The G.722 module is a bit exact implementation of the ITU G.722 specification for all three
+specified bit rates - 64000bps, 56000bps and 48000bps. It passes the ITU tests.
+
+To allow fast and flexible interworking with narrow band telephony, the encoder and decoder
+support an option for the linear audio to be an 8k samples/second stream. In this mode the
+codec is considerably faster, and still fully compatible with wideband terminals using G.722.
+
+\section g722_page_sec_2 How does it work?
+???.
+*/
+
+enum
+{
+ G722_SAMPLE_RATE_8000 = 0x0001,
+ G722_PACKED = 0x0002
+};
+
+#ifndef INT16_MAX
+#define INT16_MAX 32767
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32768)
+#endif
+
+typedef struct
+{
+ /*! TRUE if the operating in the special ITU test mode, with the band split filters
+ disabled. */
+ int itu_test_mode;
+ /*! TRUE if the G.722 data is packed */
+ int packed;
+ /*! TRUE if encode from 8k samples/second */
+ int eight_k;
+ /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+ int bits_per_sample;
+
+ /*! Signal history for the QMF */
+ int x[24];
+
+ struct
+ {
+ int s;
+ int sp;
+ int sz;
+ int r[3];
+ int a[3];
+ int ap[3];
+ int p[3];
+ int d[7];
+ int b[7];
+ int bp[7];
+ int sg[7];
+ int nb;
+ int det;
+ } band[2];
+
+ unsigned int in_buffer;
+ int in_bits;
+ unsigned int out_buffer;
+ int out_bits;
+} g722_encode_state_t;
+
+typedef struct
+{
+ /*! TRUE if the operating in the special ITU test mode, with the band split filters
+ disabled. */
+ int itu_test_mode;
+ /*! TRUE if the G.722 data is packed */
+ int packed;
+ /*! TRUE if decode to 8k samples/second */
+ int eight_k;
+ /*! 6 for 48000kbps, 7 for 56000kbps, or 8 for 64000kbps. */
+ int bits_per_sample;
+
+ /*! Signal history for the QMF */
+ int x[24];
+
+ struct
+ {
+ int s;
+ int sp;
+ int sz;
+ int r[3];
+ int a[3];
+ int ap[3];
+ int p[3];
+ int d[7];
+ int b[7];
+ int bp[7];
+ int sg[7];
+ int nb;
+ int det;
+ } band[2];
+
+ unsigned int in_buffer;
+ int in_bits;
+ unsigned int out_buffer;
+ int out_bits;
+} g722_decode_state_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options);
+int g722_decode_release(g722_decode_state_t *s);
+int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_decode.c - The ITU G.722 codec, decode part.
+ *
+ * Written by Steve Underwood <steveu at coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * Despite my general liking of the GPL, I place my own contributions
+ * to this code in the public domain for the benefit of all mankind -
+ * even the slimy ones who might try to proprietize my work and use it
+ * to my detriment.
+ *
+ * Based in part on a single channel G.722 codec which is:
+ *
+ * Copyright (c) CMU 1993
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ *
+ * $Id$
+ */
+
+/*! \file */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <memory.h>
+#include <stdlib.h>
+
+#include <limits.h>
+#include "avcodec.h"
+#include "bitstream.h"
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+#if !defined(TRUE)
+#define TRUE (!FALSE)
+#endif
+
+static int16_t saturate(int32_t amp)
+{
+ int16_t amp16;
+
+ /* Hopefully this is optimised for the common case - not clipping */
+ amp16 = (int16_t) amp;
+ if (amp == amp16)
+ return amp16;
+ if (amp > INT16_MAX)
+ return INT16_MAX;
+ return INT16_MIN;
+}
+/*- End of function --------------------------------------------------------*/
+
+static void block4(g722_decode_state_t *s, int band, int d)
+{
+ int wd1;
+ int wd2;
+ int wd3;
+ int i;
+
+ /* Block 4, RECONS */
+ s->band[band].d[0] = d;
+ s->band[band].r[0] = saturate(s->band[band].s + d);
+
+ /* Block 4, PARREC */
+ s->band[band].p[0] = saturate(s->band[band].sz + d);
+
+ /* Block 4, UPPOL2 */
+ for (i = 0; i < 3; i++)
+ s->band[band].sg[i] = s->band[band].p[i] >> 15;
+ wd1 = saturate(s->band[band].a[1] << 2);
+
+ wd2 = (s->band[band].sg[0] == s->band[band].sg[1]) ? -wd1 : wd1;
+ if (wd2 > 32767)
+ wd2 = 32767;
+ wd3 = (s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128;
+ wd3 += (wd2 >> 7);
+ wd3 += (s->band[band].a[2]*32512) >> 15;
+ if (wd3 > 12288)
+ wd3 = 12288;
+ else if (wd3 < -12288)
+ wd3 = -12288;
+ s->band[band].ap[2] = wd3;
+
+ /* Block 4, UPPOL1 */
+ s->band[band].sg[0] = s->band[band].p[0] >> 15;
+ s->band[band].sg[1] = s->band[band].p[1] >> 15;
+ wd1 = (s->band[band].sg[0] == s->band[band].sg[1]) ? 192 : -192;
+ wd2 = (s->band[band].a[1]*32640) >> 15;
+
+ s->band[band].ap[1] = saturate(wd1 + wd2);
+ wd3 = saturate(15360 - s->band[band].ap[2]);
+ if (s->band[band].ap[1] > wd3)
+ s->band[band].ap[1] = wd3;
+ else if (s->band[band].ap[1] < -wd3)
+ s->band[band].ap[1] = -wd3;
+
+ /* Block 4, UPZERO */
+ wd1 = (d == 0) ? 0 : 128;
+ s->band[band].sg[0] = d >> 15;
+ for (i = 1; i < 7; i++)
+ {
+ s->band[band].sg[i] = s->band[band].d[i] >> 15;
+ wd2 = (s->band[band].sg[i] == s->band[band].sg[0]) ? wd1 : -wd1;
+ wd3 = (s->band[band].b[i]*32640) >> 15;
+ s->band[band].bp[i] = saturate(wd2 + wd3);
+ }
+
+ /* Block 4, DELAYA */
+ for (i = 6; i > 0; i--)
+ {
+ s->band[band].d[i] = s->band[band].d[i - 1];
+ s->band[band].b[i] = s->band[band].bp[i];
+ }
+
+ for (i = 2; i > 0; i--)
+ {
+ s->band[band].r[i] = s->band[band].r[i - 1];
+ s->band[band].p[i] = s->band[band].p[i - 1];
+ s->band[band].a[i] = s->band[band].ap[i];
+ }
+
+ /* Block 4, FILTEP */
+ wd1 = saturate(s->band[band].r[1] + s->band[band].r[1]);
+ wd1 = (s->band[band].a[1]*wd1) >> 15;
+ wd2 = saturate(s->band[band].r[2] + s->band[band].r[2]);
+ wd2 = (s->band[band].a[2]*wd2) >> 15;
+ s->band[band].sp = saturate(wd1 + wd2);
+
+ /* Block 4, FILTEZ */
+ s->band[band].sz = 0;
+ for (i = 6; i > 0; i--)
+ {
+ wd1 = saturate(s->band[band].d[i] + s->band[band].d[i]);
+ s->band[band].sz += (s->band[band].b[i]*wd1) >> 15;
+ }
+ s->band[band].sz = saturate(s->band[band].sz);
+
+ /* Block 4, PREDIC */
+ s->band[band].s = saturate(s->band[band].sp + s->band[band].sz);
+}
+/*- End of function --------------------------------------------------------*/
+
+g722_decode_state_t *g722_decode_init(g722_decode_state_t *s, int rate, int options)
+{
+ if (s == NULL)
+ {
+ if ((s = (g722_decode_state_t *) av_malloc(sizeof(*s))) == NULL)
+ return NULL;
+ }
+ memset(s, 0, sizeof(*s));
+ if (rate == 48000)
+ s->bits_per_sample = 6;
+ else if (rate == 56000)
+ s->bits_per_sample = 7;
+ else
+ s->bits_per_sample = 8;
+ if ((options & G722_SAMPLE_RATE_8000))
+ s->eight_k = TRUE;
+ if ((options & G722_PACKED) && s->bits_per_sample != 8)
+ s->packed = TRUE;
+ else
+ s->packed = FALSE;
+ s->band[0].det = 32;
+ s->band[1].det = 8;
+ return s;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_decode_release(g722_decode_state_t *s)
+{
+ av_free(s);
+ return 0;
+}
+/*- End of function --------------------------------------------------------*/
+
+int g722_decode(g722_decode_state_t *s, int16_t amp[], const uint8_t g722_data[], int len)
+{
+ static const int wl[8] = {-60, -30, 58, 172, 334, 538, 1198, 3042 };
+ static const int rl42[16] = {0, 7, 6, 5, 4, 3, 2, 1, 7, 6, 5, 4, 3, 2, 1, 0 };
+ static const int ilb[32] =
+ {
+ 2048, 2093, 2139, 2186, 2233, 2282, 2332,
+ 2383, 2435, 2489, 2543, 2599, 2656, 2714,
+ 2774, 2834, 2896, 2960, 3025, 3091, 3158,
+ 3228, 3298, 3371, 3444, 3520, 3597, 3676,
+ 3756, 3838, 3922, 4008
+ };
+ static const int wh[3] = {0, -214, 798};
+ static const int rh2[4] = {2, 1, 2, 1};
+ static const int qm2[4] = {-7408, -1616, 7408, 1616};
+ static const int qm4[16] =
+ {
+ 0, -20456, -12896, -8968,
+ -6288, -4240, -2584, -1200,
+ 20456, 12896, 8968, 6288,
+ 4240, 2584, 1200, 0
+ };
+ static const int qm5[32] =
+ {
+ -280, -280, -23352, -17560,
+ -14120, -11664, -9752, -8184,
+ -6864, -5712, -4696, -3784,
+ -2960, -2208, -1520, -880,
+ 23352, 17560, 14120, 11664,
+ 9752, 8184, 6864, 5712,
+ 4696, 3784, 2960, 2208,
+ 1520, 880, 280, -280
+ };
+ static const int qm6[64] =
+ {
+ -136, -136, -136, -136,
+ -24808, -21904, -19008, -16704,
+ -14984, -13512, -12280, -11192,
+ -10232, -9360, -8576, -7856,
+ -7192, -6576, -6000, -5456,
+ -4944, -4464, -4008, -3576,
+ -3168, -2776, -2400, -2032,
+ -1688, -1360, -1040, -728,
+ 24808, 21904, 19008, 16704,
+ 14984, 13512, 12280, 11192,
+ 10232, 9360, 8576, 7856,
+ 7192, 6576, 6000, 5456,
+ 4944, 4464, 4008, 3576,
+ 3168, 2776, 2400, 2032,
+ 1688, 1360, 1040, 728,
+ 432, 136, -432, -136
+ };
+ static const int qmf_coeffs[12] =
+ {
+ 3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
+ };
+
+ int dlowt;
+ int rlow;
+ int ihigh;
+ int dhigh;
+ int rhigh;
+ int xout1;
+ int xout2;
+ int wd1;
+ int wd2;
+ int wd3;
+ int code;
+ int outlen;
+ int i;
+ int j;
+
+ outlen = 0;
+ rhigh = 0;
+ for (j = 0; j < len; )
+ {
+ if (s->packed)
+ {
+ /* Unpack the code bits */
+ if (s->in_bits < s->bits_per_sample)
+ {
+ s->in_buffer |= (g722_data[j++] << s->in_bits);
+ s->in_bits += 8;
+ }
+ code = s->in_buffer & ((1 << s->bits_per_sample) - 1);
+ s->in_buffer >>= s->bits_per_sample;
+ s->in_bits -= s->bits_per_sample;
+ }
+ else
+ {
+ code = g722_data[j++];
+ }
+
+ switch (s->bits_per_sample)
+ {
+ default:
+ case 8:
+ wd1 = code & 0x3F;
+ ihigh = (code >> 6) & 0x03;
+ wd2 = qm6[wd1];
+ wd1 >>= 2;
+ break;
+ case 7:
+ wd1 = code & 0x1F;
+ ihigh = (code >> 5) & 0x03;
+ wd2 = qm5[wd1];
+ wd1 >>= 1;
+ break;
+ case 6:
+ wd1 = code & 0x0F;
+ ihigh = (code >> 4) & 0x03;
+ wd2 = qm4[wd1];
+ break;
+ }
+ /* Block 5L, LOW BAND INVQBL */
+ wd2 = (s->band[0].det*wd2) >> 15;
+ /* Block 5L, RECONS */
+ rlow = s->band[0].s + wd2;
+ /* Block 6L, LIMIT */
+ if (rlow > 16383)
+ rlow = 16383;
+ else if (rlow < -16384)
+ rlow = -16384;
+
+ /* Block 2L, INVQAL */
+ wd2 = qm4[wd1];
+ dlowt = (s->band[0].det*wd2) >> 15;
+
+ /* Block 3L, LOGSCL */
+ wd2 = rl42[wd1];
+ wd1 = (s->band[0].nb*127) >> 7;
+ wd1 += wl[wd2];
+ if (wd1 < 0)
+ wd1 = 0;
+ else if (wd1 > 18432)
+ wd1 = 18432;
+ s->band[0].nb = wd1;
+
+ /* Block 3L, SCALEL */
+ wd1 = (s->band[0].nb >> 6) & 31;
+ wd2 = 8 - (s->band[0].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[0].det = wd3 << 2;
+
+ block4(s, 0, dlowt);
+
+ if (!s->eight_k)
+ {
+ /* Block 2H, INVQAH */
+ wd2 = qm2[ihigh];
+ dhigh = (s->band[1].det*wd2) >> 15;
+ /* Block 5H, RECONS */
+ rhigh = dhigh + s->band[1].s;
+ /* Block 6H, LIMIT */
+ if (rhigh > 16383)
+ rhigh = 16383;
+ else if (rhigh < -16384)
+ rhigh = -16384;
+
+ /* Block 2H, INVQAH */
+ wd2 = rh2[ihigh];
+ wd1 = (s->band[1].nb*127) >> 7;
+ wd1 += wh[wd2];
+ if (wd1 < 0)
+ wd1 = 0;
+ else if (wd1 > 22528)
+ wd1 = 22528;
+ s->band[1].nb = wd1;
+
+ /* Block 3H, SCALEH */
+ wd1 = (s->band[1].nb >> 6) & 31;
+ wd2 = 10 - (s->band[1].nb >> 11);
+ wd3 = (wd2 < 0) ? (ilb[wd1] << -wd2) : (ilb[wd1] >> wd2);
+ s->band[1].det = wd3 << 2;
+
+ block4(s, 1, dhigh);
+ }
+
+ if (s->itu_test_mode)
+ {
+ amp[outlen++] = (int16_t) (rlow << 1);
+ amp[outlen++] = (int16_t) (rhigh << 1);
+ }
+ else
+ {
+ if (s->eight_k)
+ {
+ amp[outlen++] = (int16_t) rlow;
+ }
+ else
+ {
+ /* Apply the receive QMF */
+ for (i = 0; i < 22; i++)
+ s->x[i] = s->x[i + 2];
+ s->x[22] = rlow + rhigh;
+ s->x[23] = rlow - rhigh;
+
+ xout1 = 0;
+ xout2 = 0;
+ for (i = 0; i < 12; i++)
+ {
+ xout2 += s->x[2*i]*qmf_coeffs[i];
+ xout1 += s->x[2*i + 1]*qmf_coeffs[11 - i];
+ }
+ amp[outlen++] = (int16_t) (xout1 >> 12);
+ amp[outlen++] = (int16_t) (xout2 >> 12);
+ }
+ }
+ }
+ return outlen;
+}
+/*- End of function --------------------------------------------------------*/
+
+typedef struct AVG722Context {
+ g722_decode_state_t *s;
+} AVG722Context;
+
+static int g722_init(AVCodecContext * avctx)
+{
+ AVG722Context *c = (AVG722Context *) avctx->priv_data;
+ int options = 0;
+
+ if (avctx->channels != 1 ||
+ (avctx->bit_rate != 48000 && avctx->bit_rate != 56000 &&
+ avctx->bit_rate != 64000)) {
+ av_log(avctx, AV_LOG_ERROR, "G722: unsupported audio format\n");
+ return -1;
+ }
+
+ if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000
+ && avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL) {
+ av_log(avctx, AV_LOG_ERROR, "G722: unsupported audio format\n");
+ return -1;
+ }
+
+ if (avctx->sample_rate == 8000)
+ options |= G722_SAMPLE_RATE_8000;
+ /* options |= G722_PACKED? */
+
+ c->s = g722_decode_init(NULL, avctx->bit_rate, options);
+
+ avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame)
+ return AVERROR(ENOMEM);
+ avctx->coded_frame->key_frame = 1;
+
+ return 0;
+}
+
+static int g722_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+ AVG722Context *c = avctx->priv_data;
+ int16_t *amp = data;
+
+ *data_size = g722_decode(c->s, amp, buf, buf_size) * sizeof(short);
+ return buf_size;
+}
+
+static int g722_close(AVCodecContext *avctx)
+{
+ AVG722Context* c = (AVG722Context *) avctx->priv_data;
+
+ g722_decode_release(c->s);
+ av_freep(&avctx->coded_frame);
+ return 0;
+}
+
+AVCodec adpcm_g722_decoder = {
+ "g722",
+ CODEC_TYPE_AUDIO,
+ CODEC_ID_ADPCM_G722,
+ sizeof(AVG722Context),
+ g722_init,
+ NULL,
+ g722_close,
+ g722_decode_frame,
+};
+
+
--- mplayer-1.0rc2.orig/etc/codecs.conf 2007-10-07 15:49:33.000000000 -0400
+++ mplayer-1.0rc2/etc/codecs.conf 2008-05-16 11:16:42.000000000 -0400
@@ -3141,6 +3141,13 @@
driver ffmpeg
dll "g726"
+audiocodec g722
+ info "G.722 Audio"
+ status working
+ format 0x41
+ driver ffmpeg
+ dll "g722"
+
audiocodec g726
info "Sharp G.726 Audio"
status untested
More information about the MPlayer-dev-eng
mailing list