Added support for setting AMR and other codecs' parameters in SDP.
Build and package separately the AMR-NB and GSM-EFR codecs. git-svn-id: http://yate.null.ro/svn/yate/trunk@6151 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
0b184401a3
commit
09ff4188b9
|
@ -6,5 +6,14 @@
|
|||
; 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.2, 12.2
|
||||
;mode=12.2
|
||||
|
||||
; mode-set: list: Allowed encoder set of AMR modes
|
||||
;mode-set=0,1,2,3,4,5,6,7
|
||||
|
||||
; mode-change-neighbor: bool: Only perform change to the neighbor mode in the set
|
||||
;mode-change-neighbor=false
|
||||
|
||||
; mode-change-period: int: Frame block period at which mode changes are allowed
|
||||
;mode-change-period=1
|
||||
|
||||
; discontinuous: bool: Use DTX (Discontinuous Transmission) frames
|
||||
;discontinuous=no
|
||||
|
|
|
@ -416,6 +416,9 @@
|
|||
; gsm: bool: European GSM 06.10 (GSM/8000)
|
||||
;gsm=default
|
||||
|
||||
; gsm-efr: bool: European GSM 06.60 (GSM-EFR/8000)
|
||||
;gsm-efr=default
|
||||
|
||||
; lpc10: bool: Linear Prediction Codec (LPC/8000)
|
||||
;lpc10=default
|
||||
|
||||
|
|
|
@ -535,6 +535,11 @@ bool DataSource::valid() const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DataSource::control(NamedList& params)
|
||||
{
|
||||
return m_translator && m_translator->control(params);
|
||||
}
|
||||
|
||||
unsigned long DataSource::Forward(const DataBlock& data, unsigned long tStamp, unsigned long flags)
|
||||
{
|
||||
Lock mylock(this,100000);
|
||||
|
@ -1053,10 +1058,12 @@ bool DataEndpoint::clearData(DataNode* node)
|
|||
bool DataEndpoint::control(NamedList& params)
|
||||
{
|
||||
// TODO how do we handle this case????? operation-status
|
||||
DataSource* peerSrc = m_consumer ? m_consumer->getConnSource() : 0;
|
||||
return (m_source && m_source->control(params)) ||
|
||||
(m_consumer && m_consumer->control(params)) ||
|
||||
(m_peerRecord && m_peerRecord->control(params)) ||
|
||||
(m_callRecord && m_callRecord->control(params));
|
||||
(m_callRecord && m_callRecord->control(params)) ||
|
||||
(peerSrc && peerSrc->control(params));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1578,6 +1585,8 @@ bool DataTranslator::attachChain(DataSource* source, DataConsumer* consumer, boo
|
|||
DataTranslator* trans = trans2->getFirstTranslator();
|
||||
trans2->getTransSource()->attach(consumer,override);
|
||||
source->attach(trans);
|
||||
trans->attached(true);
|
||||
trans2->attached(true);
|
||||
trans->deref();
|
||||
retv = true;
|
||||
}
|
||||
|
@ -1773,6 +1782,7 @@ DataTranslator* ChainedFactory::create(const DataFormat& sFormat, const DataForm
|
|||
// trans2 may be a chain itself so find the first translator
|
||||
DataTranslator* trans1 = trans2->getFirstTranslator();
|
||||
trans->getTransSource()->attach(trans1);
|
||||
trans1->attached(true);
|
||||
trans1->deref();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -229,8 +229,8 @@ ObjList* SDPParser::parse(const MimeSdpBody& sdp, String& addr, ObjList* oldMedi
|
|||
}
|
||||
else if (line.startSkip("fmtp:",false)) {
|
||||
int num = var - 1;
|
||||
line >> num >> " ";
|
||||
if (num == var) {
|
||||
line >> num;
|
||||
if ((num == var) && line.trimSpaces()) {
|
||||
if (line.startSkip("mode=",false))
|
||||
line >> mode;
|
||||
else if (line.startSkip("annexb=",false))
|
||||
|
@ -240,6 +240,8 @@ ObjList* SDPParser::parse(const MimeSdpBody& sdp, String& addr, ObjList* oldMedi
|
|||
line >> val;
|
||||
amrOctet = (0 != val);
|
||||
}
|
||||
else
|
||||
dest = dest->append(new NamedString("fmtp:" + payload,line));
|
||||
}
|
||||
}
|
||||
else if (first) {
|
||||
|
|
|
@ -202,10 +202,10 @@ bool SDPSession::startRtp(RefObject* context)
|
|||
}
|
||||
|
||||
// Update from parameters. Build a default SDP if no media is found in params
|
||||
bool SDPSession::updateSDP(const NamedList& params)
|
||||
bool SDPSession::updateSDP(const NamedList& params, bool defaults)
|
||||
{
|
||||
DDebug(m_enabler,DebugAll,"SDPSession::updateSdp('%s') [%p]",params.c_str(),m_ptr);
|
||||
bool defaults = true;
|
||||
DDebug(m_enabler,DebugAll,"SDPSession::updateSdp('%s',%s) [%p]",
|
||||
params.c_str(),String::boolText(defaults),m_ptr);
|
||||
const char* sdpPrefix = params.getValue("osdp-prefix","osdp");
|
||||
ObjList* lst = 0;
|
||||
unsigned int n = params.length();
|
||||
|
@ -215,7 +215,7 @@ bool SDPSession::updateSDP(const NamedList& params)
|
|||
const NamedString* p = params.getParam(i);
|
||||
if (!p)
|
||||
continue;
|
||||
// search for rtp_port or rtp_port_MEDIANAME parameters
|
||||
// search for media or media_MEDIANAME parameters
|
||||
String tmp(p->name());
|
||||
if (!tmp.startSkip("media",false))
|
||||
continue;
|
||||
|
@ -257,12 +257,14 @@ bool SDPSession::updateSDP(const NamedList& params)
|
|||
}
|
||||
rtp->crypto(crypto,false);
|
||||
if (sdpPrefix) {
|
||||
String prefix;
|
||||
prefix << sdpPrefix << rtp->suffix() << "_";
|
||||
for (unsigned int j = 0; j < n; j++) {
|
||||
const NamedString* param = params.getParam(j);
|
||||
if (!param)
|
||||
continue;
|
||||
tmp = param->name();
|
||||
if (tmp.startSkip(sdpPrefix + rtp->suffix() + "_",false) && (tmp.find('_') < 0))
|
||||
if (tmp.startSkip(prefix,false) && (tmp.find('_') < 0))
|
||||
rtp->parameter(tmp,*param,append);
|
||||
}
|
||||
}
|
||||
|
@ -473,16 +475,22 @@ MimeSdpBody* SDPSession::createSDP(const char* addr, ObjList* mediaList)
|
|||
((0 != l->find("g729b")) ? "yes" : "no");
|
||||
dest = dest->append(temp);
|
||||
}
|
||||
else if (*s == "amr") {
|
||||
else if (*s == "amr" || s->startsWith("amr/")) {
|
||||
temp = new String("fmtp:");
|
||||
*temp << payload << " octet-align=0";
|
||||
dest = dest->append(temp);
|
||||
}
|
||||
else if (*s == "amr-o") {
|
||||
else if (*s == "amr-o" || s->startsWith("amr-o/")) {
|
||||
temp = new String("fmtp:");
|
||||
*temp << payload << " octet-align=1";
|
||||
dest = dest->append(temp);
|
||||
}
|
||||
const String* fmtp = m->getParam("fmtp:" + *s);
|
||||
if (fmtp) {
|
||||
temp = new String("fmtp:");
|
||||
*temp << payload << " " << *fmtp;
|
||||
dest = dest->append(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +534,7 @@ MimeSdpBody* SDPSession::createSDP(const char* addr, ObjList* mediaList)
|
|||
unsigned int n = m->length();
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
const NamedString* param = m->getParam(i);
|
||||
if (param) {
|
||||
if (param && (param->name().find(':') < 0)) {
|
||||
const char* type = "a";
|
||||
String tmp = param->name();
|
||||
if (tmp.startSkip("BW-",false)) {
|
||||
|
@ -625,7 +633,7 @@ void SDPSession::updateFormats(const NamedList& msg, bool changeMedia)
|
|||
const NamedString* p = msg.getParam(i);
|
||||
if (!p)
|
||||
continue;
|
||||
// search for media_MEDIANAME parameters
|
||||
// search for media or media_MEDIANAME parameters
|
||||
String tmp = p->name();
|
||||
if (!tmp.startSkip("media",false))
|
||||
continue;
|
||||
|
|
|
@ -443,11 +443,12 @@ public:
|
|||
bool startRtp(RefObject* context = 0);
|
||||
|
||||
/**
|
||||
* Update from parameters. Build a default SDP from parser formats if no media is found in params
|
||||
* Update from parameters and optionally build a default SDP.
|
||||
* @param params List of parameters to update from
|
||||
* @param defaults Build a default SDP from parser formats if no media is found in params
|
||||
* @return True if media changed
|
||||
*/
|
||||
bool updateSDP(const NamedList& params);
|
||||
bool updateSDP(const NamedList& params, bool defaults = true);
|
||||
|
||||
/**
|
||||
* Update RTP/SDP data from parameters
|
||||
|
|
|
@ -56,6 +56,15 @@ namespace { // anonymous
|
|||
// Discontinuous Transmission (DTX)
|
||||
static bool s_discontinuous = false;
|
||||
|
||||
// Change mode only to neighbor
|
||||
static bool s_neighbor = false;
|
||||
|
||||
// Mode change period in frames
|
||||
static uint8_t s_period = 1;
|
||||
|
||||
// Supported modes mask
|
||||
static uint8_t s_mask = 0xff;
|
||||
|
||||
// Default mode
|
||||
static Mode s_mode = MR122;
|
||||
|
||||
|
@ -84,6 +93,7 @@ public:
|
|||
protected:
|
||||
void filterBias(short* buf, unsigned int len);
|
||||
bool dataError(const char* text = 0);
|
||||
void setMode(Mode mode);
|
||||
virtual bool pushData(unsigned long& tStamp, unsigned long& flags) = 0;
|
||||
void* m_amrState;
|
||||
DataBlock m_data;
|
||||
|
@ -100,13 +110,21 @@ 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,true),
|
||||
m_mode(s_mode), m_silent(false)
|
||||
m_mode(s_mode), m_desired(s_mode), m_change(0), m_mask(s_mask),
|
||||
m_period(s_period), m_neighbor(false), m_silent(false)
|
||||
{ }
|
||||
virtual ~AmrEncoder();
|
||||
virtual bool control(NamedList& params);
|
||||
protected:
|
||||
void setMode(Mode mode);
|
||||
virtual void attached(bool added);
|
||||
virtual bool pushData(unsigned long& tStamp, unsigned long& flags);
|
||||
Mode m_mode;
|
||||
Mode m_desired;
|
||||
int m_change;
|
||||
uint8_t m_mask;
|
||||
uint8_t m_period;
|
||||
bool m_neighbor;
|
||||
bool m_silent;
|
||||
};
|
||||
|
||||
|
@ -152,6 +170,77 @@ static const TokenDict s_modes[] = {
|
|||
{ 0, 0 }
|
||||
};
|
||||
|
||||
// Helper function, parses a mode-set string to a bit mask
|
||||
static uint8_t parseMask(const String& modes, uint8_t defMask = 0xff)
|
||||
{
|
||||
if (modes.null())
|
||||
return defMask;
|
||||
uint8_t mask = 0;
|
||||
ObjList* lst = modes.split(',',false);
|
||||
for (ObjList* l = lst->skipNull(); l; l = l->skipNext()) {
|
||||
int mode = static_cast<const String*>(l->get())->toInteger(s_modes,-1);
|
||||
if (mode >= MR475 && mode <= MR122)
|
||||
mask |= (1 << mode);
|
||||
}
|
||||
TelEngine::destruct(lst);
|
||||
return mask ? mask : defMask;
|
||||
}
|
||||
|
||||
// Helper function, parses a possibly NULL mode-set string pointer
|
||||
inline static uint8_t parseMask(const String* modes, uint8_t defMask = 0xff)
|
||||
{
|
||||
return modes ? parseMask(*modes) : defMask;
|
||||
}
|
||||
|
||||
// Helper function returning nearest allowed mode
|
||||
static Mode getMode(int mode, uint8_t mask, int oldMode)
|
||||
{
|
||||
if (mode < MR475)
|
||||
mode = MR475;
|
||||
else if (mode > MR122)
|
||||
mode = MR122;
|
||||
if (mask & (1 << mode))
|
||||
return (Mode)mode;
|
||||
if (oldMode > mode) {
|
||||
for (int m = mode + 1; m <= MR122; m++)
|
||||
if (mask & (1 << m))
|
||||
return (Mode)m;
|
||||
}
|
||||
while (--mode >= MR475)
|
||||
if (mask & (1 << mode))
|
||||
return (Mode)mode;
|
||||
return (Mode)oldMode;
|
||||
}
|
||||
|
||||
// Helper function returning nearest neighbor allowed mode
|
||||
static Mode getNeighbor(int mode, uint8_t mask, int oldMode)
|
||||
{
|
||||
if (mode < MR475)
|
||||
mode = MR475;
|
||||
else if (mode > MR122)
|
||||
mode = MR122;
|
||||
if (mode == oldMode)
|
||||
return (Mode)mode;
|
||||
int m;
|
||||
if (oldMode < mode) {
|
||||
for (m = oldMode + 1; m <= mode; m++) {
|
||||
if (mask & (1 << m))
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (m = oldMode - 1; m >= mode; m--) {
|
||||
if (mask & (1 << m))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m < MR475)
|
||||
m = MR475;
|
||||
else if (m > MR122)
|
||||
m = MR122;
|
||||
return (Mode)m;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -267,6 +356,19 @@ bool AmrEncoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
if (m_data.length() < BUFFER_SIZE)
|
||||
return false;
|
||||
|
||||
if ((m_mode != m_desired) && (--m_change <= 0)) {
|
||||
Mode mode = m_neighbor
|
||||
? getNeighbor(m_desired,m_mask,m_mode)
|
||||
: getMode(m_desired,m_mask,m_mode);
|
||||
if (mode == m_mode)
|
||||
m_desired = mode;
|
||||
else {
|
||||
DDebug(MODNAME,DebugAll,"Encode mode changing %d -> %d, desired %d",m_mode,mode,m_desired);
|
||||
m_mode = mode;
|
||||
m_change = (mode == m_desired) ? 0 : m_period;
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
|
@ -284,7 +386,7 @@ bool AmrEncoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
m_silent = silent;
|
||||
unpacked[len] = 0;
|
||||
XDebug(MODNAME,DebugAll,"Encoded mode %d frame to %d bytes first %02x [%p]",
|
||||
m_mode,len,unpacked[0],this);
|
||||
mode,len,unpacked[0],this);
|
||||
unsigned char buffer[MAX_AMRNB_SIZE];
|
||||
// build a TOC with just one entry
|
||||
if (m_octetAlign) {
|
||||
|
@ -307,6 +409,11 @@ bool AmrEncoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
buffer[i] = leftover | (unpacked[i] >> 2);
|
||||
leftover = (unpacked[i] << 6) & 0xc0;
|
||||
}
|
||||
switch (modeBits[mode] & 7) {
|
||||
case 0:
|
||||
case 7:
|
||||
buffer[len++] = leftover;
|
||||
}
|
||||
}
|
||||
m_data.cut(-BUFFER_SIZE);
|
||||
DataBlock outData(buffer,len,false);
|
||||
|
@ -314,19 +421,35 @@ bool AmrEncoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
outData.clear(false);
|
||||
tStamp += SAMPLES_FRAME;
|
||||
flags &= ~DataMark;
|
||||
m_showError = true;
|
||||
return (0 != m_data.length());
|
||||
}
|
||||
|
||||
// Change the desired mode
|
||||
void AmrEncoder::setMode(Mode mode)
|
||||
{
|
||||
m_desired = mode;
|
||||
if (m_period)
|
||||
m_change = m_period;
|
||||
else
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
// Execute control operations
|
||||
bool AmrEncoder::control(NamedList& params)
|
||||
{
|
||||
bool ok = false;
|
||||
int mode = params[YSTRING("mode")].toInteger(s_modes,-1);
|
||||
int mode = params.getIntValue(YSTRING("mode"),s_modes,-1);
|
||||
if (mode >= MR475 && mode <= MR122) {
|
||||
m_mode = (Mode)mode;
|
||||
if (params.getBoolValue(YSTRING("force"))) {
|
||||
m_mode = m_desired = (Mode)mode;
|
||||
m_change = 0;
|
||||
}
|
||||
else
|
||||
setMode(getMode(mode,m_mask,m_desired));
|
||||
ok = true;
|
||||
}
|
||||
mode = params[YSTRING("cmr")].toInteger(s_modes,-1);
|
||||
mode = params.getIntValue(YSTRING("cmr"),s_modes,-1);
|
||||
if (mode >= MR475 && mode <= MR122) {
|
||||
m_cmr = (Mode)mode;
|
||||
ok = true;
|
||||
|
@ -334,6 +457,32 @@ bool AmrEncoder::control(NamedList& params)
|
|||
return TelEngine::controlReturn(¶ms,AmrTrans::control(params) || ok);
|
||||
}
|
||||
|
||||
// Callback to pick AMR parameters from consumer (typically RTP)
|
||||
void AmrEncoder::attached(bool added)
|
||||
{
|
||||
AmrTrans::attached(added);
|
||||
if (!added)
|
||||
return;
|
||||
ObjList* lst = getConsumers();
|
||||
if (!lst)
|
||||
return;
|
||||
RefPointer<DataConsumer> cons = static_cast<DataConsumer*>(lst->get());
|
||||
if (!cons)
|
||||
return;
|
||||
const DataFormat& fmt = cons->getFormat();
|
||||
m_mask = parseMask(fmt[YSTRING("mode-set")],s_mask);
|
||||
m_neighbor = fmt.getIntValue(YSTRING("mode-change-neighbor"),0) != 0;
|
||||
int tmp = fmt.getIntValue(YSTRING("mode-change-period"),s_period);
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
else if (tmp > 4)
|
||||
tmp = 4;
|
||||
m_period = (uint8_t)tmp;
|
||||
Debug(MODNAME,DebugAll,"AmrEncoder picked mask=0x%02X neigh=%s period=%d [%p]",
|
||||
m_mask,String::boolText(m_neighbor),tmp,this);
|
||||
setMode(getMode(m_mode,m_mask,m_desired));
|
||||
}
|
||||
|
||||
|
||||
// Decoder cleanup
|
||||
AmrDecoder::~AmrDecoder()
|
||||
|
@ -350,9 +499,13 @@ bool AmrDecoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
return false;
|
||||
unsigned const char* ptr = (unsigned const char*)m_data.data();
|
||||
int len = m_data.length();
|
||||
bool octetHint = m_octetAlign;
|
||||
// an octet aligned packet should have 0 in the 4 reserved bits of CMR
|
||||
// and in the lower 2 bits of first TOC entry octet
|
||||
bool octetHint = ((ptr[0] & 0x0f) | (ptr[1] & 0x03)) == 0;
|
||||
if ((ptr[0] & 0x0f) | (ptr[1] & 0x03))
|
||||
octetHint = false;
|
||||
else if (((ptr[1] & 0xc0) == 0) && (len > 14))
|
||||
octetHint = true;
|
||||
if (octetHint != m_octetAlign) {
|
||||
Debug(MODNAME,DebugNote,"Decoder switching from %s to %s mode [%p]",
|
||||
alignName(m_octetAlign),alignName(octetHint),this);
|
||||
|
@ -428,6 +581,7 @@ bool AmrDecoder::pushData(unsigned long& tStamp, unsigned long& flags)
|
|||
m_cmr = (Mode)cmr;
|
||||
// TODO: find and notify paired encoder about the mode change request
|
||||
}
|
||||
m_showError = true;
|
||||
return (0 != m_data.length());
|
||||
}
|
||||
|
||||
|
@ -483,10 +637,16 @@ 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_mask = parseMask(cfg.getKey("general","mode-set"));
|
||||
s_mode = getMode(cfg.getIntValue("general","mode",s_modes,MR122),s_mask,MR122);
|
||||
s_discontinuous = cfg.getBoolValue("general","discontinuous",false);
|
||||
s_neighbor = cfg.getBoolValue("general","mode-change-neighbor",false);
|
||||
int tmp = cfg.getIntValue("general","mode-change-period",1);
|
||||
if (tmp < 0)
|
||||
tmp = 0;
|
||||
else if (tmp > 4)
|
||||
tmp = 4;
|
||||
s_period = tmp;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ private:
|
|||
bool startSRTP(const String& suite, const String& keyParams, const ObjList* paramList);
|
||||
bool setupUDPTL(Message& msg);
|
||||
void setTimeout(const Message& msg, int timeOut);
|
||||
static void setFormat(DataFormat& dest, const char* format, const NamedList& params);
|
||||
YRTPSession* m_rtp;
|
||||
YUDPTLSession* m_udptl;
|
||||
RTPSession::Direction m_dir;
|
||||
|
@ -620,6 +621,31 @@ void YRTPWrapper::setTimeout(const Message& msg, int timeOut)
|
|||
session()->setTimeout(timeOut);
|
||||
}
|
||||
|
||||
void YRTPWrapper::setFormat(DataFormat& dest, const char* format, const NamedList& params)
|
||||
{
|
||||
dest.clearParams();
|
||||
dest = format;
|
||||
const String& fmtp = params["sdp_fmtp:" + dest];
|
||||
if (fmtp.null())
|
||||
return;
|
||||
ObjList* lst = fmtp.split(';');
|
||||
for (ObjList* l = lst->skipNull(); l; l = l->skipNext()) {
|
||||
const String* s = static_cast<const String*>(l->get());
|
||||
int pos = s->find('=');
|
||||
String name;
|
||||
String value;
|
||||
if (pos > 0) {
|
||||
name = s->substr(0,pos);
|
||||
value = s->substr(pos + 1);
|
||||
}
|
||||
else if (pos)
|
||||
name = *s;
|
||||
if (name.trimSpaces())
|
||||
dest.addParam(name,value.trimSpaces());
|
||||
}
|
||||
TelEngine::destruct(lst);
|
||||
}
|
||||
|
||||
bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, Message& msg)
|
||||
{
|
||||
Debug(&splugin,DebugAll,"YRTPWrapper::startRTP(\"%s\",%u) [%p]",raddr,rport,this);
|
||||
|
@ -681,7 +707,7 @@ bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, Message& msg)
|
|||
m_source->ref();
|
||||
m_conn->setSource(0,m_media);
|
||||
}
|
||||
m_source->m_format = format;
|
||||
setFormat(m_source->m_format,format,msg);
|
||||
if (m_conn) {
|
||||
m_conn->setSource(m_source,m_media);
|
||||
m_source->deref();
|
||||
|
@ -692,7 +718,7 @@ bool YRTPWrapper::startRTP(const char* raddr, unsigned int rport, Message& msg)
|
|||
m_consumer->ref();
|
||||
m_conn->setConsumer(0,m_media);
|
||||
}
|
||||
m_consumer->m_format = format;
|
||||
setFormat(m_consumer->m_format,format,msg);
|
||||
m_consumer->setSplitable();
|
||||
if (m_conn) {
|
||||
m_conn->setConsumer(m_consumer,m_media);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
# to disable USB support run rpmbuild --define 'nousb 1'
|
||||
# to disable SCTP support run rpmbuild --define 'nosctp 1'
|
||||
# to disable H.323 support run rpmbuild --define 'noh323 1'
|
||||
# to disable AMR codecs run rpmbuild --define 'noamr 1'
|
||||
# to disable the GUI clients run rpmbuild --define 'nogui 1'
|
||||
# to disable only Zaptel support run rpmbuild --define 'nozap 1'
|
||||
# to disable only TDMV support run rpmbuild --define 'notdm 1'
|
||||
|
@ -22,6 +23,7 @@
|
|||
%{?nousb:%define no_usb 1}
|
||||
%{?nosctp:%define no_sctp 1}
|
||||
%{?noh323:%define no_h323 1}
|
||||
%{?noamr:%define no_amr 1}
|
||||
%{?nogui:%define no_gui 1}
|
||||
%{?nozap:%define no_zaptel 1}
|
||||
%{?notdm:%define no_tdmapi 1}
|
||||
|
@ -283,6 +285,29 @@ provides moderate compression and good voice quality.
|
|||
%{_libdir}/yate/gsmcodec.yate
|
||||
|
||||
|
||||
%if "%{no_amr}" != "1"
|
||||
|
||||
%package amr
|
||||
Summary: GSM-AMR and GSM-EFR audio codecs for Yate
|
||||
Group: Applications/Communication
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description amr
|
||||
GSM-AMR and GSM-EFR audio codecs for Yate. AMR is a multi-rate codec that provides moderate
|
||||
to high compression rate and good voice quality. EFR is just a different payload stucture
|
||||
for 12.2 kbit/s AMR-NB.
|
||||
|
||||
%files amr
|
||||
%{_libdir}/yate/amrnbcodec.yate
|
||||
%{_libdir}/yate/efrcodec.yate
|
||||
%config(noreplace) %{_sysconfdir}/yate/amrnbcodec.conf
|
||||
|
||||
%define conf_amr %{nil}
|
||||
%else
|
||||
%define conf_amr --without-amrnb
|
||||
%endif
|
||||
|
||||
|
||||
%package speex
|
||||
Summary: Speex audio codec for Yate
|
||||
Group: Applications/Communication
|
||||
|
@ -610,6 +635,9 @@ The devel package must still be installed separately.
|
|||
%if "%{no_h323}" == "1"
|
||||
%define _unpackaged_files_terminate_build 0
|
||||
%endif
|
||||
%if "%{no_amr}" == "1"
|
||||
%define _unpackaged_files_terminate_build 0
|
||||
%endif
|
||||
%if "%{no_gui}" == "1"
|
||||
%define _unpackaged_files_terminate_build 0
|
||||
%endif
|
||||
|
@ -654,15 +682,14 @@ chmod +x %{local_find_requires} %{local_find_provides}
|
|||
./configure --prefix=%{prefix} --sysconfdir=%{_sysconfdir} \
|
||||
--datadir=%{_datadir} --includedir=%{_includedir} \
|
||||
--libdir=%{_libdir} --mandir=%{_mandir} --with-archlib=%{_lib} \
|
||||
--without-amrnb \
|
||||
--without-spandsp --without-coredumper \
|
||||
%{conf_sctp} %{conf_h323} %{conf_pstn} %{conf_usb} %{conf_gui} %{?extra_conf}
|
||||
%{conf_sctp} %{conf_h323} %{conf_amr} %{conf_pstn} %{conf_usb} %{conf_gui} \
|
||||
%{?extra_conf}
|
||||
make %{stripped} %{?extra_make}
|
||||
%{?extra_step}
|
||||
|
||||
%install
|
||||
make install DESTDIR=%{buildroot} %{?extra_make}
|
||||
rm %{buildroot}%{_sysconfdir}/yate/amrnbcodec.conf
|
||||
rm %{buildroot}%{_sysconfdir}/yate/radiotest.conf
|
||||
%if "%{systemd}" != "0"
|
||||
mkdir -p %{buildroot}%{_unitdir}
|
||||
|
@ -684,6 +711,9 @@ rm -rf %{buildroot}
|
|||
|
||||
|
||||
%changelog
|
||||
* Fri Nov 25 2016 Paul Chitescu <paulc@voip.null.ro>
|
||||
- Added package for the AMR codec
|
||||
|
||||
* Thu Nov 26 2015 Paul Chitescu <paulc@voip.null.ro>
|
||||
- More tweaking to suppress unwanted dependencies in newer RPM
|
||||
|
||||
|
|
16
yatephone.h
16
yatephone.h
|
@ -373,7 +373,6 @@ public:
|
|||
inline static unsigned long invalidStamp()
|
||||
{ return (unsigned long)-1; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Owner attach and detach notification.
|
||||
* This method is called with @ref DataEndpoint::commonMutex() held
|
||||
|
@ -382,6 +381,7 @@ protected:
|
|||
virtual void attached(bool added)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
DataFormat m_format;
|
||||
unsigned long m_timestamp;
|
||||
};
|
||||
|
@ -505,6 +505,13 @@ public:
|
|||
*/
|
||||
virtual bool valid() const;
|
||||
|
||||
/**
|
||||
* Modify source parameters, calls translator if one is set
|
||||
* @param params The list of parameters to change
|
||||
* @return True if processed
|
||||
*/
|
||||
virtual bool control(NamedList& params);
|
||||
|
||||
/**
|
||||
* Forwards the data to its consumers
|
||||
* @param data The raw data block to forward
|
||||
|
@ -786,6 +793,13 @@ public:
|
|||
static void setMaxChain(unsigned int maxChain);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Get access to the list of consumers of the data source
|
||||
* @return Pointer to list entry of first consumer, NULL if none attached
|
||||
*/
|
||||
inline ObjList* getConsumers() const
|
||||
{ return m_tsource ? m_tsource->m_consumers.skipNull() : 0; }
|
||||
|
||||
/**
|
||||
* Synchronize the consumer with a source
|
||||
* @param source Data source to copy the timestamp from
|
||||
|
|
Loading…
Reference in New Issue