Add support for G.722 HD voice

This commit is contained in:
bossiel 2011-08-25 23:12:19 +00:00
parent 6027de054e
commit 079030a700
23 changed files with 1330 additions and 30 deletions

View File

@ -244,6 +244,7 @@ typedef enum tdav_codec_id_e
tdav_codec_id_bv32 = 0x00000001<<12,
tdav_codec_id_evrc = 0x00000001<<13,
tdav_codec_id_g729ab = 0x00000001<<14,
tdav_codec_id_g722 = 0x00000001<<15,
/* room for new Audio codecs */

View File

@ -25,6 +25,7 @@ public enum tdav_codec_id_t {
tdav_codec_id_bv32 = 0x00000001 << 12,
tdav_codec_id_evrc = 0x00000001 << 13,
tdav_codec_id_g729ab = 0x00000001 << 14,
tdav_codec_id_g722 = 0x00000001 << 15,
tdav_codec_id_h261 = 0x00010000 << 0,
tdav_codec_id_h263 = 0x00010000 << 1,
tdav_codec_id_h263p = 0x00010000 << 2,

View File

@ -25,6 +25,7 @@ public enum tdav_codec_id_t {
tdav_codec_id_bv32(0x00000001 << 12),
tdav_codec_id_evrc(0x00000001 << 13),
tdav_codec_id_g729ab(0x00000001 << 14),
tdav_codec_id_g722(0x00000001 << 15),
tdav_codec_id_h261(0x00010000 << 0),
tdav_codec_id_h263(0x00010000 << 1),
tdav_codec_id_h263p(0x00010000 << 2),

View File

@ -25,6 +25,7 @@ public enum tdav_codec_id_t {
tdav_codec_id_bv32(0x00000001 << 12),
tdav_codec_id_evrc(0x00000001 << 13),
tdav_codec_id_g729ab(0x00000001 << 14),
tdav_codec_id_g722(0x00000001 << 15),
tdav_codec_id_h261(0x00010000 << 0),
tdav_codec_id_h263(0x00010000 << 1),
tdav_codec_id_h263p(0x00010000 << 2),

View File

@ -2300,6 +2300,7 @@ package tinyWRAP;
*tdav_codec_id_bv32 = *tinyWRAPc::tdav_codec_id_bv32;
*tdav_codec_id_evrc = *tinyWRAPc::tdav_codec_id_evrc;
*tdav_codec_id_g729ab = *tinyWRAPc::tdav_codec_id_g729ab;
*tdav_codec_id_g722 = *tinyWRAPc::tdav_codec_id_g722;
*tdav_codec_id_h261 = *tinyWRAPc::tdav_codec_id_h261;
*tdav_codec_id_h263 = *tinyWRAPc::tdav_codec_id_h263;
*tdav_codec_id_h263p = *tinyWRAPc::tdav_codec_id_h263p;

View File

@ -22704,6 +22704,11 @@ XS(SWIG_init) {
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(tdav_codec_id_g729ab)));
SvREADONLY_on(sv);
} while(0) /*@SWIG@*/;
/*@SWIG:/usr/local/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
SV *sv = get_sv((char*) SWIG_prefix "tdav_codec_id_g722", TRUE | 0x2 | GV_ADDMULTI);
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(tdav_codec_id_g722)));
SvREADONLY_on(sv);
} while(0) /*@SWIG@*/;
/*@SWIG:/usr/local/share/swig/1.3.39/perl5/perltypemaps.swg,65,%set_constant@*/ do {
SV *sv = get_sv((char*) SWIG_prefix "tdav_codec_id_h261", TRUE | 0x2 | GV_ADDMULTI);
sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(tdav_codec_id_h261)));

View File

@ -1282,6 +1282,7 @@ tdav_codec_id_bv16 = _tinyWRAP.tdav_codec_id_bv16
tdav_codec_id_bv32 = _tinyWRAP.tdav_codec_id_bv32
tdav_codec_id_evrc = _tinyWRAP.tdav_codec_id_evrc
tdav_codec_id_g729ab = _tinyWRAP.tdav_codec_id_g729ab
tdav_codec_id_g722 = _tinyWRAP.tdav_codec_id_g722
tdav_codec_id_h261 = _tinyWRAP.tdav_codec_id_h261
tdav_codec_id_h263 = _tinyWRAP.tdav_codec_id_h263
tdav_codec_id_h263p = _tinyWRAP.tdav_codec_id_h263p

View File

@ -22465,6 +22465,7 @@ SWIG_init(void) {
SWIG_Python_SetConstant(d, "tdav_codec_id_bv32",SWIG_From_int(static_cast< int >(tdav_codec_id_bv32)));
SWIG_Python_SetConstant(d, "tdav_codec_id_evrc",SWIG_From_int(static_cast< int >(tdav_codec_id_evrc)));
SWIG_Python_SetConstant(d, "tdav_codec_id_g729ab",SWIG_From_int(static_cast< int >(tdav_codec_id_g729ab)));
SWIG_Python_SetConstant(d, "tdav_codec_id_g722",SWIG_From_int(static_cast< int >(tdav_codec_id_g722)));
SWIG_Python_SetConstant(d, "tdav_codec_id_h261",SWIG_From_int(static_cast< int >(tdav_codec_id_h261)));
SWIG_Python_SetConstant(d, "tdav_codec_id_h263",SWIG_From_int(static_cast< int >(tdav_codec_id_h263)));
SWIG_Python_SetConstant(d, "tdav_codec_id_h263p",SWIG_From_int(static_cast< int >(tdav_codec_id_h263p)));

View File

@ -184,6 +184,11 @@ OBJS += src/codecs/amr/tdav_codec_amr.o
OBJS += src/codecs/g711/g711.o \
src/codecs/g711/tdav_codec_g711.o
### codecs (G.722)
OBJS += src/codecs/g722/g722_decode.o \
src/codecs/g722/g722_encode.o \
src/codecs/g722/tdav_codec_g722.o
### codecs (G.729)
OBJS += src/codecs/g729/tdav_codec_g729.o

View File

@ -0,0 +1,156 @@
/*
* 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: g722.h,v 1.10 2006/06/16 12:45:53 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Changed to use WebRtc types
* -Added new defines for minimum and maximum values of short int
*/
/*! \file */
#if !defined(_G722_ENC_DEC_H_)
#define _G722_ENC_DEC_H_
#include "tinydav_config.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?
???.
*/
#define TDAV_INT16_MAX 32767
#define TDAV_INT16_MIN -32768
enum
{
G722_SAMPLE_RATE_8000 = 0x0001,
G722_PACKED = 0x0002
};
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_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options);
int g722_encode_release(g722_encode_state_t *s);
int g722_encode(g722_encode_state_t *s,
uint8_t g722_data[],
const int16_t amp[],
int len);
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

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2011 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tdav_codec_g722.h
* @brief G.722 codec plugins.
*
* @author Mamadou Diop <diopmamadou(at)doubango.org>
*
*/
#ifndef TINYDAV_CODEC_G722_H
#define TINYDAV_CODEC_G722_H
#include "tinydav_config.h"
#include "tinydav/codecs/g722/g722_enc_dec.h"
#include "tinymedia/tmedia_codec.h"
TDAV_BEGIN_DECLS
typedef struct tdav_codec_g722_s
{
TMEDIA_DECLARE_CODEC_AUDIO;
g722_encode_state_t *enc_state;
g722_decode_state_t *dec_state;
}
tdav_codec_g722_t;
TINYDAV_GEXTERN const tmedia_codec_plugin_def_t *tdav_codec_g722_plugin_def_t;
TDAV_END_DECLS
#endif /* TINYDAV_CODEC_G722_H */

View File

@ -54,6 +54,7 @@ typedef enum tdav_codec_id_e
tdav_codec_id_bv32 = 0x00000001<<12,
tdav_codec_id_evrc = 0x00000001<<13,
tdav_codec_id_g729ab = 0x00000001<<14,
tdav_codec_id_g722 = 0x00000001<<15,
/* room for new Audio codecs */

View File

@ -54,7 +54,7 @@ static void *__playback_thread(void *param)
TSK_DEBUG_INFO("__playback_thread -- START");
SetPriorityClass(GetCurrentThread(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
for(;;){
DWORD dwEvent = WaitForMultipleObjects(sizeof(dsound->notifEvents)/sizeof(HANDLE), dsound->notifEvents, FALSE, INFINITE);

View File

@ -54,7 +54,7 @@ static void *__playback_thread(void *param)
TSK_DEBUG_INFO("__record_thread -- START");
SetPriorityClass(GetCurrentThread(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
for(;;){
DWORD dwEvent = WaitForMultipleObjects(sizeof(dsound->notifEvents)/sizeof(HANDLE), dsound->notifEvents, FALSE, INFINITE);

View File

@ -138,7 +138,7 @@ static int tdav_webrtc_denoise_echo_playback(tmedia_denoise_t* self, const void*
case 32000:
{
uint32_t i;
for(i = 0; i<denoiser->frame_size; i+=denoiser->frame_size/2){
for(i = 0; i<1/*denoiser->frame_size*/; i+=denoiser->frame_size/2){
if((ret = TDAV_WebRtcAec_BufferFarend(denoiser->AEC_inst, &pEchoFrame[i], denoiser->frame_size/2))){
TSK_DEBUG_ERROR("WebRtcAec_BufferFarend failed with error code = %d", ret);
return ret;

View File

@ -162,7 +162,7 @@ static void *__playback_thread(void *param)
TSK_DEBUG_INFO("__playback_thread -- START");
SetPriorityClass(GetCurrentThread(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
for(;;){
dwEvent = WaitForMultipleObjects(2, consumer->events, FALSE, INFINITE);

View File

@ -29,7 +29,7 @@
*/
#include "tinydav/codecs/g711/tdav_codec_g711.h"
#include "tinydav/codecs/g711/g711.h" /* alforithms */
#include "tinydav/codecs/g711/g711.h" /* algorithms */
#include "tsk_memory.h"
#include "tsk_debug.h"
@ -45,29 +45,29 @@ static tsk_size_t tdav_codec_g711u_encode(tmedia_codec_t* self, const void* in_d
{
register tsk_size_t i;
register uint8_t* pout_data;
register short* pin_data;
register int16_t* pin_data;
if(!self || !in_data || !in_size || !out_data){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if(*out_max_size <in_size/2){
if(!(*out_data = tsk_realloc(*out_data, in_size/2))){
if(*out_max_size <in_size>>1){
if(!(*out_data = tsk_realloc(*out_data, in_size>>1))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = in_size/2;
*out_max_size = in_size>>1;
}
pout_data = *out_data;
pin_data = (short*)in_data;
for(i = 0; i<(in_size/2); i++){
pin_data = (int16_t*)in_data;
for(i = 0; i<(in_size>>1); i++){
pout_data[i] = linear2ulaw(pin_data[i]);
}
return (in_size/2);
return (in_size>>1);
}
static tsk_size_t tdav_codec_g711u_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
@ -80,20 +80,20 @@ static tsk_size_t tdav_codec_g711u_decode(tmedia_codec_t* self, const void* in_d
}
/* allocate new buffer */
if(*out_max_size<(in_size*2)){
if(!(*out_data = tsk_calloc(in_size, sizeof(short)))){
if(*out_max_size<(in_size<<1)){
if(!(*out_data = tsk_calloc(in_size, sizeof(int16_t)))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = in_size*2;
*out_max_size = in_size<<1;
}
for(i = 0; i<in_size; i++){
((short*)*out_data)[i] = ulaw2linear(((uint8_t*)in_data)[i]);
}
return (in_size*2);
return (in_size<<1);
}
static tsk_bool_t tdav_codec_g711u_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
@ -178,29 +178,29 @@ static tsk_size_t tdav_codec_g711a_encode(tmedia_codec_t* self, const void* in_d
{
register tsk_size_t i;
register uint8_t* pout_data;
register short* pin_data;
register int16_t* pin_data;
if(!self || !in_data || !in_size || !out_data){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
if(*out_max_size <in_size/2){
if(!(*out_data = tsk_realloc(*out_data, in_size/2))){
if(*out_max_size <in_size>>1){
if(!(*out_data = tsk_realloc(*out_data, in_size>>1))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = in_size/2;
*out_max_size = in_size>>1;
}
pout_data = *out_data;
pin_data = (short*)in_data;
for(i = 0; i<(in_size/2); i++){
pin_data = (int16_t*)in_data;
for(i = 0; i<(in_size>>1); i++){
pout_data[i] = linear2alaw(pin_data[i]);
}
return (in_size/2);
return (in_size>>1);
}
#if 0
@ -221,13 +221,13 @@ static tsk_size_t tdav_codec_g711a_decode(tmedia_codec_t* self, const void* in_d
}
#endif
/* allocate new buffer */
if(*out_max_size<(in_size*2)){
if(!(*out_data = tsk_realloc(*out_data, in_size*2))){
if(*out_max_size<(in_size<<1)){
if(!(*out_data = tsk_realloc(*out_data, in_size<<1))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = in_size*2;
*out_max_size = in_size<<1;
}
for(i = 0; i<in_size; i++){
@ -242,7 +242,7 @@ static tsk_size_t tdav_codec_g711a_decode(tmedia_codec_t* self, const void* in_d
file = tsk_null;
}
#endif
return (in_size*2);
return (in_size<<1);
}
static tsk_bool_t tdav_codec_g711a_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)

View File

@ -0,0 +1,400 @@
/*
* 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: g722_decode.c,v 1.15 2006/07/07 16:37:49 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed usage of inttypes.h and tgmath.h
* -Changed to use WebRtc types
* -Changed __inline__ to __inline
* -Added saturation check on output
*/
/*! \file */
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include "tinydav/codecs/g722/g722_enc_dec.h"
#if !defined(FALSE)
#define FALSE 0
#endif
#if !defined(TRUE)
#define TRUE (!FALSE)
#endif
static __inline 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 > TDAV_INT16_MAX)
return TDAV_INT16_MAX;
return TDAV_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
static void block4(g722_decode_state_t *s, int band, int d);
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 *) 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)
{
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 << 1);
}
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];
}
/* We shift by 12 to allow for the QMF filters (DC gain = 4096), less 1
to allow for the 15 bit input to the G.722 algorithm. */
/* WebRtc, tlegrand: added saturation */
amp[outlen++] = saturate(xout1 >> 11);
amp[outlen++] = saturate(xout2 >> 11);
}
}
}
return outlen;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,426 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* g722_encode.c - The ITU G.722 codec, encode part.
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2005 Steve Underwood
*
* All rights reserved.
*
* 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 64kbps only G.722 codec which is:
*
***** Copyright (c) CMU 1993 *****
* Computer Science, Speech Group
* Chengxiang Lu and Alex Hauptmann
*
* $Id: g722_encode.c,v 1.14 2006/07/07 16:37:49 steveu Exp $
*
* Modifications for WebRtc, 2011/04/28, by tlegrand:
* -Removed usage of inttypes.h and tgmath.h
* -Changed to use WebRtc types
* -Added option to run encoder bitexact with ITU-T reference implementation
*/
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include "tinydav/codecs/g722/g722_enc_dec.h"
#if !defined(FALSE)
#define FALSE 0
#endif
#if !defined(TRUE)
#define TRUE (!FALSE)
#endif
static __inline 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 > TDAV_INT16_MAX)
return TDAV_INT16_MAX;
return TDAV_INT16_MIN;
}
/*- End of function --------------------------------------------------------*/
static void block4(g722_encode_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 = (wd2 >> 7) + ((s->band[band].sg[0] == s->band[band].sg[2]) ? 128 : -128);
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_encode_state_t *g722_encode_init(g722_encode_state_t *s, int rate, int options)
{
if (s == NULL)
{
if ((s = (g722_encode_state_t *) 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_encode_release(g722_encode_state_t *s)
{
free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/* WebRtc, tlegrand:
* Only define the following if bit-exactness with reference implementation
* is needed. Will only have any effect if input signal is saturated.
*/
//#define RUN_LIKE_REFERENCE_G722
#ifdef RUN_LIKE_REFERENCE_G722
int16_t limitValues (int16_t rl)
{
int16_t yl;
yl = (rl > 16383) ? 16383 : ((rl < -16384) ? -16384 : rl);
return (yl);
}
#endif
int g722_encode(g722_encode_state_t *s, uint8_t g722_data[],
const int16_t amp[], int len)
{
static const int q6[32] =
{
0, 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, 0, 0
};
static const int iln[32] =
{
0, 63, 62, 31, 30, 29, 28, 27,
26, 25, 24, 23, 22, 21, 20, 19,
18, 17, 16, 15, 14, 13, 12, 11,
10, 9, 8, 7, 6, 5, 4, 0
};
static const int ilp[32] =
{
0, 61, 60, 59, 58, 57, 56, 55,
54, 53, 52, 51, 50, 49, 48, 47,
46, 45, 44, 43, 42, 41, 40, 39,
38, 37, 36, 35, 34, 33, 32, 0
};
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 qm4[16] =
{
0, -20456, -12896, -8968,
-6288, -4240, -2584, -1200,
20456, 12896, 8968, 6288,
4240, 2584, 1200, 0
};
static const int qm2[4] =
{
-7408, -1616, 7408, 1616
};
static const int qmf_coeffs[12] =
{
3, -11, 12, 32, -210, 951, 3876, -805, 362, -156, 53, -11,
};
static const int ihn[3] = {0, 1, 0};
static const int ihp[3] = {0, 3, 2};
static const int wh[3] = {0, -214, 798};
static const int rh2[4] = {2, 1, 2, 1};
int dlow;
int dhigh;
int el;
int wd;
int wd1;
int ril;
int wd2;
int il4;
int ih2;
int wd3;
int eh;
int mih;
int i;
int j;
/* Low and high band PCM from the QMF */
int xlow;
int xhigh;
int g722_bytes;
/* Even and odd tap accumulators */
int sumeven;
int sumodd;
int ihigh;
int ilow;
int code;
g722_bytes = 0;
xhigh = 0;
for (j = 0; j < len; )
{
if (s->itu_test_mode)
{
xlow =
xhigh = amp[j++] >> 1;
}
else
{
if (s->eight_k)
{
/* We shift by 1 to allow for the 15 bit input to the G.722 algorithm. */
xlow = amp[j++] >> 1;
}
else
{
/* Apply the transmit QMF */
/* Shuffle the buffer down */
for (i = 0; i < 22; i++)
s->x[i] = s->x[i + 2];
s->x[22] = amp[j++];
s->x[23] = amp[j++];
/* Discard every other QMF output */
sumeven = 0;
sumodd = 0;
for (i = 0; i < 12; i++)
{
sumodd += s->x[2*i]*qmf_coeffs[i];
sumeven += s->x[2*i + 1]*qmf_coeffs[11 - i];
}
/* We shift by 12 to allow for the QMF filters (DC gain = 4096), plus 1
to allow for us summing two filters, plus 1 to allow for the 15 bit
input to the G.722 algorithm. */
xlow = (sumeven + sumodd) >> 14;
xhigh = (sumeven - sumodd) >> 14;
#ifdef RUN_LIKE_REFERENCE_G722
/* The following lines are only used to verify bit-exactness
* with reference implementation of G.722. Higher precision
* is achieved without limiting the values.
*/
xlow = limitValues(xlow);
xhigh = limitValues(xhigh);
#endif
}
}
/* Block 1L, SUBTRA */
el = saturate(xlow - s->band[0].s);
/* Block 1L, QUANTL */
wd = (el >= 0) ? el : -(el + 1);
for (i = 1; i < 30; i++)
{
wd1 = (q6[i]*s->band[0].det) >> 12;
if (wd < wd1)
break;
}
ilow = (el < 0) ? iln[i] : ilp[i];
/* Block 2L, INVQAL */
ril = ilow >> 2;
wd2 = qm4[ril];
dlow = (s->band[0].det*wd2) >> 15;
/* Block 3L, LOGSCL */
il4 = rl42[ril];
wd = (s->band[0].nb*127) >> 7;
s->band[0].nb = wd + wl[il4];
if (s->band[0].nb < 0)
s->band[0].nb = 0;
else if (s->band[0].nb > 18432)
s->band[0].nb = 18432;
/* 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, dlow);
if (s->eight_k)
{
/* Just leave the high bits as zero */
code = (0xC0 | ilow) >> (8 - s->bits_per_sample);
}
else
{
/* Block 1H, SUBTRA */
eh = saturate(xhigh - s->band[1].s);
/* Block 1H, QUANTH */
wd = (eh >= 0) ? eh : -(eh + 1);
wd1 = (564*s->band[1].det) >> 12;
mih = (wd >= wd1) ? 2 : 1;
ihigh = (eh < 0) ? ihn[mih] : ihp[mih];
/* Block 2H, INVQAH */
wd2 = qm2[ihigh];
dhigh = (s->band[1].det*wd2) >> 15;
/* Block 3H, LOGSCH */
ih2 = rh2[ihigh];
wd = (s->band[1].nb*127) >> 7;
s->band[1].nb = wd + wh[ih2];
if (s->band[1].nb < 0)
s->band[1].nb = 0;
else if (s->band[1].nb > 22528)
s->band[1].nb = 22528;
/* 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);
code = ((ihigh << 6) | ilow) >> (8 - s->bits_per_sample);
}
if (s->packed)
{
/* Pack the code bits */
s->out_buffer |= (code << s->out_bits);
s->out_bits += s->bits_per_sample;
if (s->out_bits >= 8)
{
g722_data[g722_bytes++] = (uint8_t) (s->out_buffer & 0xFF);
s->out_bits -= 8;
s->out_buffer >>= 8;
}
}
else
{
g722_data[g722_bytes++] = (uint8_t) code;
}
}
return g722_bytes;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,216 @@
/*
* Copyright (C) 2011 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tdav_codec_g722.c
* @brief G.722 codec plugins.
*
* @author Mamadou Diop <diopmamadou(at)doubango.org>
*
*/
#include "tinydav/codecs/g722/tdav_codec_g722.h"
#include "tsk_memory.h"
#include "tsk_debug.h"
#define tdav_codec_g722_fmtp_set tsk_null
static int tdav_codec_g722_open(tmedia_codec_t* self)
{
tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
if(!g722){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
// Initialize the decoder
if(!g722->dec_state){
if(!(g722->dec_state = tsk_calloc(1, sizeof(g722_decode_state_t)))){
TSK_DEBUG_ERROR("Failed to create G.722 decoder state");
return -2;
}
// Create and/or reset the G.722 decoder
// Bitrate 64 kbps and wideband mode (2)
if(!(g722->dec_state = g722_decode_init(g722->dec_state, 64000, 2))){
TSK_DEBUG_ERROR("g722_decode_init failed");
return -3;
}
}
// Initialize the encoder
if(!g722->enc_state){
if(!(g722->enc_state = tsk_calloc(1, sizeof(g722_encode_state_t)))){
TSK_DEBUG_ERROR("Failed to create G.722 encoder state");
return -4;
}
// Create and/or reset the G.722 encoder
// Bitrate 64 kbps and wideband mode (2)
if(!(g722->enc_state = g722_encode_init(g722->enc_state, 64000, 2))){
TSK_DEBUG_ERROR("g722_encode_init failed");
return -5;
}
}
return 0;
}
static int tdav_codec_g722_close(tmedia_codec_t* self)
{
tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
(g722);
/* resources will be freed by the dctor() */
return 0;
}
static tsk_size_t tdav_codec_g722_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size)
{
tsk_size_t out_g722_size;
tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
if(!self || !in_data || !in_size || !out_data){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
out_g722_size = in_size>>2;
if(*out_max_size <out_g722_size){
if(!(*out_data = tsk_realloc(*out_data, out_g722_size))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = out_g722_size;
}
g722_encode(g722->enc_state, (uint8_t*)*out_data, (int16_t*)in_data, in_size/sizeof(int16_t));
return out_g722_size;
}
static tsk_size_t tdav_codec_g722_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
{
tdav_codec_g722_t* g722 = (tdav_codec_g722_t*)self;
if(!self || !in_data || !in_size || !out_data){
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
/* allocate new buffer */
if(*out_max_size<(in_size<<2)){
if(!(*out_data = tsk_realloc(*out_data, in_size<<2))){
TSK_DEBUG_ERROR("Failed to allocate new buffer");
*out_max_size = 0;
return 0;
}
*out_max_size = in_size<<2;
}
g722_decode(g722->dec_state, (int16_t*)*out_data, (uint8_t*)in_data, in_size);
return (in_size<<2);
}
static tsk_bool_t tdav_codec_g722_fmtp_match(const tmedia_codec_t* codec, const char* fmtp)
{
return tsk_true;
}
static char* tdav_codec_g722_fmtp_get(const tmedia_codec_t* codec)
{
return tsk_null;
}
//
// g722 Plugin definition
//
/* constructor */
static tsk_object_t* tdav_codec_g722_ctor(tsk_object_t * self, va_list * app)
{
tdav_codec_g722_t *g722 = self;
if(g722){
/* init base: called by tmedia_codec_create() */
/* init self */
}
return self;
}
/* destructor */
static tsk_object_t* tdav_codec_g722_dtor(tsk_object_t * self)
{
tdav_codec_g722_t *g722 = self;
if(g722){
/* deinit base */
tmedia_codec_audio_deinit(g722);
/* deinit self */
if(g722->enc_state){
g722_encode_release(g722->enc_state), g722->enc_state = tsk_null;
}
if(g722->dec_state){
g722_decode_release(g722->dec_state), g722->dec_state = tsk_null;
}
}
return self;
}
/* object definition */
static const tsk_object_def_t tdav_codec_g722_def_s =
{
sizeof(tdav_codec_g722_t),
tdav_codec_g722_ctor,
tdav_codec_g722_dtor,
tmedia_codec_cmp,
};
/* plugin definition*/
static const tmedia_codec_plugin_def_t tdav_codec_g722_plugin_def_s =
{
&tdav_codec_g722_def_s,
tmedia_audio,
"G722",
"g722 Codec",
TMEDIA_CODEC_FORMAT_G722,
tsk_false,
16000,
{ /* audio */
1, // channels
20 // ptime
},
/* video */
{0},
tdav_codec_g722_open,
tdav_codec_g722_close,
tdav_codec_g722_encode,
tdav_codec_g722_decode,
tdav_codec_g722_fmtp_match,
tdav_codec_g722_fmtp_get,
tdav_codec_g722_fmtp_set
};
const tmedia_codec_plugin_def_t *tdav_codec_g722_plugin_def_t = &tdav_codec_g722_plugin_def_s;

View File

@ -52,6 +52,7 @@
#include "tinydav/codecs/gsm/tdav_codec_gsm.h"
#include "tinydav/codecs/ilbc/tdav_codec_ilbc.h"
#include "tinydav/codecs/g729/tdav_codec_g729.h"
#include "tinydav/codecs/g722/tdav_codec_g722.h"
#include "tinydav/codecs/speex/tdav_codec_speex.h"
#include "tinydav/codecs/h261/tdav_codec_h261.h"
#include "tinydav/codecs/h263/tdav_codec_h263.h"
@ -152,6 +153,7 @@ int tdav_init()
tmedia_codec_plugin_register(tdav_codec_msrp_plugin_def_t);
tmedia_codec_plugin_register(tdav_codec_g711a_plugin_def_t);
tmedia_codec_plugin_register(tdav_codec_g711u_plugin_def_t);
tmedia_codec_plugin_register(tdav_codec_g722_plugin_def_t);
#if HAVE_OPENCORE_AMR
tmedia_codec_plugin_register(tdav_codec_amrnb_oa_plugin_def_t);
tmedia_codec_plugin_register(tdav_codec_amrnb_be_plugin_def_t);
@ -273,6 +275,7 @@ static tdav_codec_decl_t __codecs[] = {
#endif
{ tdav_codec_id_pcma, &tdav_codec_g711a_plugin_def_t },
{ tdav_codec_id_pcmu, &tdav_codec_g711u_plugin_def_t },
{ tdav_codec_id_g722, &tdav_codec_g722_plugin_def_t },
#if HAVE_ILBC
{ tdav_codec_id_ilbc, &tdav_codec_ilbc_plugin_def_t },
#endif
@ -371,6 +374,7 @@ tsk_bool_t tdav_codec_is_supported(tdav_codec_id_t codec)
case tdav_codec_id_pcma:
case tdav_codec_id_pcmu:
case tdav_codec_id_g722:
return tsk_true;
case tdav_codec_id_ilbc:
@ -475,6 +479,7 @@ int tdav_deinit()
tmedia_codec_plugin_unregister(tdav_codec_msrp_plugin_def_t);
tmedia_codec_plugin_unregister(tdav_codec_g711a_plugin_def_t);
tmedia_codec_plugin_unregister(tdav_codec_g711u_plugin_def_t);
tmedia_codec_plugin_unregister(tdav_codec_g722_plugin_def_t);
#if HAVE_OPENCORE_AMR
tmedia_codec_plugin_unregister(tdav_codec_amrnb_oa_plugin_def_t);
tmedia_codec_plugin_unregister(tdav_codec_amrnb_be_plugin_def_t);

View File

@ -225,6 +225,14 @@
<Filter
Name="g722"
>
<File
RelativePath=".\include\tinydav\codecs\g722\g722_enc_dec.h"
>
</File>
<File
RelativePath=".\include\tinydav\codecs\g722\tdav_codec_g722.h"
>
</File>
</Filter>
<Filter
Name="gsm"
@ -521,6 +529,18 @@
<Filter
Name="g722"
>
<File
RelativePath=".\src\codecs\g722\g722_decode.c"
>
</File>
<File
RelativePath=".\src\codecs\g722\g722_encode.c"
>
</File>
<File
RelativePath=".\src\codecs\g722\tdav_codec_g722.c"
>
</File>
</Filter>
<Filter
Name="gsm"

View File

@ -343,11 +343,18 @@ char* tmedia_codec_get_rtpmap(const tmedia_codec_t* self)
case tmedia_audio:
{ /* audio codecs */
/* const tmedia_codec_audio_t* audioCodec = (const tmedia_codec_audio_t*)self; */
if(self->plugin->audio.channels > 0){
tsk_sprintf(&rtpmap, "%s %s/%d/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->rate, self->plugin->audio.channels);
// special case for G.722 which has fake rate
if(tsk_strequals(self->plugin->format,TMEDIA_CODEC_FORMAT_G722)){
tsk_sprintf(&rtpmap, "%s %s/8000/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->audio.channels);
}
else{
tsk_sprintf(&rtpmap, "%s %s/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->audio);
if(self->plugin->audio.channels > 0){
tsk_sprintf(&rtpmap, "%s %s/%d/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->rate, self->plugin->audio.channels);
}
else{
tsk_sprintf(&rtpmap, "%s %s/%d", self->neg_format? self->neg_format : self->format, self->name, self->plugin->audio);
}
}
}
break;