while trying to play from rtp/mpeg-es streams i found i needed the following patch: --- stream/rtp.c.000 2008-05-13 17:37:23.000000000 -0400 +++ stream/rtp.c 2008-05-13 18:02:02.000000000 -0400 @@ -246,6 +246,9 @@ headerSize = 12 + 4*rh->b.cc; /* in bytes */ + if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData = lengthPacket - headerSize; *data = (char*) buf + headerSize; to skip over the 4-byte mpeg header present in the file. however, after looking at mplayer a bit harder, i see that there are two rtp decoders/demuxers. the one supplied in libavformat (apparently derived from ffmpeg) seems like it has more smarts. which one should i be using?
On Thursday 15 May 2008 15:21:38 chas williams - CONTRACTOR wrote:
while trying to play from rtp/mpeg-es streams i found i needed the following patch:
--- stream/rtp.c.000 2008-05-13 17:37:23.000000000 -0400 +++ stream/rtp.c 2008-05-13 18:02:02.000000000 -0400 @@ -246,6 +246,9 @@
headerSize = 12 + 4*rh->b.cc; /* in bytes */
+ if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData = lengthPacket - headerSize; *data = (char*) buf + headerSize;
to skip over the 4-byte mpeg header present in the file.
eh??? do you want to skip the mpeg-ts 4 bytes header or I misunderstood what you mean?
however, after looking at mplayer a bit harder, i see that there are two rtp decoders/demuxers. the one supplied in libavformat (apparently derived from ffmpeg) seems like it has more smarts. which one should i be using? _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
In message <200805151536.36068.Nicola.Sabbi@poste.it>,Nico Sabbi writes:
On Thursday 15 May 2008 15:21:38 chas williams - CONTRACTOR wrote:
+ if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */
eh??? do you want to skip the mpeg-ts 4 bytes header or I misunderstood what you mean?
yes. rfc2250 makes you prepend a 'MPEG Video-specific header' on the actual mpeg data which isnt decoded by the mpeg layers. there is also an mpeg2 specific header which should probably be skipped. also, i need g722 support. i ported over a g722 decoder, but i cant seem to get the libmpdemux to use it. i put the decoder in libavcodec so i guess i need to write a g722 specific (or perhaps just an adpcm) demuxer?
On Thu, 15 May 2008 10:37:16 -0400, "Chas Williams (CONTRACTOR)" <chas@cmf.nrl.navy.mil> wrote:
In message <200805151536.36068.Nicola.Sabbi@poste.it>,Nico Sabbi writes:
On Thursday 15 May 2008 15:21:38 chas williams - CONTRACTOR wrote:
+ if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */
eh??? do you want to skip the mpeg-ts 4 bytes header or I misunderstood what you mean?
yes. rfc2250 makes you prepend a 'MPEG Video-specific header' on the actual mpeg data which isnt decoded by the mpeg layers. there is also an mpeg2 specific header which should probably be skipped.
also, i need g722 support. i ported over a g722 decoder, but i cant seem to get the libmpdemux to use it. i put the decoder in libavcodec so i guess i need to write a g722 specific (or perhaps just an adpcm) demuxer?
i assume you've already added the g722 decoder to codecs.conf ? the only samples of g722 i can find are all playable with mplayer already. do you have a sample file or stream we can take a look at ? -compn
In message <20080515124848.67df9025.tempn@twmi.rr.com>,compn writes:
i assume you've already added the g722 decoder to codecs.conf ?
nope.
the only samples of g722 i can find are all playable with mplayer already. do you have a sample file or stream we can take a look at ?
i cant since its an rtp stream. can you send me an example of a g722 file so that i can see what decoder mplayer is using so i can get the incoming rtp stream to demux to that decoder?
On Thu, 15 May 2008 13:13:38 -0400, "Chas Williams (CONTRACTOR)" <chas@cmf.nrl.navy.mil> wrote:
In message <20080515124848.67df9025.tempn@twmi.rr.com>,compn writes:
i assume you've already added the g722 decoder to codecs.conf ?
nope.
the only samples of g722 i can find are all playable with mplayer already. do you have a sample file or stream we can take a look at ?
i cant since its an rtp stream. can you send me an example of a g722 file so that i can see what decoder mplayer is using so i can get the incoming rtp stream to demux to that decoder?
erm, ignore above, i only found g722 > wav samples apparently here are some g722 samples: http://samples.mplayerhq.hu/A-codecs/g722/ http://downloads.digium.com/pub/telephony/sounds/asterisk-core-sounds-es-g72... after adding your g722 codec to codecs.conf, assuming you got it properly built into libavcodec/mplayer... try without a demuxer, mplayer -demuxer rawaudio -rawaudio format=0xxxx somefile.722 where the format 0xxxx is what you write in the codecs.conf entry. is there anyway you could make the stream public ? did you try it in vlc ? -compn
In message <20080515154816.e84d8b40.tempn@twmi.rr.com>,compn writes:
here are some g722 samples: http://samples.mplayerhq.hu/A-codecs/g722/
i cant seem to play this one. do you have any hints about the rate or sampling?
http://downloads.digium.com/pub/telephony/sounds/asterisk-core-sounds-es-g72... current.tar.gz
these play just fine. however, they appear to be in espanol (that or the decoder makes english sound like spanish). they are single channel, 64khz sampled, 8khz rate.
is there anyway you could make the stream public ? did you try it in vlc ?
vlc plays the video for sure. however, i wanted to use mplayer. no idea if vlc supports g.722. i can now play my g.722 rtp stream with: mplayer -demuxer rawaudio -rawaudio channels=1:bitrate=64000:rate=16000:format=0x41 rtp://239.192.1.52:56522\?multicast=1 however, rtp contains enough information to tell mplayer what decoder to use.
On Fri, 16 May 2008 12:54:33 -0400, "Chas Williams (CONTRACTOR)" <chas@cmf.nrl.navy.mil> wrote:
In message <20080515154816.e84d8b40.tempn@twmi.rr.com>,compn writes:
here are some g722 samples: http://samples.mplayerhq.hu/A-codecs/g722/
i cant seem to play this one. do you have any hints about the rate or sampling?
i dont have any info on it. it looks like rxt owns that file, maybe he remembers.
http://downloads.digium.com/pub/telephony/sounds/asterisk-core-sounds-es-g72... current.tar.gz
these play just fine. however, they appear to be in espanol (that or the decoder makes english sound like spanish). they are single channel, 64khz sampled, 8khz rate.
is there anyway you could make the stream public ? did you try it in vlc ?
vlc plays the video for sure. however, i wanted to use mplayer. no idea if vlc supports g.722. i can now play my g.722 rtp stream with:
mplayer -demuxer rawaudio -rawaudio channels=1:bitrate=64000:rate=16000:format=0x41 rtp://239.192.1.52:56522\?multicast=1
however, rtp contains enough information to tell mplayer what decoder to use.
ah good, is it all working properly now ? feel free to submit whatever changes you made :) libavcodec patches go to ffmpeg-devel list. -compn
In message <20080516134500.8485095e.tempn@twmi.rr.com>,compn writes:
ah good, is it all working properly now ?
the following patch adds a skip for the mpeg1 video specific header in an rtp stream. it also adds support for hinting the file format of the stream to the upper layer by capturing a single packet during the open and giving it a quick parse. diff -u mplayer-1.0rc2.orig/stream/rtp.c mplayer-1.0rc2/stream/rtp.c --- mplayer-1.0rc2.orig/stream/rtp.c 2007-10-07 15:49:26.000000000 -0400 +++ mplayer-1.0rc2/stream/rtp.c 2008-05-14 22:54:18.000000000 -0400 @@ -39,22 +39,6 @@ #define MAXRTPPACKETSIN 32 // The number of max packets being reordered -struct rtpbits { - unsigned int v:2; /* version: 2 */ - unsigned int p:1; /* is there padding appended: 0 */ - unsigned int x:1; /* number of extension headers: 0 */ - unsigned int cc:4; /* number of CSRC identifiers: 0 */ - unsigned int m:1; /* marker: 0 */ - unsigned int pt:7; /* payload type: 33 for MPEG2 TS - RFC 1890 */ - unsigned int sequence:16; /* sequence number: random */ -}; - -struct rtpheader { /* in network byte order */ - struct rtpbits b; - int timestamp; /* start: random */ - int ssrc; /* random */ -}; - struct rtpbuffer { unsigned char data[MAXRTPPACKETSIN][STREAM_BUFFER_SIZE]; @@ -64,7 +48,7 @@ }; static struct rtpbuffer rtpbuf; -static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData); +int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData); // RTP Reordering functions // Algorithm works as follows: @@ -216,12 +200,13 @@ return(length); } -static int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { +int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData) { static char buf[1600]; unsigned int intP; char* charP = (char*) &intP; int headerSize; int lengthPacket; + lengthPacket=recv(fd,buf,1590,0); if (lengthPacket<0) mp_msg(MSGT_NETWORK,MSGL_ERR,"rtp: socket read error\n"); @@ -246,6 +231,9 @@ headerSize = 12 + 4*rh->b.cc; /* in bytes */ + if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData = lengthPacket - headerSize; *data = (char*) buf + headerSize; diff -u mplayer-1.0rc2.orig/stream/rtp.h mplayer-1.0rc2/stream/rtp.h --- mplayer-1.0rc2.orig/stream/rtp.h 2007-10-07 15:49:26.000000000 -0400 +++ mplayer-1.0rc2/stream/rtp.h 2008-06-09 13:20:10.000000000 -0400 @@ -9,5 +9,22 @@ #define RTP_H int read_rtp_from_server(int fd, char *buffer, int length); +int getrtp2(int fd, struct rtpheader *rh, char** data, int* lengthData); + +struct rtpbits { + unsigned int v:2; /* version: 2 */ + unsigned int p:1; /* is there padding appended: 0 */ + unsigned int x:1; /* number of extension headers: 0 */ + unsigned int cc:4; /* number of CSRC identifiers: 0 */ + unsigned int m:1; /* marker: 0 */ + unsigned int pt:7; /* payload type: 33 for MPEG2 TS - RFC 1890 */ + unsigned int sequence:16; /* sequence number: random */ +}; + +struct rtpheader { /* in network byte order */ + struct rtpbits b; + int timestamp; /* start: random */ + int ssrc; /* random */ +}; #endif diff -u mplayer-1.0rc2.orig/stream/stream_rtp.c mplayer-1.0rc2/stream/stream_rtp.c --- mplayer-1.0rc2.orig/stream/stream_rtp.c 2007-10-07 15:49:26.000000000 -0400 +++ mplayer-1.0rc2/stream/stream_rtp.c 2008-06-09 13:21:08.000000000 -0400 @@ -26,6 +26,7 @@ #include "url.h" #include "udp.h" #include "rtp.h" +#include "libmpdemux/demuxer.h" static int rtp_streaming_read (int fd, char *buffer, @@ -67,6 +68,9 @@ rtp_stream_open (stream_t *stream, int mode, void *opts, int *file_format) { URL_t *url; + struct rtpheader rh; + char *data; + int len; extern int network_bandwidth; mp_msg (MSGT_OPEN, MSGL_INFO, "STREAM_RTP, URL: %s\n", stream->url); @@ -99,6 +103,15 @@ stream->type = STREAMTYPE_STREAM; fixup_network_stream_cache (stream); + + /* grab a packet and determine if we can hint the type */ + getrtp2(stream->fd, &rh, &data, &len); + + if (rh.b.pt == 32) + *file_format = DEMUXER_TYPE_MPEG_ES; + + if (rh.b.pt == 9) + *file_format = DEMUXER_TYPE_RAWAUDIO; return STREAM_OK; }
per rfc 2250, you need to skip an additional 4 bytes of header for mpeg transport streams. if you dont do this, the demuxer cant detect the mpeg transport stream. Index: stream/rtp.c =================================================================== --- stream/rtp.c (revision 31105) +++ stream/rtp.c (working copy) @@ -246,6 +246,9 @@ headerSize = 12 + 4*rh->b.cc; /* in bytes */ + if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData = lengthPacket - headerSize; *data = (char*) buf + headerSize;
Il venerdì 30 aprile 2010 18:08:46 Chas Williams (CONTRACTOR) ha scritto:
per rfc 2250, you need to skip an additional 4 bytes of header for mpeg transport streams. if you dont do this, the demuxer cant detect the mpeg transport stream.
Index: stream/rtp.c =================================================================== --- stream/rtp.c (revision 31105) +++ stream/rtp.c (working copy) @@ -246,6 +246,9 @@
headerSize = 12 + 4*rh->b.cc; /* in bytes */
+ if (rh->b.pt == 32) /* 32 = MPV from RFC 1890 */ + headerSize += 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData = lengthPacket - headerSize; *data = (char*) buf + headerSize;
Please, explain. MPV identified the 4-bytes mpeg audio or video elementary stream. Does it precede the mpegts payload???
In message <201004301824.10083.nicola.sabbi@poste.it>,Nico Sabbi writes:
Il venerd=EC 30 aprile 2010 18:08:46 Chas Williams (CONTRACTOR) ha =
scritto:
per rfc 2250, you need to skip an additional 4 bytes of header for mpeg transport streams. if you dont do this, the demuxer cant detect the mpeg transport stream.
Index: stream/rtp.c = =
--- stream/rtp.c (revision 31105) +++ stream/rtp.c (working copy) @@ -246,6 +246,9 @@
headerSize 12 + 4*rh->b.cc; /* in bytes */
+ if (rh->b.pt 32) /* 32 MPV from RFC 1890 */ + headerSize + 4; /* skip MPEG video-specific header RFC 2250 */ + *lengthData lengthPacket - headerSize; *data (char*) buf + headerSize;
Please, explain. MPV identified the 4-bytes mpeg audio or video = elementary stream. Does it precede the mpegts payload???
yes, mpeg video transport streams have header seperate from the rtp header. take a look at rfc 2250 and you will see: 3.4 MPEG Video-specific header This header shall be attached to each RTP packet after the RTP fixed header. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MBZ |T| TR | |N|S|B|E| P | | BFC | | FFC | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ AN FBV FFV note that there is another optional extended header whose presence is determined by the T-bit in the mandatory mpeg video header. however, i have never seen an rtp mpeg stream with optional extended header.
In message <20080516134500.8485095e.tempn@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@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@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
On Thu, 15 May 2008 09:21:38 -0400, "chas williams - CONTRACTOR" <chas.williams@cmf.nrl.navy.mil> wrote:
to skip over the 4-byte mpeg header present in the file. however, after looking at mplayer a bit harder, i see that there are two rtp decoders/demuxers. the one supplied in libavformat (apparently derived from ffmpeg) seems like it has more smarts. which one should i be using?
mplayer cannot use the libavformat rtp support i think :( it would be nice to be able to use ffmpegs' network support in the future. you can also try building mplayer with libnemesi , which is going to replace the live555 library one day. it supports some rtp streams i think. -compn
participants (4)
-
Chas Williams (CONTRACTOR) -
chas williams - CONTRACTOR -
compn -
Nico Sabbi