diff --git a/include/opal/mediafmt.h b/include/opal/mediafmt.h index 6b9f923..d335ef9 100644 --- a/include/opal/mediafmt.h +++ b/include/opal/mediafmt.h @@ -1120,8 +1120,12 @@ class OpalVideoFormat : public OpalMediaFormat #define OPAL_PCM16 "PCM-16" #define OPAL_PCM16_16KHZ "PCM-16-16kHz" +#define OPAL_PCM16_32KHZ "PCM-16-32kHz" +#define OPAL_PCM16_48KHZ "PCM-16-48kHz" #define OPAL_L16_MONO_8KHZ "Linear-16-Mono-8kHz" #define OPAL_L16_MONO_16KHZ "Linear-16-Mono-16kHz" +#define OPAL_L16_MONO_32KHZ "Linear-16-Mono-32kHz" +#define OPAL_L16_MONO_48KHZ "Linear-16-Mono-48kHz" #define OPAL_G711_ULAW_64K "G.711-uLaw-64k" #define OPAL_G711_ALAW_64K "G.711-ALaw-64k" #define OPAL_G726_40K "G.726-40K" @@ -1148,8 +1152,12 @@ class OpalVideoFormat : public OpalMediaFormat extern const OpalAudioFormat & GetOpalPCM16(); extern const OpalAudioFormat & GetOpalPCM16_16KHZ(); +extern const OpalAudioFormat & GetOpalPCM16_32KHZ(); +extern const OpalAudioFormat & GetOpalPCM16_48KHZ(); extern const OpalAudioFormat & GetOpalL16_MONO_8KHZ(); extern const OpalAudioFormat & GetOpalL16_MONO_16KHZ(); +extern const OpalAudioFormat & GetOpalL16_MONO_32KHZ(); +extern const OpalAudioFormat & GetOpalL16_MONO_48KHZ(); extern const OpalAudioFormat & GetOpalL16_STEREO_48KHZ(); extern const OpalAudioFormat & GetOpalG711_ULAW_64K(); extern const OpalAudioFormat & GetOpalG711_ALAW_64K(); @@ -1178,8 +1186,12 @@ extern const OpalMediaFormat & GetOpalT38(); #define OpalPCM16 GetOpalPCM16() #define OpalPCM16_16KHZ GetOpalPCM16_16KHZ() +#define OpalPCM16_32KHZ GetOpalPCM16_32KHZ() +#define OpalPCM16_48KHZ GetOpalPCM16_48KHZ() #define OpalL16_MONO_8KHZ GetOpalL16_MONO_8KHZ() #define OpalL16_MONO_16KHZ GetOpalL16_MONO_16KHZ() +#define OpalL16_MONO_32KHZ GetOpalL16_MONO_32KHZ() +#define OpalL16_MONO_48KHZ GetOpalL16_MONO_48KHZ() #define OpalL16_STEREO_48KHZ GetOpalL16_STEREO_48KHZ() #define OpalG711_ULAW_64K GetOpalG711_ULAW_64K() #define OpalG711_ALAW_64K GetOpalG711_ALAW_64K() diff --git a/opal_inc.mak b/opal_inc.mak index db31fb6..e2f7d40 100644 --- a/opal_inc.mak +++ b/opal_inc.mak @@ -45,7 +45,7 @@ ifdef OPALDIR include $(OPALDIR)/opal_defs.mak else default_target: - @echo "Must have OPALDIR defined + @echo "Must have OPALDIR defined" @false endif @@ -56,7 +56,7 @@ opt :: include $(PTLIBDIR)/make/ptlib.mak else default_target: - @echo "Must have PTLIBDIR defined + @echo "Must have PTLIBDIR defined" @false endif diff --git a/plugins/Makefile.in b/plugins/Makefile.in index ae83c3f..9d473e1 100644 --- a/plugins/Makefile.in +++ b/plugins/Makefile.in @@ -7,6 +7,11 @@ SUBDIRS = audio/GSM0610 \ audio/gsm-amr \ video/H.261-vic +HAVE_CELT=@HAVE_CELT@ +ifeq ($(HAVE_CELT),yes) +SUBDIRS += audio/celt +endif + HAVE_H263=@HAVE_H263@ ifeq ($(HAVE_H263),yes) SUBDIRS += video/H.263-ffmpeg diff --git a/plugins/audio/celt/Makefile.in b/plugins/audio/celt/Makefile.in new file mode 100644 index 0000000..56d8a63 --- /dev/null +++ b/plugins/audio/celt/Makefile.in @@ -0,0 +1,63 @@ +# +# Makefile for Celt Codec Plugin +# +# based on the GSM-AMR one +# + +AC_PLUGIN_DIR=@AC_PLUGIN_DIR@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +target_os=@target_os@ + +PLUGINDIR=../.. + +BASENAME= celtcodec +SONAME = $(BASENAME) + +CC =@CC@ +CFLAGS =@CFLAGS@ +CXX =@CXX@ +LDSO =@LDSO@ +PLUGINEXT =@PLUGINEXT@ +STDCCFLAGS =@STDCCFLAGS@ +LDFLAGS =@LDFLAGS@ +LIBS = + +SRCS = celtcodec.c + +CFLAGS += -I../../../include +EXTRACFLAGS=-I$(PLUGINDIR) + +EXTRACFLAGS += @CELT_CFLAGS@ +LIBS += @CELT_LIBS@ + +PLUGIN = ./$(BASENAME)_pwplugin.$(PLUGINEXT) + +%.o : %.c + $(CC) -c $(STDCCFLAGS) $(CFLAGS) $(EXTRACFLAGS) -o $@ $< + +OBJECTS = $(patsubst %.c,%.o,$(notdir $(SRCS))) + + +$(PLUGIN): $(OBJECTS) + +ifeq (solaris,$(findstring solaris,$(target_os))) + + $(CC) $(LDSO) $@ -o $@ $^ $(LIBS) +else + $(CC) $(LDSO) -o $@ $^ $(LIBS) + +endif + +install: + mkdir -p $(DESTDIR)$(libdir)/$(AC_PLUGIN_DIR) + install $(PLUGIN) $(DESTDIR)$(libdir)/$(AC_PLUGIN_DIR) + +uninstall: + rm -f $(DESTDIR)$(libdir)/$(AC_PLUGIN_DIR)/$(PLUGIN) + +clean: + rm -f $(OBJECTS) $(PLUGIN) + +########################################### diff --git a/plugins/audio/celt/celtcodec.c b/plugins/audio/celt/celtcodec.c new file mode 100644 index 0000000..6bcfcfc --- /dev/null +++ b/plugins/audio/celt/celtcodec.c @@ -0,0 +1,391 @@ +/* + * CELT Codec Plugin for Opal + * + * Based on the GSM-AMR one + */ + +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_WARNINGS 1 + +#include +#include +#include + +#ifndef PLUGIN_CODEC_DLL_EXPORTS +#include "plugin-config.h" +#endif + +#include +#include + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) + #define STRCMPI _strcmpi +#else + #define STRCMPI strcasecmp +#endif + +/*Disable some warnings on VC++*/ +#ifdef _MSC_VER +#pragma warning(disable : 4100) +#endif + +// this is what we hand back when we are asked to create an encoder +typedef struct +{ + CELTDecoder *decoder_state; + CELTEncoder *encoder_state; + CELTMode *mode; + int frame_size; + int bytes_per_packet; +} CELTContext; + + +///////////////////////////////////////////////////////////////////////////// + +static int init_mode(CELTContext *celt, const struct PluginCodec_Definition * codec) +{ + int error = 0; + + celt->mode = celt_mode_create(codec->sampleRate, 1, codec->parm.audio.samplesPerFrame, &error); + if (celt->mode == NULL) { + return FALSE; + } + + celt_mode_info(celt->mode, CELT_GET_FRAME_SIZE, &celt->frame_size); + celt->bytes_per_packet = (codec->bitsPerSec * celt->frame_size/codec->sampleRate + 4) / 8; + + return TRUE; +} + +static void * celt_create_encoder(const struct PluginCodec_Definition * codec) +{ + CELTContext * celt = malloc(sizeof(CELTContext)); + if (celt == NULL) + return NULL; + + if (init_mode(celt, codec) == FALSE) { + free(celt); + return NULL; + } + + celt->encoder_state = celt_encoder_create(celt->mode); + if (celt->encoder_state == NULL ) { + celt_mode_destroy(celt->mode); + free(celt); + return NULL; + } + + return celt; +} + + +static void * celt_create_decoder(const struct PluginCodec_Definition * codec) +{ + CELTContext * celt = malloc(sizeof(CELTContext)); + if (celt == NULL) + return NULL; + + if (init_mode(celt, codec) == FALSE) { + free(celt); + return NULL; + } + + celt->decoder_state = celt_decoder_create(celt->mode); + if (celt->decoder_state == NULL ) { + celt_mode_destroy(celt->mode); + free(celt); + return NULL; + } + + return celt; +} + + +static void celt_destroy_encoder(const struct PluginCodec_Definition * codec, void * context) +{ + CELTContext * celt = (CELTContext *)context; + celt_encoder_destroy(celt->encoder_state); + celt_mode_destroy(celt->mode); + free(celt); +} + + +static void celt_destroy_decoder(const struct PluginCodec_Definition * codec, void * context) +{ + CELTContext * celt = (CELTContext *)context; + celt_decoder_destroy(celt->decoder_state); + celt_mode_destroy(celt->mode); + free(celt); +} + + +static int celt_codec_encoder(const struct PluginCodec_Definition * codec, + void * context, + const void * fromPtr, + unsigned * fromLen, + void * toPtr, + unsigned * toLen, + unsigned int * flag) +{ + CELTContext *celt = (CELTContext *)context; + unsigned byteCount; + + if (*fromLen < codec->parm.audio.samplesPerFrame*sizeof(short)) + return FALSE; + + if (*toLen < celt->bytes_per_packet) + return FALSE; + + byteCount = celt_encode(celt->encoder_state, (const short *)fromPtr, NULL, (char *)toPtr, celt->bytes_per_packet); + if (byteCount < 0) { + return 0; + } + *toLen = byteCount; + *fromLen = codec->parm.audio.samplesPerFrame*sizeof(short); + + return TRUE; +} + + +static int celt_codec_decoder(const struct PluginCodec_Definition * codec, + void * context, + const void * fromPtr, + unsigned * fromLen, + void * toPtr, + unsigned * toLen, + unsigned int * flag) +{ + CELTContext *celt = (CELTContext *)context; + + if (*toLen < codec->parm.audio.samplesPerFrame*sizeof(short)) + return FALSE; + + if (*fromLen == 0) + return FALSE; + + if (celt_decode(celt->decoder_state, (char *)fromPtr, *fromLen, (short *)toPtr) < 0) { + return 0; + } + + *toLen = codec->parm.audio.samplesPerFrame*sizeof(short); + + return TRUE; +} + +/* taken from Speex */ +static int valid_for_sip( + const struct PluginCodec_Definition * codec, + void * context, + const char * key, + void * parm, + unsigned * parmLen) +{ + if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char *)) + return 0; + + return (STRCMPI((const char *)parm, "sip") == 0) ? 1 : 0; +} + +///////////////////////////////////////////////////////////////////////////// + +static struct PluginCodec_ControlDefn celt_codec_controls[] = { + { "valid_for_protocol", valid_for_sip }, + { NULL } +}; + +static struct PluginCodec_information licenseInfo = { + // Fri Dec 13 2008, 23:37:31 CET = + 1229729851, + + "Stefan Knoblich, axsentis GmbH", // source code author + "0.1", // source code version + "s.knoblich@axsentis.de", // source code email + "http://oss.axsentis.de/", // source code URL + "Copyright (C) 2008 axsentis GmbH", // source code copyright + "BSD license", // source code license + PluginCodec_License_BSD, // source code license + + "CELT (ultra-low delay audio codec)", // codec description + "Jean-Marc Valin, Xiph Foundation.", // codec author + "", // codec version + "jean-marc.valin@hermes.usherb.ca", // codec email + "http://www.celt-codec.org", // codec URL + "(C) 2008 Xiph.Org Foundation, All Rights Reserved", // codec copyright information + "Xiph BSD license", // codec license + PluginCodec_License_BSD // codec license code +}; + +static struct PluginCodec_Definition celtCodecDefn[] = { + /* 32KHz */ + { + // encoder + PLUGIN_CODEC_VERSION_OPTIONS, // codec API version + &licenseInfo, // license information + + PluginCodec_MediaTypeAudio | // audio codec + PluginCodec_InputTypeRaw | // raw input data + PluginCodec_OutputTypeRaw | // raw output data + PluginCodec_RTPTypeShared | + PluginCodec_RTPTypeDynamic, // dynamic RTP type + + "CELT-32K", // text decription + "L16", // source format + "CELT-32K", // destination format + + NULL, // user data + + 32000, // samples per second + 32000, // raw bits per second + 10000, // microseconds per frame + {{ + 320, // samples per frame + 40, // bytes per frame + 1, // recommended number of frames per packet + 1, // maximum number of frames per packet + }}, + 0, // IANA RTP payload code + "CELT", // RTP payload name + + celt_create_encoder, // create codec function + celt_destroy_encoder, // destroy codec + celt_codec_encoder, // encode/decode + celt_codec_controls, // codec controls + + PluginCodec_H323Codec_NoH323, + NULL + }, + { + // decoder + PLUGIN_CODEC_VERSION_OPTIONS, // codec API version + &licenseInfo, // license information + + PluginCodec_MediaTypeAudio | // audio codec + PluginCodec_InputTypeRaw | // raw input data + PluginCodec_OutputTypeRaw | // raw output data + PluginCodec_RTPTypeShared | + PluginCodec_RTPTypeDynamic, // dynamic RTP type + +#if 0 /* supported ???*/ + PluginCodec_DecodeSilence, // Can accept missing (empty) frames and generate silence +#endif + + "CELT-32K", // text decription + "CELT-32K", // source format + "L16", // destination format + + NULL, // user data + + 32000, // samples per second + 32000, // raw bits per second + 10000, // microseconds per frame + {{ + 320, // samples per frame + 40, // bytes per frame + 1, // recommended number of frames per packet + 1, // maximum number of frames per packet + }}, + 0, // IANA RTP payload code + "CELT", // RTP payload name + + celt_create_decoder, // create codec function + celt_destroy_decoder, // destroy codec + celt_codec_decoder, // encode/decode + celt_codec_controls, // codec controls + + PluginCodec_H323Codec_NoH323, + NULL + }, + + /* 48 KHz */ + { + // encoder + PLUGIN_CODEC_VERSION_OPTIONS, // codec API version + &licenseInfo, // license information + + PluginCodec_MediaTypeAudio | // audio codec + PluginCodec_InputTypeRaw | // raw input data + PluginCodec_OutputTypeRaw | // raw output data + PluginCodec_RTPTypeShared | + PluginCodec_RTPTypeDynamic, // dynamic RTP type + + "CELT-48K", // text decription + "L16", // source format + "CELT-48K", // destination format + + NULL, // user data + + 48000, // samples per second + 48000, // raw bits per second + 10000, // microseconds per frame + {{ + 480, // samples per frame + 60, // bytes per frame + 1, // recommended number of frames per packet + 1, // maximum number of frames per packet + }}, + 0, // IANA RTP payload code + "CELT", // RTP payload name + + celt_create_encoder, // create codec function + celt_destroy_encoder, // destroy codec + celt_codec_encoder, // encode/decode + celt_codec_controls, // codec controls + + PluginCodec_H323Codec_NoH323, + NULL + }, + { + // decoder + PLUGIN_CODEC_VERSION_OPTIONS, // codec API version + &licenseInfo, // license information + + PluginCodec_MediaTypeAudio | // audio codec + PluginCodec_InputTypeRaw | // raw input data + PluginCodec_OutputTypeRaw | // raw output data + PluginCodec_RTPTypeShared | + PluginCodec_RTPTypeDynamic, // dynamic RTP type + +#if 0 /* supported ???*/ + PluginCodec_DecodeSilence, // Can accept missing (empty) frames and generate silence +#endif + + "CELT-48K", // text decription + "CELT-48K", // source format + "L16", // destination format + + NULL, // user data + + 48000, // samples per second + 48000, // raw bits per second + 10000, // microseconds per frame + {{ + 480, // samples per frame + 60, // bytes per frame + 1, // recommended number of frames per packet + 1, // maximum number of frames per packet + }}, + 0, // IANA RTP payload code + "CELT", // RTP payload name + + celt_create_decoder, // create codec function + celt_destroy_decoder, // destroy codec + celt_codec_decoder, // encode/decode + celt_codec_controls, // codec controls + + PluginCodec_H323Codec_NoH323, + NULL + } +}; + + +PLUGIN_CODEC_IMPLEMENT_ALL(CELT, celtCodecDefn, PLUGIN_CODEC_VERSION_OPTIONS) + +///////////////////////////////////////////////////////////////////////////// diff --git a/plugins/configure.ac b/plugins/configure.ac index 85d4ccf..d6d0001 100644 --- a/plugins/configure.ac +++ b/plugins/configure.ac @@ -111,6 +111,7 @@ HAVE_CAPI=yes HAVE_IXJ=no HAVE_H263=yes HAVE_H264=yes +HAVE_CELT=no HAVE_SPANDSP=yes DEFAULT_TO_FULL_CAPABILITIES=yes X264_LINK_STATIC=no @@ -270,6 +271,22 @@ PKG_CHECK_MODULES([THEORA], AC_SUBST(HAVE_THEORA) dnl ######################## +dnl celt +dnl ######################## +PKG_CHECK_MODULES([CELT], + [celt], + [ + AC_SUBST(CELT_CFLAGS) + AC_SUBST(CELT_LIBS) + AC_DEFINE([HAVE_CELT], [1], [celt]) + HAVE_CELT=yes + ], + [ + HAVE_CELT=no + ]) +AC_SUBST(HAVE_CELT) + +dnl ######################## dnl LIBDL dnl ######################## OPAL_FIND_LIBDL([HAVE_LIBDL=yes], [HAVE_LIBDL=no]) @@ -373,6 +390,9 @@ fi if test -d audio/IMA_ADPCM ; then AC_CONFIG_FILES(audio/IMA_ADPCM/Makefile) fi +if test -d audio/celt ; then + AC_CONFIG_FILES(audio/celt/Makefile) +fi if test -d video/H.261-vic ; then AC_CONFIG_FILES(video/H.261-vic/Makefile) fi @@ -467,6 +487,7 @@ fi else echo " MPEG4 Part 2 : no" fi +echo " CELT : ${HAVE_CELT}" echo "" echo " SpanDSP FAX : $HAVE_SPANDSP" diff --git a/src/codec/opalpluginmgr.cxx b/src/codec/opalpluginmgr.cxx index 7326111..0997819 100644 --- a/src/codec/opalpluginmgr.cxx +++ b/src/codec/opalpluginmgr.cxx @@ -793,8 +793,8 @@ bool OpalPluginTranscoder::UpdateOptions(const OpalMediaFormat & fmt) // OpalPluginFramedAudioTranscoder::OpalPluginFramedAudioTranscoder(PluginCodec_Definition * _codec, PBoolean _isEncoder, const char * rawFormat) - : OpalFramedTranscoder( (strcmp(_codec->sourceFormat, "L16") == 0) ? (rawFormat != NULL ? rawFormat : ((_codec->sampleRate == 8000) ? OpalPCM16 : OpalPCM16_16KHZ)) : _codec->sourceFormat, - (strcmp(_codec->destFormat, "L16") == 0) ? (rawFormat != NULL ? rawFormat : ((_codec->sampleRate == 8000) ? OpalPCM16 : OpalPCM16_16KHZ)) : _codec->destFormat, + : OpalFramedTranscoder( (strcmp(_codec->sourceFormat, "L16") == 0) ? (rawFormat != NULL ? rawFormat : ((_codec->sampleRate == 8000) ? OpalPCM16 : ((_codec->sampleRate == 16000) ? OpalPCM16_16KHZ : ((_codec->sampleRate == 32000) ? OpalPCM16_32KHZ : OpalPCM16_48KHZ)))) : _codec->sourceFormat, + (strcmp(_codec->destFormat, "L16") == 0) ? (rawFormat != NULL ? rawFormat : ((_codec->sampleRate == 8000) ? OpalPCM16 : ((_codec->sampleRate == 16000) ? OpalPCM16_16KHZ : ((_codec->sampleRate == 32000) ? OpalPCM16_32KHZ : OpalPCM16_48KHZ)))) : _codec->destFormat, _isEncoder ? _codec->parm.audio.samplesPerFrame*2 : _codec->parm.audio.bytesPerFrame, _isEncoder ? _codec->parm.audio.bytesPerFrame : _codec->parm.audio.samplesPerFrame*2) , OpalPluginTranscoder(_codec, _isEncoder) @@ -869,8 +869,8 @@ OpalPluginStreamedAudioTranscoder::OpalPluginStreamedAudioTranscoder(PluginCodec PBoolean _isEncoder, unsigned inputBits, unsigned outputBits) - : OpalStreamedTranscoder((strcmp(_codec->sourceFormat, "L16") == 0) ? ((_codec->sampleRate == 8000) ? OpalPCM16 : OpalPCM16_16KHZ) : _codec->sourceFormat, - (strcmp(_codec->destFormat, "L16") == 0) ? ((_codec->sampleRate == 8000) ? OpalPCM16 : OpalPCM16_16KHZ) : _codec->destFormat, + : OpalStreamedTranscoder((strcmp(_codec->sourceFormat, "L16") == 0) ? ((_codec->sampleRate == 8000) ? OpalPCM16 : ((_codec->sampleRate == 16000) ? OpalPCM16_16KHZ : ((_codec->sampleRate == 32000) ? OpalPCM16_32KHZ : OpalPCM16_48KHZ))) : _codec->sourceFormat, + (strcmp(_codec->destFormat, "L16") == 0) ? ((_codec->sampleRate == 8000) ? OpalPCM16 : ((_codec->sampleRate == 16000) ? OpalPCM16_16KHZ : ((_codec->sampleRate == 32000) ? OpalPCM16_32KHZ : OpalPCM16_48KHZ))) : _codec->destFormat, inputBits, outputBits) , OpalPluginTranscoder(_codec, _isEncoder) { @@ -1605,6 +1605,16 @@ void OpalPluginCodecManager::RegisterPluginPair( new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, PTrue); new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, PFalse); } + else if (encoderCodec->sampleRate == 32000) + { + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_32KHZ, encoderCodec->destFormat), encoderCodec, PTrue); + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_32KHZ), decoderCodec, PFalse); + } + else if (encoderCodec->sampleRate == 48000) + { + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_48KHZ, encoderCodec->destFormat), encoderCodec, PTrue); + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_48KHZ), decoderCodec, PFalse); + } else { PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate); @@ -1620,6 +1630,16 @@ void OpalPluginCodecManager::RegisterPluginPair( new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_16KHZ, encoderCodec->destFormat), encoderCodec, PTrue); new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_16KHZ), decoderCodec, PFalse); } + else if (encoderCodec->sampleRate == 32000) + { + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_32KHZ, encoderCodec->destFormat), encoderCodec, PTrue); + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_32KHZ), decoderCodec, PFalse); + } + else if (encoderCodec->sampleRate == 48000) + { + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(OpalPCM16_48KHZ, encoderCodec->destFormat), encoderCodec, PTrue); + new OpalPluginTranscoderFactory::Worker(OpalTranscoderKey(encoderCodec->destFormat, OpalPCM16_48KHZ), decoderCodec, PFalse); + } else { PTRACE(1, "OpalPlugin\tAudio plugin defines unsupported clock rate " << encoderCodec->sampleRate); diff --git a/src/opal/endpoint.cxx b/src/opal/endpoint.cxx index e8050ed..bfe28f4 100644 --- a/src/opal/endpoint.cxx +++ b/src/opal/endpoint.cxx @@ -502,6 +502,8 @@ OpalMediaFormatList OpalEndPoint::GetMediaFormats() const // Sound cards can only do 16 bit PCM, but at various sample rates // The following will be in order of preference, so lets do wideband first + formats += OpalPCM16_48KHZ; + formats += OpalPCM16_32KHZ; formats += OpalPCM16_16KHZ; formats += OpalPCM16; diff --git a/src/opal/mediafmt.cxx b/src/opal/mediafmt.cxx index b32f91b..04e082d 100644 --- a/src/opal/mediafmt.cxx +++ b/src/opal/mediafmt.cxx @@ -73,8 +73,12 @@ static class InstantiateMe AUDIO_FORMAT(PCM16, MaxPayloadType, "", 16, 8, 240, 0, 256, 8000); AUDIO_FORMAT(PCM16_16KHZ, MaxPayloadType, "", 32,16, 240, 0, 256, 16000); +AUDIO_FORMAT(PCM16_32KHZ, MaxPayloadType, "", 64,32, 240, 0, 256, 32000); +AUDIO_FORMAT(PCM16_48KHZ, MaxPayloadType, "", 96,48, 240, 0, 256, 48000); AUDIO_FORMAT(L16_MONO_8KHZ, L16_Mono, "L16", 16, 8, 240, 30, 256, 8000); AUDIO_FORMAT(L16_MONO_16KHZ, L16_Mono, "L16", 32,16, 240, 30, 256, 16000); +AUDIO_FORMAT(L16_MONO_32KHZ, L16_Mono, "L16", 64,32, 240, 30, 256, 32000); +AUDIO_FORMAT(L16_MONO_48KHZ, L16_Mono, "L16", 96,48, 240, 30, 256, 48000); AUDIO_FORMAT(G711_ULAW_64K, PCMU, "PCMU", 8, 8, 240, 20, 256, 8000); AUDIO_FORMAT(G711_ALAW_64K, PCMA, "PCMA", 8, 8, 240, 20, 256, 8000); Index: src/opal/mediastrm.cxx =================================================================== --- a/src/opal/mediastrm.cxx (revision 21846) +++ b/src/opal/mediastrm.cxx (working copy) @@ -917,7 +917,7 @@ /* For efficiency reasons we will not accept a packet size that is too small. We move it up to the next even multiple, which has a danger of the remote not sending an even number of our multiplier. */ - const unsigned MinTime = 20; + const unsigned MinTime = 10; PINDEX minSize = mediaFormat.GetClockRate()/(1000/MinTime)*sizeof(short); if (dataSize < minSize) { PTRACE(1, "Media\tClamping audio stream data size from " << dataSize << " to minimum " << minSize);