Added AMR-NB codec based on 3GPP code converted to library by Stanislav Brabec.
git-svn-id: http://voip.null.ro/svn/yate@1984 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
0d3d4aa509
commit
4b4d836687
39
configure.in
39
configure.in
|
@ -446,6 +446,7 @@ HAVE_ALSA="yes"
|
|||
AC_MSG_RESULT([$HAVE_ALSA])
|
||||
AC_SUBST(HAVE_ALSA)
|
||||
|
||||
|
||||
HAVE_GSM=no
|
||||
GSM_INC=""
|
||||
AC_ARG_WITH(libgsm,AC_HELP_STRING([--with-libgsm],[use GSM codec if available (default)]),[ac_cv_use_libgsm=$withval],[ac_cv_use_libgsm=yes])
|
||||
|
@ -466,6 +467,7 @@ fi
|
|||
AC_SUBST(HAVE_GSM)
|
||||
AC_SUBST(GSM_INC)
|
||||
|
||||
|
||||
HAVE_ILBC=no
|
||||
ILBC_INC=""
|
||||
AC_ARG_ENABLE(ilbc,AC_HELP_STRING([--enable-ilbc],[Enable iLBC codec (default: yes)]),want_ilbc=$enableval,want_ilbc=yes)
|
||||
|
@ -516,6 +518,31 @@ fi
|
|||
AC_SUBST(HAVE_SPEEX)
|
||||
AC_SUBST(SPEEX_INC)
|
||||
|
||||
|
||||
HAVE_AMRNB=no
|
||||
AMRNB_INC=""
|
||||
AMRNB_LIB=""
|
||||
AC_ARG_WITH(amrnb,AC_HELP_STRING([--with-amrnb=DIR],[use AMR-NB if available (default)]),[ac_cv_use_amrnb=$withval],[ac_cv_use_amrnb=/usr])
|
||||
if [[ "x$ac_cv_use_amrnb" != "xno" ]]; then
|
||||
AC_MSG_CHECKING([for AMR-NB in $ac_cv_use_amrnb])
|
||||
local_lib="$ARCHLIB"
|
||||
amrinc="$ac_cv_use_amrnb/include/amrnb"
|
||||
test -f "$ac_cv_use_amrnb/$local_lib/libamrnb.so" || local_lib="lib"
|
||||
if [[ -f "$ac_cv_use_amrnb/$local_lib/libamrnb.so" -a -f "$amrinc/interf_rom.h" ]]; then
|
||||
HAVE_AMRNB=yes
|
||||
AMRNB_LIB="-L$ac_cv_use_amrnb/$local_lib -lamrnb"
|
||||
AMRNB_INC="-I$amrinc"
|
||||
fi
|
||||
AC_MSG_RESULT([$HAVE_AMRNB])
|
||||
if [[ "x$HAVE_AMRNB" != "xyes" -a "x$YATE_VER" != "xno" ]]; then
|
||||
AC_ERROR([Could not find AMR-NB devel files])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(HAVE_AMRNB)
|
||||
AC_SUBST(AMRNB_INC)
|
||||
AC_SUBST(AMRNB_LIB)
|
||||
|
||||
|
||||
HAVE_SPANDSP=no
|
||||
SPANDSP_INC=""
|
||||
AC_ARG_WITH(spandsp,AC_HELP_STRING([--with-spandsp],[use spandsp library if available (default)]),[ac_cv_use_spandsp=$withval],[ac_cv_use_spandsp=yes])
|
||||
|
@ -564,6 +591,7 @@ fi
|
|||
AC_SUBST(HAVE_SPANDSP)
|
||||
AC_SUBST(SPANDSP_INC)
|
||||
|
||||
|
||||
HAVE_PWLIB=no
|
||||
PWLIB_RTTI=none
|
||||
PWLIB_INC=""
|
||||
|
@ -623,6 +651,7 @@ fi
|
|||
AC_MSG_RESULT([$HAVE_PWLIB $verpw RTTI: $PWLIB_RTTI])
|
||||
fi
|
||||
|
||||
|
||||
HAVE_H323=no
|
||||
H323_INC=""
|
||||
H323_LIB=""
|
||||
|
@ -673,6 +702,7 @@ AC_SUBST(H323_INC)
|
|||
AC_SUBST(H323_LIB)
|
||||
AC_SUBST(H323_RUN)
|
||||
|
||||
|
||||
HAVE_OPENSSL=no
|
||||
OPENSSL_INC=""
|
||||
OPENSSL_LIB=""
|
||||
|
@ -703,6 +733,7 @@ AC_SUBST(OPENSSL_INC)
|
|||
AC_SUBST(OPENSSL_LIB)
|
||||
AC_SUBST(OPENSSL_VER)
|
||||
|
||||
|
||||
HAVE_GTK2=no
|
||||
GTK2_INC=""
|
||||
GTK2_LIB=""
|
||||
|
@ -726,6 +757,7 @@ AC_SUBST(HAVE_GTK2)
|
|||
AC_SUBST(GTK2_INC)
|
||||
AC_SUBST(GTK2_LIB)
|
||||
|
||||
|
||||
HAVE_GMOZ=no
|
||||
GMOZ_INC=""
|
||||
GMOZ_LIB=""
|
||||
|
@ -762,6 +794,7 @@ AC_SUBST(HAVE_GMOZ)
|
|||
AC_SUBST(GMOZ_INC)
|
||||
AC_SUBST(GMOZ_LIB)
|
||||
|
||||
|
||||
HAVE_QT4=no
|
||||
QT4_INC=""
|
||||
QT4_LIB=""
|
||||
|
@ -792,6 +825,7 @@ AC_SUBST(QT4_LIB)
|
|||
AC_SUBST(QT4_MOC)
|
||||
AC_SUBST(QT4_VER)
|
||||
|
||||
|
||||
HAVE_COREDUMPER=no
|
||||
COREDUMPER_INC=""
|
||||
COREDUMPER_LIB=""
|
||||
|
@ -816,6 +850,7 @@ AC_SUBST(HAVE_COREDUMPER)
|
|||
AC_SUBST(COREDUMPER_INC)
|
||||
AC_SUBST(COREDUMPER_LIB)
|
||||
|
||||
|
||||
RTTI_OPT=""
|
||||
AC_ARG_ENABLE(rtti,AC_HELP_STRING([--enable-rtti],[Enable RTTI support (default: like pwlib)]),want_rtti=$enableval,want_rtti=auto)
|
||||
AC_MSG_CHECKING([whether to enable RTTI support])
|
||||
|
@ -848,6 +883,7 @@ AC_MSG_WARN([Mismatched RTTI setting between Yate ($USE_RTTI) and pwlib ($PWLIB_
|
|||
fi
|
||||
fi
|
||||
|
||||
|
||||
INSTALL_D="install -D"
|
||||
MODULE_CFLAGS="-fno-exceptions -fPIC $HAVE_GCC_FORMAT_CHECK"
|
||||
MODULE_CPPFLAGS="-fno-check-new $RTTI_OPT $MODULE_CFLAGS"
|
||||
|
@ -867,6 +903,7 @@ AC_SUBST(MODULE_LDRELAX)
|
|||
AC_SUBST(MODULE_LDFLAGS)
|
||||
AC_SUBST(MODULE_SYMBOLS)
|
||||
|
||||
|
||||
DOXYGEN_BIN=""
|
||||
AC_ARG_WITH(doxygen,AC_HELP_STRING([--with-doxygen=EXE],[use doxygen to generate API docs (default: PATH)]),[ac_cv_use_doxygen=$withval],[ac_cv_use_doxygen=yes])
|
||||
if [[ "x$ac_cv_use_doxygen" != "xno" ]]; then
|
||||
|
@ -882,6 +919,7 @@ AC_MSG_RESULT([$ac_cv_use_doxygen])
|
|||
fi
|
||||
AC_SUBST(DOXYGEN_BIN)
|
||||
|
||||
|
||||
KDOC_BIN=""
|
||||
AC_ARG_WITH(kdoc,AC_HELP_STRING([--with-kdoc=EXE],[use kdoc to generate API docs (default: PATH)]),[ac_cv_use_kdoc=$withval],[ac_cv_use_kdoc=yes])
|
||||
if [[ "x$ac_cv_use_kdoc" != "xno" ]]; then
|
||||
|
@ -897,6 +935,7 @@ AC_MSG_RESULT([$ac_cv_use_kdoc])
|
|||
fi
|
||||
AC_SUBST(KDOC_BIN)
|
||||
|
||||
|
||||
m4_sinclude(./YateLocal.ac)
|
||||
|
||||
AC_CONFIG_FILES([packing/rpm/yate.spec
|
||||
|
|
|
@ -92,6 +92,10 @@ ifneq (@HAVE_SPEEX@,no)
|
|||
PROGS := $(PROGS) speexcodec.yate
|
||||
endif
|
||||
|
||||
ifneq (@HAVE_AMRNB@,no)
|
||||
PROGS := $(PROGS) amrnbcodec.yate
|
||||
endif
|
||||
|
||||
ifneq (@HAVE_OPENSSL@,no)
|
||||
PROGS := $(PROGS) openssl.yate
|
||||
endif
|
||||
|
@ -246,6 +250,9 @@ gsmcodec.yate: LOCALFLAGS = @GSM_INC@
|
|||
speexcodec.yate: LOCALLIBS = -lspeex
|
||||
speexcodec.yate: LOCALFLAGS = @SPEEX_INC@
|
||||
|
||||
amrnbcodec.yate: LOCALFLAGS = @AMRNB_INC@
|
||||
amrnbcodec.yate: LOCALLIBS = @AMRNB_LIB@
|
||||
|
||||
faxchan.yate: LOCALLIBS = -lspandsp
|
||||
faxchan.yate: LOCALFLAGS = @SPANDSP_INC@
|
||||
|
||||
|
|
|
@ -0,0 +1,369 @@
|
|||
/**
|
||||
* amrnbcodec.cpp
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* AMR narrowband transcoder implemented using 3GPP codec
|
||||
*
|
||||
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
||||
* Copyright (C) 2004-2007 Null Team
|
||||
* Author: Paul Chitescu
|
||||
*
|
||||
* AMR codec library by Stanislav Brabec at http://www.penguin.cz/~utx/amr
|
||||
*
|
||||
* This program 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <yatephone.h>
|
||||
|
||||
extern "C" {
|
||||
#include <interf_enc.h>
|
||||
#include <interf_dec.h>
|
||||
}
|
||||
namespace RxTypes {
|
||||
// There is a conflict between encoder and decoder so insulate in a namespace
|
||||
#include <sp_dec.h>
|
||||
};
|
||||
|
||||
// IF1/GP3 is Bandwidth-Efficient Mode
|
||||
// IF2 is Octet-aligned Mode (not supported here)
|
||||
|
||||
using namespace TelEngine;
|
||||
namespace { // anonymous
|
||||
|
||||
#define MODNAME "amrnbcodec"
|
||||
|
||||
// Transcoding voice size, 20ms of 8kHz slin data
|
||||
#define SAMPLES_FRAME 160
|
||||
|
||||
// Transcoding buffer size, 2 bytes per sample
|
||||
#define BUFFER_SIZE (2*SAMPLES_FRAME)
|
||||
|
||||
// Maximum compressed frame size
|
||||
#define MAX_AMRNB_SIZE 32
|
||||
|
||||
// Maximum number of frames we are willing to decode in a packet
|
||||
#define MAX_PKT_FRAMES 4
|
||||
|
||||
class AmrPlugin : public Plugin, public TranslatorFactory
|
||||
{
|
||||
public:
|
||||
AmrPlugin();
|
||||
~AmrPlugin();
|
||||
virtual void initialize() {}
|
||||
virtual bool isBusy() const;
|
||||
virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat);
|
||||
virtual const TranslatorCaps* getCapabilities() const;
|
||||
};
|
||||
|
||||
class AmrTrans : public DataTranslator
|
||||
{
|
||||
public:
|
||||
AmrTrans(const char* sFormat, const char* dFormat, void* amrState);
|
||||
virtual ~AmrTrans();
|
||||
virtual void Consume(const DataBlock& data, unsigned long tStamp);
|
||||
inline bool valid() const
|
||||
{ return 0 != m_amrState; }
|
||||
protected:
|
||||
bool dataError(const char* text = 0);
|
||||
virtual bool pushData(unsigned long& tStamp) = 0;
|
||||
void* m_amrState;
|
||||
DataBlock m_data;
|
||||
bool m_showError;
|
||||
Mode m_cmr;
|
||||
};
|
||||
|
||||
// Encoding specific class
|
||||
class AmrEncoder : public AmrTrans
|
||||
{
|
||||
public:
|
||||
inline AmrEncoder(const char* sFormat, const char* dFormat, bool discont = false)
|
||||
: AmrTrans(sFormat,dFormat,::Encoder_Interface_init(discont ? 1 : 0)),
|
||||
m_mode(MR122)
|
||||
{ }
|
||||
virtual ~AmrEncoder();
|
||||
protected:
|
||||
virtual bool pushData(unsigned long& tStamp);
|
||||
Mode m_mode;
|
||||
};
|
||||
|
||||
// Decoding specific class
|
||||
class AmrDecoder : public AmrTrans
|
||||
{
|
||||
public:
|
||||
inline AmrDecoder(const char* sFormat, const char* dFormat)
|
||||
: AmrTrans(sFormat,dFormat,::Decoder_Interface_init())
|
||||
{ }
|
||||
virtual ~AmrDecoder();
|
||||
protected:
|
||||
virtual bool pushData(unsigned long& tStamp);
|
||||
};
|
||||
|
||||
// Module data
|
||||
static int count = 0; // Created objects
|
||||
|
||||
static TranslatorCaps caps[] = {
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
// Voice bits per mode 0-7, 8 = Silence, 15 = No Data
|
||||
static int modeBits[16] = {
|
||||
95, 103, 118, 134, 148, 159, 204, 244, 39,
|
||||
-1, -1, -1, -1, -1, -1, 0
|
||||
};
|
||||
|
||||
// Discontinuous Transmission (DTX)
|
||||
bool s_discontinuous = false;
|
||||
|
||||
|
||||
// Helper function, gets a number of bits and advances pointer, return -1 for error
|
||||
static int getBits(unsigned const char*& ptr, int& len, int& bpos, unsigned char bits)
|
||||
{
|
||||
if (!ptr)
|
||||
return -1;
|
||||
if (!bits)
|
||||
return 0;
|
||||
int ret = 0;
|
||||
int mask = 0x80;
|
||||
while (bits--) {
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
if (((ptr[0] >> (7 - bpos)) & 1) != 0)
|
||||
ret |= mask;
|
||||
mask = mask >> 1;
|
||||
if (++bpos >= 8) {
|
||||
bpos = 0;
|
||||
ptr++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Arbitrary type transcoder constructor
|
||||
AmrTrans::AmrTrans(const char* sFormat, const char* dFormat, void* amrState)
|
||||
: DataTranslator(sFormat,dFormat),
|
||||
m_amrState(amrState), m_showError(true), m_cmr(MR122)
|
||||
{
|
||||
Debug(MODNAME,DebugAll,"AmrTrans::AmrTrans('%s','%s',%p) [%p]",
|
||||
sFormat,dFormat,amrState,this);
|
||||
count++;
|
||||
}
|
||||
|
||||
// Destructor, closes the channel
|
||||
AmrTrans::~AmrTrans()
|
||||
{
|
||||
Debug(MODNAME,DebugAll,"AmrTrans::~AmrTrans() [%p]",this);
|
||||
m_amrState = 0;
|
||||
count--;
|
||||
}
|
||||
|
||||
// Actual transcoding of data
|
||||
void AmrTrans::Consume(const DataBlock& data, unsigned long tStamp)
|
||||
{
|
||||
if (!(m_amrState && getTransSource()))
|
||||
return;
|
||||
ref();
|
||||
m_data += data;
|
||||
if (!tStamp)
|
||||
tStamp = timeStamp() + SAMPLES_FRAME;
|
||||
while (pushData(tStamp))
|
||||
;
|
||||
deref();
|
||||
}
|
||||
|
||||
// Data error, report error 1st time and clear buffer
|
||||
bool AmrTrans::dataError(const char* text)
|
||||
{
|
||||
if (m_showError) {
|
||||
m_showError = false;
|
||||
const char* prefix = ": ";
|
||||
if (!text)
|
||||
prefix = text = "";
|
||||
Debug(MODNAME,DebugWarn,"Error transcoding data%s%s [%p]",prefix,text,this);
|
||||
}
|
||||
m_data.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Encoder cleanup
|
||||
AmrEncoder::~AmrEncoder()
|
||||
{
|
||||
Debug(MODNAME,DebugAll,"AmrEncoder::~AmrEncoder() %p [%p]",m_amrState,this);
|
||||
if (m_amrState)
|
||||
::Encoder_Interface_exit(m_amrState);
|
||||
}
|
||||
|
||||
// Encode accumulated slin data and push it to the consumer
|
||||
bool AmrEncoder::pushData(unsigned long& tStamp)
|
||||
{
|
||||
if (m_data.length() < BUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
unsigned char unpacked[MAX_AMRNB_SIZE+1];
|
||||
int len = ::Encoder_Interface_Encode(m_amrState,m_mode,(short*)m_data.data(),unpacked,0);
|
||||
if ((len <= 0) || (len > MAX_AMRNB_SIZE))
|
||||
return dataError("encoder");
|
||||
unpacked[len] = 0;
|
||||
XDebug(MODNAME,DebugAll,"Encoded mode %d frame to %d bytes first %02x [%p]",
|
||||
m_mode,len,unpacked[0],this);
|
||||
unsigned char buffer[MAX_AMRNB_SIZE];
|
||||
// build a TOC with just one entry
|
||||
// 4 bit CMR, 1 bit follows (forced 0), 3 bits of mode
|
||||
buffer[0] = (m_cmr << 4) | ((unpacked[0] >> 4) & 0x07);
|
||||
// 1 bit of mode and 1 bit Q
|
||||
unsigned char leftover = (unpacked[0] << 4) & 0xc0;
|
||||
for (int i = 1; i < len; i++) {
|
||||
buffer[i] = leftover | (unpacked[i] >> 2);
|
||||
leftover = (unpacked[i] << 6) & 0xc0;
|
||||
}
|
||||
m_data.cut(-BUFFER_SIZE);
|
||||
DataBlock outData(buffer,len,false);
|
||||
getTransSource()->Forward(outData,tStamp);
|
||||
outData.clear(false);
|
||||
tStamp += SAMPLES_FRAME;
|
||||
return (0 != m_data.length());
|
||||
}
|
||||
|
||||
|
||||
// Decoder cleanup
|
||||
AmrDecoder::~AmrDecoder()
|
||||
{
|
||||
Debug(MODNAME,DebugAll,"AmrDecoder::~AmrDecoder() %p [%p]",m_amrState,this);
|
||||
if (m_amrState)
|
||||
::Decoder_Interface_exit(m_amrState);
|
||||
}
|
||||
|
||||
// Decode AMR data and push it to the consumer
|
||||
bool AmrDecoder::pushData(unsigned long& tStamp)
|
||||
{
|
||||
if (m_data.length() < 2)
|
||||
return false;
|
||||
unsigned const char* ptr = (unsigned const char*)m_data.data();
|
||||
int len = m_data.length();
|
||||
int bpos = 0;
|
||||
unsigned char cmr = getBits(ptr,len,bpos,4) >> 4;
|
||||
unsigned int tocLen = 0;
|
||||
unsigned char toc[MAX_PKT_FRAMES];
|
||||
int dataBits = 0;
|
||||
// read the TOC
|
||||
for (;;) {
|
||||
int ft = getBits(ptr,len,bpos,6);
|
||||
if (ft < 0)
|
||||
return dataError("TOC truncated");
|
||||
int nBits = modeBits[(ft >> 3) & 0x0f];
|
||||
// discard the entire packet if an invalid frame is found
|
||||
if (nBits < 0)
|
||||
return dataError("invalid mode");
|
||||
dataBits += nBits;
|
||||
toc[tocLen++] = ft & 0x7c; // keep type and quality bit
|
||||
// does another TOC follow?
|
||||
if (0 == (ft & 0x80))
|
||||
break;
|
||||
if (tocLen >= MAX_PKT_FRAMES)
|
||||
return dataError("TOC too large");
|
||||
}
|
||||
if (dataBits > (8*len - bpos))
|
||||
return dataError("data truncated");
|
||||
// We read the TOC, now pick the following voice frames and decode
|
||||
for (unsigned int idx = 0; idx < tocLen; idx++) {
|
||||
int mode = (toc[idx] >> 3) & 0x0f;
|
||||
bool good = 0 != (toc[idx] & 0x04);
|
||||
int nBits = modeBits[mode];
|
||||
XDebug(MODNAME,DebugAll,"Decoding %d bits %s mode %d frame %u [%p]",
|
||||
nBits,(good ? "good" : "bad"),mode,idx,this);
|
||||
unsigned char unpacked[MAX_AMRNB_SIZE];
|
||||
unpacked[0] = toc[idx];
|
||||
for (unsigned int i = 1; i < MAX_AMRNB_SIZE; i++) {
|
||||
int bits = (nBits <= 8) ? nBits : 8;
|
||||
unpacked[i] = getBits(ptr,len,bpos,bits);
|
||||
nBits -= bits;
|
||||
}
|
||||
short buffer[SAMPLES_FRAME];
|
||||
int type = (MRDTX == mode) ?
|
||||
(good ? RxTypes::RX_SID_UPDATE : RxTypes::RX_SID_BAD) :
|
||||
(good ? RxTypes::RX_SPEECH_GOOD : RxTypes::RX_SPEECH_DEGRADED);
|
||||
::Decoder_Interface_Decode(m_amrState,unpacked,buffer,type);
|
||||
DataBlock outData(buffer,BUFFER_SIZE,false);
|
||||
getTransSource()->Forward(outData,tStamp);
|
||||
outData.clear(false);
|
||||
tStamp += SAMPLES_FRAME;
|
||||
}
|
||||
if (bpos)
|
||||
len--;
|
||||
// now len holds how many bytes we should keep in data buffer
|
||||
m_data.cut(len-(int)m_data.length());
|
||||
if (cmr != m_cmr) {
|
||||
Debug(MODNAME,DebugNote,"Remote CMR changed from %d to %d [%p]",
|
||||
m_cmr,cmr,this);
|
||||
m_cmr = (Mode)cmr;
|
||||
// TODO: find and notify paired encoder about the mode change request
|
||||
}
|
||||
return (0 != m_data.length());
|
||||
}
|
||||
|
||||
|
||||
// Plugin and translator factory
|
||||
AmrPlugin::AmrPlugin()
|
||||
{
|
||||
Output("Loaded module AMR-NB codec - based on 3GPP code");
|
||||
const FormatInfo* f = FormatRepository::addFormat("amr",0,20000);
|
||||
caps[0].src = caps[1].dest = f;
|
||||
caps[0].dest = caps[1].src = FormatRepository::getFormat("slin");
|
||||
// FIXME: put proper conversion costs
|
||||
caps[0].cost = caps[1].cost = 5;
|
||||
}
|
||||
|
||||
AmrPlugin::~AmrPlugin()
|
||||
{
|
||||
Output("Unloading module AMR-NB with %d codecs still in use",count);
|
||||
}
|
||||
|
||||
bool AmrPlugin::isBusy() const
|
||||
{
|
||||
return (count != 0);
|
||||
}
|
||||
|
||||
// Create transcoder instance for requested formats
|
||||
DataTranslator* AmrPlugin::create(const DataFormat& sFormat, const DataFormat& dFormat)
|
||||
{
|
||||
if (sFormat == "slin" && dFormat == "amr")
|
||||
return new AmrEncoder(sFormat,dFormat,s_discontinuous);
|
||||
else if (sFormat == "amr" && dFormat == "slin")
|
||||
return new AmrDecoder(sFormat,dFormat);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
const TranslatorCaps* AmrPlugin::getCapabilities() const
|
||||
{
|
||||
return caps;
|
||||
}
|
||||
|
||||
|
||||
INIT_PLUGIN(AmrPlugin);
|
||||
|
||||
UNLOAD_PLUGIN(unloadNow)
|
||||
{
|
||||
if (unloadNow)
|
||||
return !__plugin.isBusy();
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // anonymous namespace
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
|
@ -412,7 +412,11 @@ chmod +x %{local_find_requires} %{local_find_provides}
|
|||
%endif
|
||||
|
||||
%build
|
||||
./configure --prefix=%{prefix} --sysconfdir=%{_sysconfdir} --datadir=%{_datadir} --includedir=%{_includedir} --libdir=%{_libdir} --mandir=%{_mandir} --with-archlib=%{_lib} --without-libspeex --without-spandsp --without-coredumper
|
||||
./configure --prefix=%{prefix} --sysconfdir=%{_sysconfdir} \
|
||||
--datadir=%{_datadir} --includedir=%{_includedir} \
|
||||
--libdir=%{_libdir} --mandir=%{_mandir} --with-archlib=%{_lib} \
|
||||
--without-libspeex --without-amrnb \
|
||||
--without-spandsp --without-coredumper
|
||||
make strip
|
||||
|
||||
%install
|
||||
|
@ -428,6 +432,9 @@ rm -rf %{buildroot}
|
|||
|
||||
|
||||
%changelog
|
||||
* Thu May 15 2008 Paul Chitescu <paulc@voip.null.ro>
|
||||
- Disabled the newly added AMR-NB from building
|
||||
|
||||
* Mon Jan 07 2008 Paul Chitescu <paulc@voip.null.ro>
|
||||
- Added Qt client
|
||||
|
||||
|
|
Loading…
Reference in New Issue