Added timestamps to the data channels and external RTP support for h323chan.
git-svn-id: http://voip.null.ro/svn/yate@68 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
b45ac35d1b
commit
eba2c99999
|
@ -36,13 +36,13 @@ class SimpleTranslator : public DataTranslator
|
|||
public:
|
||||
SimpleTranslator(const String &sFormat, const String &dFormat)
|
||||
: DataTranslator(sFormat,dFormat) { }
|
||||
virtual void Consume(const DataBlock &data)
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
ref();
|
||||
if (getTransSource()) {
|
||||
DataBlock oblock;
|
||||
if (oblock.convert(data, m_format, getTransSource()->getFormat()))
|
||||
getTransSource()->Forward(oblock);
|
||||
getTransSource()->Forward(oblock, timeDelta);
|
||||
}
|
||||
deref();
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ bool DataBlock::convert(const DataBlock &src, const String &sFormat,
|
|||
return true;
|
||||
}
|
||||
|
||||
void DataSource::Forward(const DataBlock &data)
|
||||
void DataSource::Forward(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
ref();
|
||||
|
@ -254,8 +254,9 @@ void DataSource::Forward(const DataBlock &data)
|
|||
for (; l; l=l->next()) {
|
||||
DataConsumer *c = static_cast<DataConsumer *>(l->get());
|
||||
if (c)
|
||||
c->Consume(data);
|
||||
c->Consume(data,timeDelta);
|
||||
}
|
||||
m_timestamp += timeDelta;
|
||||
deref();
|
||||
}
|
||||
|
||||
|
@ -565,9 +566,13 @@ DataTranslator *DataTranslator::create(const String &sFormat, const String &dFor
|
|||
if (trans)
|
||||
Debug(DebugAll,"Created DataTranslator [%p] for \"%s\" -> \"%s\"",
|
||||
trans,sFormat.c_str(),dFormat.c_str());
|
||||
else
|
||||
Debug(DebugWarn,"No DataTranslator created for \"%s\" -> \"%s\"",
|
||||
else {
|
||||
int level = DebugWarn;
|
||||
if (sFormat.null() || dFormat.null())
|
||||
level = DebugInfo;
|
||||
Debug(level,"No DataTranslator created for \"%s\" -> \"%s\"",
|
||||
sFormat.c_str(),dFormat.c_str());
|
||||
}
|
||||
return trans;
|
||||
}
|
||||
|
||||
|
@ -604,18 +609,16 @@ bool DataTranslator::detachChain(DataSource *source, DataConsumer *consumer)
|
|||
if (!source || !consumer)
|
||||
return false;
|
||||
|
||||
if (source->detach(consumer))
|
||||
return true;
|
||||
|
||||
DataSource *tsource = consumer->getConnSource();
|
||||
if (tsource) {
|
||||
if (source->detach(consumer))
|
||||
return true;
|
||||
DataTranslator *trans = tsource->getTranslator();
|
||||
if (trans && detachChain(source,trans)) {
|
||||
trans->deref();
|
||||
return true;
|
||||
}
|
||||
Debug(DebugWarn,"DataTranslator failed to detach chain [%p] -> [%p]",source,consumer);
|
||||
}
|
||||
|
||||
Debug(DebugWarn,"DataTranslator failed to detach chain [%p] -> [%p]",source,consumer);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ bool EngineStatusHandler::received(Message &msg)
|
|||
return false;
|
||||
msg.retValue() << "engine";
|
||||
msg.retValue() << ",plugins=" << plugins.count();
|
||||
msg.retValue() << ",threads=" << Thread::count();
|
||||
msg.retValue() << ",workers=" << EnginePrivate::count;
|
||||
msg.retValue() << "\n";
|
||||
return false;
|
||||
|
|
|
@ -50,7 +50,7 @@ class ExtModConsumer : public DataConsumer
|
|||
public:
|
||||
ExtModConsumer(int fd);
|
||||
~ExtModConsumer();
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timestamp);
|
||||
private:
|
||||
int m_fd;
|
||||
unsigned m_total;
|
||||
|
@ -200,7 +200,7 @@ void ExtModSource::run()
|
|||
#endif
|
||||
::usleep((unsigned long)dly);
|
||||
}
|
||||
Forward(data);
|
||||
Forward(data,m_total);
|
||||
m_total += r;
|
||||
tpos += (r*1000000ULL/m_brate);
|
||||
} while (r > 0);
|
||||
|
@ -223,7 +223,7 @@ ExtModConsumer::~ExtModConsumer()
|
|||
}
|
||||
}
|
||||
|
||||
void ExtModConsumer::Consume(const DataBlock &data)
|
||||
void ExtModConsumer::Consume(const DataBlock &data, unsigned long timestamp)
|
||||
{
|
||||
if ((m_fd >= 0) && !data.null()) {
|
||||
::write(m_fd,data.data(),data.length());
|
||||
|
|
|
@ -39,7 +39,7 @@ class GsmCodec : public DataTranslator
|
|||
public:
|
||||
GsmCodec(const char *sFormat, const char *dFormat, bool encoding);
|
||||
~GsmCodec();
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
private:
|
||||
bool m_encoding;
|
||||
gsm m_gsm;
|
||||
|
@ -66,7 +66,7 @@ GsmCodec::~GsmCodec()
|
|||
}
|
||||
}
|
||||
|
||||
void GsmCodec::Consume(const DataBlock &data)
|
||||
void GsmCodec::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
if (!(m_gsm && getTransSource()))
|
||||
return;
|
||||
|
@ -84,6 +84,7 @@ void GsmCodec::Consume(const DataBlock &data)
|
|||
(gsm_signal*)(((gsm_block *)m_data.data())+i),
|
||||
(gsm_byte*)(((gsm_frame *)outdata.data())+i));
|
||||
}
|
||||
timeDelta = consumed / 2;
|
||||
}
|
||||
else {
|
||||
frames = m_data.length() / sizeof(gsm_frame);
|
||||
|
@ -95,6 +96,7 @@ void GsmCodec::Consume(const DataBlock &data)
|
|||
(gsm_byte*)(((gsm_frame *)m_data.data())+i),
|
||||
(gsm_signal*)(((gsm_block *)outdata.data())+i));
|
||||
}
|
||||
timeDelta = frames*sizeof(gsm_block) / 2;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
Debug("GsmCodec",DebugAll,"%scoding %d frames of %d input bytes (consumed %d) in %d output bytes",
|
||||
|
@ -102,7 +104,7 @@ void GsmCodec::Consume(const DataBlock &data)
|
|||
#endif
|
||||
if (frames) {
|
||||
m_data.cut(-consumed);
|
||||
getTransSource()->Forward(outdata);
|
||||
getTransSource()->Forward(outdata,timeDelta);
|
||||
}
|
||||
deref();
|
||||
}
|
||||
|
|
|
@ -17,12 +17,17 @@
|
|||
#include <ptclib/delaychan.h>
|
||||
#include <gkserver.h>
|
||||
|
||||
/* Define a easily comparable version, 2 digits for each component */
|
||||
#define OPENH323_NUMVERSION ((OPENH323_MAJOR)*10000 + (OPENH323_MINOR)*100 + (OPENH323_BUILD))
|
||||
|
||||
/* Guess if codecs are dynamically loaded or linked in */
|
||||
#if (OPENH323_MAJOR <= 1)
|
||||
#if (OPENH323_MINOR < 13)
|
||||
#if (OPENH323_NUMVERSION < 11300)
|
||||
#define OLD_STYLE_CODECS 1
|
||||
#endif
|
||||
|
||||
/* Guess if we have a QOS parameter to the RTP channel creation */
|
||||
#if (OPENH323_NUMVERSION >= 11304)
|
||||
#define NEED_RTP_QOS_PARAM 1
|
||||
#endif
|
||||
|
||||
#include <telengine.h>
|
||||
|
@ -33,6 +38,10 @@
|
|||
|
||||
using namespace TelEngine;
|
||||
|
||||
static Mutex s_calls;
|
||||
|
||||
static bool s_externalRtp;
|
||||
|
||||
static Configuration s_cfg;
|
||||
static ObjList translate;
|
||||
|
||||
|
@ -43,6 +52,20 @@ static TokenDict dict_str2code[] = {
|
|||
{ 0 , 0 },
|
||||
};
|
||||
|
||||
const char* h323_formats[] = {
|
||||
"G.711-ALaw-64k{sw}", "alaw",
|
||||
"G.711-uLaw-64k{sw}", "mulaw",
|
||||
"GSM-06.10{sw}", "gsm",
|
||||
0
|
||||
};
|
||||
|
||||
static TokenDict dict_h323_dir[] = {
|
||||
{ "receive", H323Channel::IsReceiver },
|
||||
{ "send", H323Channel::IsTransmitter },
|
||||
{ "bidir", H323Channel::IsBidirectional },
|
||||
{ 0 , 0 },
|
||||
};
|
||||
|
||||
class H323Process : public PProcess
|
||||
{
|
||||
PCLASSINFO(H323Process, PProcess)
|
||||
|
@ -128,13 +151,15 @@ public:
|
|||
virtual BOOL Close();
|
||||
virtual BOOL IsOpen() const;
|
||||
virtual BOOL Read(void *buf, PINDEX len);
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
private:
|
||||
DataBlock m_buffer;
|
||||
bool m_exit;
|
||||
Mutex m_mutex;
|
||||
};
|
||||
|
||||
class YateH323_ExternalRTPChannel;
|
||||
|
||||
class YateH323EndPoint : public H323EndPoint
|
||||
{
|
||||
PCLASSINFO(YateH323EndPoint, H323EndPoint)
|
||||
|
@ -162,13 +187,48 @@ public:
|
|||
virtual void OnUserInputString(const PString &value);
|
||||
virtual BOOL OpenAudioChannel(BOOL isEncoding, unsigned bufferSize,
|
||||
H323AudioCodec &codec);
|
||||
#ifdef NEED_RTP_QOS_PARAM
|
||||
H323Channel *CreateRealTimeLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters *param,RTP_QOS * rtpqos = NULL);
|
||||
#else
|
||||
H323Channel *CreateRealTimeLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters *param);
|
||||
#endif
|
||||
BOOL OnStartLogicalChannel(H323Channel & channel);
|
||||
BOOL OnCreateLogicalChannel(const H323Capability & capability, H323Channel::Directions dir, unsigned & errorCode ) ;
|
||||
BOOL StartExternalRTP(const char* remoteIP, WORD remotePort, H323Channel::Directions dir, YateH323_ExternalRTPChannel* chan);
|
||||
void OnStoppedExternal(H323Channel::Directions dir);
|
||||
virtual void disconnected();
|
||||
inline const String &id() const
|
||||
{ return m_id; }
|
||||
private:
|
||||
bool m_nativeRtp;
|
||||
String m_id;
|
||||
};
|
||||
|
||||
// this part have been inspired (more or less) from chan_h323 of project asterisk, credits to Jeremy McNamara for chan_h323 and to Mark Spencer for asterisk.
|
||||
class YateH323_ExternalRTPChannel : public H323_ExternalRTPChannel
|
||||
{
|
||||
PCLASSINFO(YateH323_ExternalRTPChannel, H323_ExternalRTPChannel);
|
||||
public:
|
||||
/* Create a new channel. */
|
||||
YateH323_ExternalRTPChannel(
|
||||
YateH323Connection & connection,
|
||||
const H323Capability & capability,
|
||||
Directions direction,
|
||||
unsigned sessionID,
|
||||
const PIPSocket::Address & ip,
|
||||
WORD dataPort);
|
||||
/* Destructor */
|
||||
~YateH323_ExternalRTPChannel();
|
||||
BOOL Start();
|
||||
|
||||
BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
|
||||
BOOL OnSendingPDU( H245_H2250LogicalChannelParameters & param );
|
||||
BOOL OnReceivedPDU(const H245_H2250LogicalChannelParameters & param,unsigned & errorCode);
|
||||
private:
|
||||
YateH323Connection *m_conn;
|
||||
};
|
||||
|
||||
|
||||
class H323Handler : public MessageHandler
|
||||
{
|
||||
public:
|
||||
|
@ -411,16 +471,17 @@ bool YateH323EndPoint::Init(void)
|
|||
|
||||
YateH323Connection::YateH323Connection(YateH323EndPoint &endpoint,
|
||||
unsigned callReference, void *userdata)
|
||||
: H323Connection(endpoint,callReference), DataEndpoint("h323")
|
||||
: H323Connection(endpoint,callReference), DataEndpoint("h323"), m_nativeRtp(false)
|
||||
{
|
||||
Debug(DebugAll,"YateH323Connection::YateH323Connection(%p,%u,%p) [%p]",
|
||||
&endpoint,callReference,userdata,this);
|
||||
m_id = "h323/";
|
||||
m_id << callReference;
|
||||
/*
|
||||
setSource(new YateH323AudioSource);
|
||||
getSource()->deref();
|
||||
setConsumer(new YateH323AudioConsumer);
|
||||
getConsumer()->deref();
|
||||
getConsumer()->deref();*/
|
||||
DataEndpoint *dd = static_cast<DataEndpoint *>(userdata);
|
||||
if (dd && connect(dd))
|
||||
deref();
|
||||
|
@ -430,7 +491,9 @@ YateH323Connection::YateH323Connection(YateH323EndPoint &endpoint,
|
|||
YateH323Connection::~YateH323Connection()
|
||||
{
|
||||
Debug(DebugAll,"YateH323Connection::~YateH323Connection() [%p]",this);
|
||||
s_calls.lock();
|
||||
hplugin.calls().remove(this,false);
|
||||
s_calls.unlock();
|
||||
CloseAllLogicalChannels(true);
|
||||
CloseAllLogicalChannels(false);
|
||||
}
|
||||
|
@ -454,11 +517,19 @@ H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PStrin
|
|||
|
||||
const H225_Setup_UUIE &setup = setupPDU.m_h323_uu_pdu.m_h323_message_body;
|
||||
const H225_ArrayOf_AliasAddress &adr = setup.m_destinationAddress;
|
||||
s = adr.GetSize() ? (const char *)H323GetAliasAddressString(adr[0]) : 0;
|
||||
if (!(s && *s))
|
||||
s = s_cfg.getValue("incoming","called");
|
||||
if (s)
|
||||
m->addParam("called",s);
|
||||
for (int i = 0; i<adr.GetSize(); i++)
|
||||
Debug(DebugAll,"adr[%d]='%s'",i,(const char *)H323GetAliasAddressString(adr[i]));
|
||||
String called;
|
||||
if (adr.GetSize() > 0)
|
||||
called = (const char *)H323GetAliasAddressString(adr[0]);
|
||||
if (called.null())
|
||||
called = s_cfg.getValue("incoming","called");
|
||||
if (!called.null()) {
|
||||
Debug(DebugInfo,"Called number is '%s'",called.c_str());
|
||||
m->addParam("called",called);
|
||||
}
|
||||
else
|
||||
Debug(DebugWarn,"No called number present!");
|
||||
#if 0
|
||||
s = GetRemotePartyAddress();
|
||||
Debug(DebugInfo,"GetRemotePartyAddress()='%s'",s);
|
||||
|
@ -517,12 +588,28 @@ void YateH323Connection::OnUserInputString(const PString &value)
|
|||
BOOL YateH323Connection::OpenAudioChannel(BOOL isEncoding, unsigned bufferSize,
|
||||
H323AudioCodec &codec)
|
||||
{
|
||||
Debug(DebugInfo,"YateH323Connection::OpenAudioChannel [%p]",this);
|
||||
if (!m_nativeRtp) {
|
||||
Debug(DebugGoOn,"YateH323Connection::OpenAudioChannel for external RTP in [%p]",this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isEncoding) {
|
||||
if (!getConsumer())
|
||||
{
|
||||
setConsumer(new YateH323AudioConsumer);
|
||||
getConsumer()->deref();
|
||||
}
|
||||
// data going TO h.323
|
||||
if (getConsumer())
|
||||
return codec.AttachChannel(static_cast<YateH323AudioConsumer *>(getConsumer()),false);
|
||||
}
|
||||
else {
|
||||
if(!getSource())
|
||||
{
|
||||
setSource(new YateH323AudioSource);
|
||||
getSource()->deref();
|
||||
}
|
||||
// data coming FROM h.323
|
||||
if (getSource())
|
||||
return codec.AttachChannel(static_cast<YateH323AudioSource *>(getSource()),false);
|
||||
|
@ -535,13 +622,176 @@ void YateH323Connection::disconnected()
|
|||
Debugger debug("YateH323Connection::disconnected()");
|
||||
// we must bypass the normal Yate refcounted destruction as OpenH323 will destroy the object
|
||||
ref();
|
||||
if (getSource())
|
||||
if (getSource() && m_nativeRtp)
|
||||
static_cast<YateH323AudioSource *>(getSource())->Close();
|
||||
if (getConsumer())
|
||||
if (getConsumer() && m_nativeRtp)
|
||||
static_cast<YateH323AudioConsumer *>(getConsumer())->Close();
|
||||
ClearCall();
|
||||
}
|
||||
|
||||
#ifdef NEED_RTP_QOS_PARAM
|
||||
H323Channel *YateH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters *param,RTP_QOS * rtpqos)
|
||||
#else
|
||||
H323Channel *YateH323Connection::CreateRealTimeLogicalChannel(const H323Capability & capability,H323Channel::Directions dir,unsigned sessionID,const H245_H2250LogicalChannelParameters *param)
|
||||
#endif
|
||||
{
|
||||
Debug(DebugAll,"H323Connection::CreateRealTimeLogicalChannel");
|
||||
if (s_externalRtp) {
|
||||
const char* sdir = lookup(dir,dict_h323_dir);
|
||||
Debug(DebugInfo,"capability '%s' session %u %s",(const char *)capability.GetFormatName(),sessionID,sdir);
|
||||
PIPSocket::Address externalIpAddress;
|
||||
// GetControlChannel().GetLocalAddress().GetIpAndPort(externalIpAddress, port);
|
||||
GetControlChannel().GetLocalAddress().GetIpAddress(externalIpAddress);
|
||||
Debug(DebugInfo,"address '%s'",(const char *)externalIpAddress.AsString());
|
||||
Message m("rtp");
|
||||
m.addParam("localip",externalIpAddress.AsString());
|
||||
m.userData(static_cast<DataEndpoint *>(this));
|
||||
Debug(DebugAll,"userData=%p this=%p",m.userData(),this);
|
||||
if (sdir)
|
||||
m.addParam("direction",sdir);
|
||||
if (Engine::dispatch(m)) {
|
||||
String p(m.getValue("localport"));
|
||||
WORD externalPort = p.toInteger();
|
||||
if (externalPort) {
|
||||
m_nativeRtp = false;
|
||||
return new YateH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
|
||||
}
|
||||
}
|
||||
Debug(DebugWarn,"YateH323Connection failed to create external RTP, using native");
|
||||
}
|
||||
|
||||
m_nativeRtp = true;
|
||||
#ifdef NEED_RTP_QOS_PARAM
|
||||
return H323Connection::CreateRealTimeLogicalChannel(capability,dir,sessionID,param,rtpqos);
|
||||
#else
|
||||
return H323Connection::CreateRealTimeLogicalChannel(capability,dir,sessionID,param);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL YateH323Connection::OnStartLogicalChannel(H323Channel & channel)
|
||||
{
|
||||
Debug(DebugInfo,"YateH323Connection::OnStartLogicalChannel(%p) [%p]",&channel,this);
|
||||
return m_nativeRtp ? H323Connection::OnStartLogicalChannel(channel) : TRUE;
|
||||
}
|
||||
|
||||
BOOL YateH323Connection::OnCreateLogicalChannel(const H323Capability & capability, H323Channel::Directions dir, unsigned & errorCode )
|
||||
{
|
||||
Debug(DebugInfo,"YateH323Connection::OnCreateLogicalChannel('%s',%d) [%p]",(const char *)capability.GetFormatName(),dir,this);
|
||||
return H323Connection::OnCreateLogicalChannel(capability,dir,errorCode);
|
||||
}
|
||||
|
||||
BOOL YateH323Connection::StartExternalRTP(const char* remoteIP, WORD remotePort, H323Channel::Directions dir, YateH323_ExternalRTPChannel* chan)
|
||||
{
|
||||
const char* sdir = lookup(dir,dict_h323_dir);
|
||||
Debug(DebugAll,"YateH323Connection::StartExternalRTP(\"%s\",%u,%s,%p) [%p]",
|
||||
remoteIP,remotePort,sdir,chan,this);
|
||||
Message m("rtp");
|
||||
m.userData(static_cast<DataEndpoint *>(this));
|
||||
Debug(DebugAll,"userData=%p this=%p",m.userData(),this);
|
||||
if (sdir)
|
||||
m.addParam("direction",sdir);
|
||||
m.addParam("remoteip",remoteIP);
|
||||
m.addParam("remoteport",String(remotePort));
|
||||
String capability((const char *)chan->GetCapability().GetFormatName());
|
||||
// int payload = chan->GetCapability().GetPayloadType();
|
||||
OpalMediaFormat oformat(capability, FALSE);
|
||||
int payload = oformat.GetPayloadType();
|
||||
const char *format = 0;
|
||||
const char** f = h323_formats;
|
||||
for (; *f; f += 2) {
|
||||
if (capability == *f) {
|
||||
format = f[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug(DebugInfo,"capability '%s' format '%s' payload %d",capability.c_str(),format,payload);
|
||||
if (format)
|
||||
m.addParam("format",format);
|
||||
if ((payload >= 0) && (payload < 127))
|
||||
m.addParam("payload",String(payload));
|
||||
if (Engine::dispatch(m)) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void YateH323Connection::OnStoppedExternal(H323Channel::Directions dir)
|
||||
{
|
||||
Debug(DebugInfo,"YateH323Connection::OnStoppedExternal(%s) [%p]",lookup(dir,dict_h323_dir),this);
|
||||
switch (dir) {
|
||||
case H323Channel::IsReceiver:
|
||||
setSource();
|
||||
break;
|
||||
case H323Channel::IsTransmitter:
|
||||
setConsumer();
|
||||
break;
|
||||
case H323Channel::IsBidirectional:
|
||||
setSource();
|
||||
setConsumer();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
YateH323_ExternalRTPChannel::YateH323_ExternalRTPChannel(
|
||||
YateH323Connection & connection,
|
||||
const H323Capability & capability,
|
||||
Directions direction,
|
||||
unsigned sessionID,
|
||||
const PIPSocket::Address & ip,
|
||||
WORD dataPort)
|
||||
: H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort),m_conn(&connection)
|
||||
{
|
||||
Debug(DebugAll,"YateH323_ExternalRTPChannel::YateH323_ExternalRTPChannel dir=%d addr=%s:%u",
|
||||
GetDirection(), (const char *)ip.AsString(), dataPort);
|
||||
SetExternalAddress(H323TransportAddress(ip, dataPort), H323TransportAddress(ip, dataPort+1));
|
||||
}
|
||||
|
||||
YateH323_ExternalRTPChannel::~YateH323_ExternalRTPChannel()
|
||||
{
|
||||
Debug(DebugInfo,"YateH323_ExternalRTPChannel::~YateH323_ExternalRTPChannel [%p]",this);
|
||||
if (isRunning) {
|
||||
isRunning = FALSE;
|
||||
if (m_conn)
|
||||
m_conn->OnStoppedExternal(GetDirection());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL YateH323_ExternalRTPChannel::Start()
|
||||
{
|
||||
Debug(DebugAll,"YateH323_ExternalRTPChannel::Start() [%p]",this);
|
||||
if (!m_conn)
|
||||
return FALSE;
|
||||
|
||||
PIPSocket::Address remoteIpAddress;
|
||||
WORD remotePort;
|
||||
GetRemoteAddress(remoteIpAddress,remotePort);
|
||||
Debug(DebugInfo,"external rtp ip address %s:%u",(const char *)remoteIpAddress.AsString(),remotePort);
|
||||
|
||||
return isRunning = m_conn->StartExternalRTP((const char *)remoteIpAddress.AsString(), remotePort, GetDirection(), this);
|
||||
}
|
||||
|
||||
BOOL YateH323_ExternalRTPChannel::OnReceivedPDU(
|
||||
const H245_H2250LogicalChannelParameters & param,
|
||||
unsigned & errorCode)
|
||||
{
|
||||
Debug(DebugInfo,"OnReceivedPDU");
|
||||
return H323_ExternalRTPChannel::OnReceivedPDU(param,errorCode);
|
||||
}
|
||||
|
||||
BOOL YateH323_ExternalRTPChannel::OnSendingPDU( H245_H2250LogicalChannelParameters & param )
|
||||
{
|
||||
Debug(DebugInfo,"OnSendingPDU");
|
||||
return H323_ExternalRTPChannel::OnSendingPDU(param);
|
||||
}
|
||||
|
||||
BOOL YateH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
|
||||
{
|
||||
|
||||
Debug(DebugInfo,"OnReceivedAckPDU");
|
||||
return H323_ExternalRTPChannel::OnReceivedAckPDU(param);
|
||||
}
|
||||
|
||||
BOOL YateH323AudioConsumer::Close()
|
||||
{
|
||||
m_exit = true;
|
||||
|
@ -553,7 +803,7 @@ BOOL YateH323AudioConsumer::IsOpen() const
|
|||
return !m_exit;
|
||||
}
|
||||
|
||||
void YateH323AudioConsumer::Consume(const DataBlock &data)
|
||||
void YateH323AudioConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
Lock lock(m_mutex);
|
||||
if ((m_buffer.length() + data.length()) <= (480*5))
|
||||
|
@ -562,6 +812,7 @@ void YateH323AudioConsumer::Consume(const DataBlock &data)
|
|||
else
|
||||
Debug("YateH323AudioConsumer",DebugAll,"Skipped %u bytes, buffer is full",data.length());
|
||||
#endif
|
||||
m_timestamp += timeDelta;
|
||||
}
|
||||
|
||||
BOOL YateH323AudioConsumer::Read(void *buf, PINDEX len)
|
||||
|
@ -604,7 +855,7 @@ BOOL YateH323AudioSource::IsOpen() const
|
|||
BOOL YateH323AudioSource::Write(const void *buf, PINDEX len)
|
||||
{
|
||||
DataBlock data((void *)buf,len,false);
|
||||
Forward(data);
|
||||
Forward(data,len/2);
|
||||
data.clear(false);
|
||||
lastWriteCount = len;
|
||||
writeDelay.Delay(len/16);
|
||||
|
@ -825,6 +1076,7 @@ bool H323Dropper::received(Message &msg)
|
|||
String id(msg.getValue("id"));
|
||||
if (id.null()) {
|
||||
Debug("H323Dropper",DebugInfo,"Dropping all calls");
|
||||
Lock lock(s_calls);
|
||||
ObjList *l = &hplugin.calls();
|
||||
for (; l; l=l->next()) {
|
||||
YateH323Connection *c = static_cast<YateH323Connection *>(l->get());
|
||||
|
@ -854,6 +1106,7 @@ bool StatusHandler::received(Message &msg)
|
|||
if (sel && ::strcmp(sel,"h323chan") && ::strcmp(sel,"varchans"))
|
||||
return false;
|
||||
String st("h323chan,type=varchans");
|
||||
Lock lock(s_calls);
|
||||
st << ",chans=" << hplugin.calls().count() << ",[LIST]";
|
||||
ObjList *l = &hplugin.calls();
|
||||
for (; l; l=l->next()) {
|
||||
|
@ -905,6 +1158,7 @@ H323Plugin::~H323Plugin()
|
|||
|
||||
YateH323Connection *H323Plugin::findConnectionLock(const char *id)
|
||||
{
|
||||
Lock lock(s_calls);
|
||||
ObjList *l = &m_calls;
|
||||
for (; l; l=l->next()) {
|
||||
YateH323Connection *c = static_cast<YateH323Connection *>(l->get());
|
||||
|
@ -919,7 +1173,7 @@ YateH323Connection *H323Plugin::findConnectionLock(const char *id)
|
|||
|
||||
void H323Plugin::initialize()
|
||||
{
|
||||
Output("Initializing module H.323");
|
||||
Output("Initializing module H.323 - based on OpenH323-" OPENH323_VERSION);
|
||||
s_cfg = Engine::configFile("h323chan");
|
||||
s_cfg.load();
|
||||
if (!m_process)
|
||||
|
@ -932,6 +1186,7 @@ void H323Plugin::initialize()
|
|||
m_endpoint = new YateH323EndPoint;
|
||||
m_endpoint->Init();
|
||||
}
|
||||
s_externalRtp = s_cfg.getBoolValue("general","external_rtp",false);
|
||||
if (m_first) {
|
||||
m_first = false;
|
||||
Engine::install(new H323Handler("call"));
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
IAXSource(const char *frm) : DataSource(frm),m_total(0),m_time(Time::now())
|
||||
{ Debug(DebugInfo,"IAXSource::IAXSource [%p] frm %s",this,frm);};
|
||||
~IAXSource();
|
||||
void Forward(const DataBlock &data);
|
||||
void Forward(const DataBlock &data, unsigned long timeDelta = 0);
|
||||
private:
|
||||
unsigned m_total;
|
||||
unsigned long long m_time;
|
||||
|
@ -72,7 +72,7 @@ public:
|
|||
|
||||
~YateIAXAudioConsumer();
|
||||
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
|
||||
private:
|
||||
YateIAXConnection *m_conn;
|
||||
|
@ -801,10 +801,10 @@ IAXSource::~IAXSource()
|
|||
|
||||
}
|
||||
|
||||
void IAXSource::Forward(const DataBlock &data)
|
||||
void IAXSource::Forward(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
m_total += data.length();
|
||||
DataSource::Forward(data);
|
||||
DataSource::Forward(data, timeDelta);
|
||||
}
|
||||
|
||||
YateIAXAudioConsumer::YateIAXAudioConsumer(YateIAXConnection *conn, iax_session *session, int ast_format, const char *format)
|
||||
|
@ -827,7 +827,7 @@ YateIAXAudioConsumer::~YateIAXAudioConsumer()
|
|||
|
||||
}
|
||||
|
||||
void YateIAXAudioConsumer::Consume(const DataBlock &data)
|
||||
void YateIAXAudioConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
m_total += data.length();
|
||||
::iax_send_voice(m_session,m_ast_format,(char *)data.data(),data.length());
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
}
|
||||
bool init();
|
||||
~OssConsumer();
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
private:
|
||||
OssChan *m_chan;
|
||||
unsigned m_total;
|
||||
|
@ -175,7 +175,7 @@ void OssSource::run()
|
|||
#endif
|
||||
::usleep((unsigned long)dly);
|
||||
}
|
||||
Forward(data);
|
||||
Forward(data,data.length()/2);
|
||||
m_total += r;
|
||||
tpos += (r*1000000ULL/m_brate);
|
||||
} while (r > 0);
|
||||
|
@ -222,7 +222,7 @@ OssConsumer::~OssConsumer()
|
|||
}
|
||||
}
|
||||
|
||||
void OssConsumer::Consume(const DataBlock &data)
|
||||
void OssConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
if ((m_chan->m_fd >= 0) && !data.null()) {
|
||||
::write(m_chan->m_fd,data.data(),data.length());
|
||||
|
|
|
@ -105,7 +105,7 @@ ToneSource::ToneSource(const String &tone)
|
|||
|
||||
ToneSource::~ToneSource()
|
||||
{
|
||||
Debug(DebugAll,"ToneSource::~ToneSource() [%p] total=%u",this,m_total);
|
||||
Debug(DebugAll,"ToneSource::~ToneSource() [%p] total=%u stamp=%lu",this,m_total,timeStamp());
|
||||
if (m_time) {
|
||||
m_time = Time::now() - m_time;
|
||||
if (m_time) {
|
||||
|
@ -181,7 +181,7 @@ void ToneSource::run()
|
|||
#endif
|
||||
::usleep((unsigned long)dly);
|
||||
}
|
||||
Forward(data);
|
||||
Forward(data,data.length()/2);
|
||||
m_total += data.length();
|
||||
tpos += (data.length()*1000000ULL/m_brate);
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ class WaveConsumer : public DataConsumer
|
|||
public:
|
||||
WaveConsumer(const String& file, DataEndpoint *chan = 0, unsigned maxlen = 0);
|
||||
~WaveConsumer();
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
inline void setNotify(const String& id)
|
||||
{ m_id = id; }
|
||||
private:
|
||||
|
@ -111,7 +111,7 @@ WaveSource::WaveSource(const String& file, DataEndpoint *chan, bool autoclose)
|
|||
|
||||
WaveSource::~WaveSource()
|
||||
{
|
||||
Debug(DebugAll,"WaveSource::~WaveSource() [%p] total=%u",this,m_total);
|
||||
Debug(DebugAll,"WaveSource::~WaveSource() [%p] total=%u stamp=%lu",this,m_total,timeStamp());
|
||||
if (m_time) {
|
||||
m_time = Time::now() - m_time;
|
||||
if (m_time) {
|
||||
|
@ -149,7 +149,7 @@ void WaveSource::run()
|
|||
#endif
|
||||
::usleep((unsigned long)dly);
|
||||
}
|
||||
Forward(data);
|
||||
Forward(data,data.length()*8000/m_brate);
|
||||
m_total += r;
|
||||
tpos += (r*1000000ULL/m_brate);
|
||||
} while (r > 0);
|
||||
|
@ -189,7 +189,7 @@ WaveConsumer::WaveConsumer(const String& file, DataEndpoint *chan, unsigned maxl
|
|||
|
||||
WaveConsumer::~WaveConsumer()
|
||||
{
|
||||
Debug(DebugAll,"WaveConsumer::~WaveConsumer() [%p] total=%u",this,m_total);
|
||||
Debug(DebugAll,"WaveConsumer::~WaveConsumer() [%p] total=%u stamp=%lu",this,m_total,timeStamp());
|
||||
if (m_time) {
|
||||
m_time = Time::now() - m_time;
|
||||
if (m_time) {
|
||||
|
@ -203,7 +203,7 @@ WaveConsumer::~WaveConsumer()
|
|||
}
|
||||
}
|
||||
|
||||
void WaveConsumer::Consume(const DataBlock &data)
|
||||
void WaveConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
if (!data.null()) {
|
||||
if (!m_time)
|
||||
|
@ -211,6 +211,7 @@ void WaveConsumer::Consume(const DataBlock &data)
|
|||
if (m_fd >= 0)
|
||||
::write(m_fd,data.data(),data.length());
|
||||
m_total += data.length();
|
||||
m_timestamp += timeDelta;
|
||||
if (m_maxlen && (m_total >= m_maxlen)) {
|
||||
m_maxlen = 0;
|
||||
if (m_fd >= 0) {
|
||||
|
|
|
@ -386,7 +386,7 @@ public:
|
|||
~ZapConsumer()
|
||||
{ Debug(DebugAll,"ZapConsumer::~ZapConsumer() [%p]",this); }
|
||||
|
||||
virtual void Consume(const DataBlock &data);
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta);
|
||||
|
||||
private:
|
||||
ZapChan *m_owner;
|
||||
|
@ -768,15 +768,15 @@ void ZapSource::run()
|
|||
switch (m_owner->law()) {
|
||||
case -1:
|
||||
data.assign(buf.data(),rd);
|
||||
Forward(data);
|
||||
Forward(data,rd/2);
|
||||
break;
|
||||
case ZT_LAW_MULAW:
|
||||
data.convert(buf,"mulaw","slin",rd);
|
||||
Forward(data);
|
||||
Forward(data,rd);
|
||||
break;
|
||||
case ZT_LAW_ALAW:
|
||||
data.convert(buf,"alaw","slin",rd);
|
||||
Forward(data);
|
||||
Forward(data,rd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -790,7 +790,7 @@ void ZapSource::run()
|
|||
}
|
||||
}
|
||||
|
||||
void ZapConsumer::Consume(const DataBlock &data)
|
||||
void ZapConsumer::Consume(const DataBlock &data, unsigned long timeDelta)
|
||||
{
|
||||
int fd = m_owner->fd();
|
||||
#ifdef DEBUG
|
||||
|
|
24
yatephone.h
24
yatephone.h
|
@ -169,7 +169,7 @@ public:
|
|||
* @param format Name of the data format, default none
|
||||
*/
|
||||
DataNode(const char *format = 0)
|
||||
: m_format(format) { }
|
||||
: m_format(format), m_timestamp(0) { }
|
||||
|
||||
/**
|
||||
* Get the computing cost of converting the data to the format asked
|
||||
|
@ -194,11 +194,16 @@ public:
|
|||
inline const String &getFormat() const
|
||||
{ return m_format; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The name of the data format the node is currently using
|
||||
* Get the current position in the data stream
|
||||
* @return Timestamp of current data position
|
||||
*/
|
||||
inline unsigned long timeStamp() const
|
||||
{ return m_timestamp; }
|
||||
|
||||
protected:
|
||||
String m_format;
|
||||
unsigned long m_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -218,8 +223,9 @@ public:
|
|||
/**
|
||||
* Consumes the data sent to it from a source
|
||||
* @param data The raw data block to process; an empty block ends data
|
||||
* @param timeDelta Timestamp increment of data - typically samples
|
||||
*/
|
||||
virtual void Consume(const DataBlock &data) = 0;
|
||||
virtual void Consume(const DataBlock &data, unsigned long timeDelta) = 0;
|
||||
|
||||
/**
|
||||
* Get the data source of this object if it's connected
|
||||
|
@ -255,14 +261,17 @@ public:
|
|||
DataSource(const char *format = "slin")
|
||||
: DataNode(format), m_translator(0) { }
|
||||
|
||||
/** porma */
|
||||
/**
|
||||
* Source's destructor - detaches all consumers
|
||||
*/
|
||||
~DataSource();
|
||||
|
||||
/**
|
||||
* Forwards the data to its consumers
|
||||
* @param data The raw data block to forward; an empty block ends data
|
||||
* @param timeDelta Timestamp increment of data - typically samples
|
||||
*/
|
||||
void Forward(const DataBlock &data);
|
||||
void Forward(const DataBlock &data, unsigned long timeDelta = 0);
|
||||
|
||||
/**
|
||||
* Attach a data consumer
|
||||
|
@ -292,6 +301,9 @@ public:
|
|||
{ return m_translator; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The current position in the data - format dependent, usually samples
|
||||
*/
|
||||
inline void setTranslator(DataTranslator *translator)
|
||||
{ m_translator = translator; }
|
||||
DataTranslator *m_translator;
|
||||
|
|
Loading…
Reference in New Issue