From 4a641d9b2597ac8cfd77de5451bdc97402efbe60 Mon Sep 17 00:00:00 2001 From: paulc Date: Fri, 21 Sep 2012 10:38:19 +0000 Subject: [PATCH] Fixed timestamps in AMR when transcoding from non-20ms packetization. Added setting for initial AMR mode. git-svn-id: http://yate.null.ro/svn/yate/trunk@5278 acf43c95-373e-0410-b603-e72c3f656dc1 --- conf.d/amrnbcodec.conf.sample | 10 +++++ modules/amrnbcodec.cpp | 74 ++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 conf.d/amrnbcodec.conf.sample diff --git a/conf.d/amrnbcodec.conf.sample b/conf.d/amrnbcodec.conf.sample new file mode 100644 index 00000000..7652c129 --- /dev/null +++ b/conf.d/amrnbcodec.conf.sample @@ -0,0 +1,10 @@ +[general] +; Initial settings for each created codec + +; mode: int: AMR mode to use by default +; Allowed values are 0-7 or the following keywords (not real numbers!) +; 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.2, 12.2 +;mode=12.2 + +; discontinuous: bool: Use DTX (Discontinuous Transmission) frames +;discontinuous=no diff --git a/modules/amrnbcodec.cpp b/modules/amrnbcodec.cpp index 9ed0e231..21de6e01 100644 --- a/modules/amrnbcodec.cpp +++ b/modules/amrnbcodec.cpp @@ -56,12 +56,19 @@ namespace { // anonymous // Maximum number of frames we are willing to decode in a packet #define MAX_PKT_FRAMES 4 +// Discontinuous Transmission (DTX) +static bool s_discontinuous = false; + +// Default mode +static Mode s_mode = MR122; + + class AmrPlugin : public Plugin, public TranslatorFactory { public: AmrPlugin(); ~AmrPlugin(); - virtual void initialize() {} + virtual void initialize(); virtual bool isBusy() const; virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat); virtual const TranslatorCaps* getCapabilities() const; @@ -70,7 +77,7 @@ public: class AmrTrans : public DataTranslator { public: - AmrTrans(const char* sFormat, const char* dFormat, void* amrState, bool octetAlign = false); + AmrTrans(const char* sFormat, const char* dFormat, void* amrState, bool octetAlign, bool encoding); virtual ~AmrTrans(); virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags); inline bool valid() const @@ -82,6 +89,7 @@ protected: virtual bool pushData(unsigned long& tStamp) = 0; void* m_amrState; DataBlock m_data; + bool m_encoding; bool m_showError; bool m_octetAlign; Mode m_cmr; @@ -92,10 +100,11 @@ class AmrEncoder : public AmrTrans { public: inline AmrEncoder(const char* sFormat, const char* dFormat, bool octetAlign, bool discont = false) - : AmrTrans(sFormat,dFormat,::Encoder_Interface_init(discont ? 1 : 0),octetAlign), - m_mode(MR122) + : AmrTrans(sFormat,dFormat,::Encoder_Interface_init(discont ? 1 : 0),octetAlign,true), + m_mode(s_mode) { } virtual ~AmrEncoder(); + virtual bool control(NamedList& params); protected: virtual bool pushData(unsigned long& tStamp); Mode m_mode; @@ -106,7 +115,7 @@ class AmrDecoder : public AmrTrans { public: inline AmrDecoder(const char* sFormat, const char* dFormat, bool octetAlign) - : AmrTrans(sFormat,dFormat,::Decoder_Interface_init(),octetAlign) + : AmrTrans(sFormat,dFormat,::Decoder_Interface_init(),octetAlign,false) { } virtual ~AmrDecoder(); protected: @@ -130,8 +139,18 @@ static int modeBits[16] = { -1, -1, -1, -1, -1, -1, 0 }; -// Discontinuous Transmission (DTX) -bool s_discontinuous = false; +// Table for bitrate to mode conversion +static const TokenDict s_modes[] = { + { "4.75", MR475 }, + { "5.15", MR515 }, + { "5.90", MR59 }, + { "6.70", MR67 }, + { "7.40", MR74 }, + { "7.95", MR795 }, + { "10.2", MR102 }, + { "12.2", MR122 }, + { 0, 0 } +}; // 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) @@ -159,13 +178,13 @@ static int getBits(unsigned const char*& ptr, int& len, int& bpos, unsigned char // Arbitrary type transcoder constructor -AmrTrans::AmrTrans(const char* sFormat, const char* dFormat, void* amrState, bool octetAlign) +AmrTrans::AmrTrans(const char* sFormat, const char* dFormat, void* amrState, bool octetAlign, bool encoding) : DataTranslator(sFormat,dFormat), - m_amrState(amrState), m_showError(true), - m_octetAlign(octetAlign), m_cmr(MR122) + m_amrState(amrState), m_encoding(encoding), m_showError(true), + m_octetAlign(octetAlign), m_cmr(s_mode) { - Debug(MODNAME,DebugAll,"AmrTrans::AmrTrans('%s','%s',%p,%s) [%p]", - sFormat,dFormat,amrState,String::boolText(octetAlign),this); + Debug(MODNAME,DebugAll,"AmrTrans::AmrTrans('%s','%s',%p,%s,%s) [%p]", + sFormat,dFormat,amrState,String::boolText(octetAlign),String::boolText(encoding),this); count++; } @@ -185,9 +204,9 @@ unsigned long AmrTrans::Consume(const DataBlock& data, unsigned long tStamp, uns if (data.null() && (flags & DataSilent)) return getTransSource()->Forward(data,tStamp,flags); ref(); + if (m_encoding && (tStamp != invalidStamp()) && !m_data.null()) + tStamp -= (m_data.length() / 2); m_data += data; - if (!tStamp) - tStamp = timeStamp() + SAMPLES_FRAME; while (pushData(tStamp)) ; deref(); @@ -261,6 +280,23 @@ bool AmrEncoder::pushData(unsigned long& tStamp) return (0 != m_data.length()); } +// Execute control operations +bool AmrEncoder::control(NamedList& params) +{ + bool ok = false; + int mode = params[YSTRING("mode")].toInteger(s_modes,-1); + if (mode >= MR475 && mode <= MR122) { + m_mode = (Mode)mode; + ok = true; + } + mode = params[YSTRING("cmr")].toInteger(s_modes,-1); + if (mode >= MR475 && mode <= MR122) { + m_cmr = (Mode)mode; + ok = true; + } + return AmrTrans::control(params) || ok; +} + // Decoder cleanup AmrDecoder::~AmrDecoder() @@ -405,6 +441,16 @@ const TranslatorCaps* AmrPlugin::getCapabilities() const return caps; } +void AmrPlugin::initialize() +{ + Output("Initializing module AMR-NB"); + Configuration cfg(Engine::configFile("amrnbcodec")); + int mode = cfg.getIntValue("general","mode",s_modes,MR122); + if (mode >= MR475 && mode <= MR122) + s_mode = (Mode)mode; + s_discontinuous = cfg.getBoolValue("general","discontinuous",false); +} + INIT_PLUGIN(AmrPlugin);