Fixed timestamps in AMR when transcoding from non-20ms packetization.

Added setting for initial AMR mode.


git-svn-id: http://voip.null.ro/svn/yate@5278 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-09-21 10:38:19 +00:00
parent 9fe101f4cd
commit 43c94fe9cd
2 changed files with 70 additions and 14 deletions

View File

@ -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

View File

@ -56,12 +56,19 @@ namespace { // anonymous
// Maximum number of frames we are willing to decode in a packet // Maximum number of frames we are willing to decode in a packet
#define MAX_PKT_FRAMES 4 #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 class AmrPlugin : public Plugin, public TranslatorFactory
{ {
public: public:
AmrPlugin(); AmrPlugin();
~AmrPlugin(); ~AmrPlugin();
virtual void initialize() {} virtual void initialize();
virtual bool isBusy() const; virtual bool isBusy() const;
virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat); virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat);
virtual const TranslatorCaps* getCapabilities() const; virtual const TranslatorCaps* getCapabilities() const;
@ -70,7 +77,7 @@ public:
class AmrTrans : public DataTranslator class AmrTrans : public DataTranslator
{ {
public: 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 ~AmrTrans();
virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags); virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags);
inline bool valid() const inline bool valid() const
@ -82,6 +89,7 @@ protected:
virtual bool pushData(unsigned long& tStamp) = 0; virtual bool pushData(unsigned long& tStamp) = 0;
void* m_amrState; void* m_amrState;
DataBlock m_data; DataBlock m_data;
bool m_encoding;
bool m_showError; bool m_showError;
bool m_octetAlign; bool m_octetAlign;
Mode m_cmr; Mode m_cmr;
@ -92,10 +100,11 @@ class AmrEncoder : public AmrTrans
{ {
public: public:
inline AmrEncoder(const char* sFormat, const char* dFormat, bool octetAlign, bool discont = false) inline AmrEncoder(const char* sFormat, const char* dFormat, bool octetAlign, bool discont = false)
: AmrTrans(sFormat,dFormat,::Encoder_Interface_init(discont ? 1 : 0),octetAlign), : AmrTrans(sFormat,dFormat,::Encoder_Interface_init(discont ? 1 : 0),octetAlign,true),
m_mode(MR122) m_mode(s_mode)
{ } { }
virtual ~AmrEncoder(); virtual ~AmrEncoder();
virtual bool control(NamedList& params);
protected: protected:
virtual bool pushData(unsigned long& tStamp); virtual bool pushData(unsigned long& tStamp);
Mode m_mode; Mode m_mode;
@ -106,7 +115,7 @@ class AmrDecoder : public AmrTrans
{ {
public: public:
inline AmrDecoder(const char* sFormat, const char* dFormat, bool octetAlign) 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(); virtual ~AmrDecoder();
protected: protected:
@ -130,8 +139,18 @@ static int modeBits[16] = {
-1, -1, -1, -1, -1, -1, 0 -1, -1, -1, -1, -1, -1, 0
}; };
// Discontinuous Transmission (DTX) // Table for bitrate to mode conversion
bool s_discontinuous = false; 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 // 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) 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 // 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), : DataTranslator(sFormat,dFormat),
m_amrState(amrState), m_showError(true), m_amrState(amrState), m_encoding(encoding), m_showError(true),
m_octetAlign(octetAlign), m_cmr(MR122) m_octetAlign(octetAlign), m_cmr(s_mode)
{ {
Debug(MODNAME,DebugAll,"AmrTrans::AmrTrans('%s','%s',%p,%s) [%p]", Debug(MODNAME,DebugAll,"AmrTrans::AmrTrans('%s','%s',%p,%s,%s) [%p]",
sFormat,dFormat,amrState,String::boolText(octetAlign),this); sFormat,dFormat,amrState,String::boolText(octetAlign),String::boolText(encoding),this);
count++; count++;
} }
@ -185,9 +204,9 @@ unsigned long AmrTrans::Consume(const DataBlock& data, unsigned long tStamp, uns
if (data.null() && (flags & DataSilent)) if (data.null() && (flags & DataSilent))
return getTransSource()->Forward(data,tStamp,flags); return getTransSource()->Forward(data,tStamp,flags);
ref(); ref();
if (m_encoding && (tStamp != invalidStamp()) && !m_data.null())
tStamp -= (m_data.length() / 2);
m_data += data; m_data += data;
if (!tStamp)
tStamp = timeStamp() + SAMPLES_FRAME;
while (pushData(tStamp)) while (pushData(tStamp))
; ;
deref(); deref();
@ -261,6 +280,23 @@ bool AmrEncoder::pushData(unsigned long& tStamp)
return (0 != m_data.length()); 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 // Decoder cleanup
AmrDecoder::~AmrDecoder() AmrDecoder::~AmrDecoder()
@ -405,6 +441,16 @@ const TranslatorCaps* AmrPlugin::getCapabilities() const
return caps; 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); INIT_PLUGIN(AmrPlugin);