1
0
mirror of https://github.com/rofafor/vdr-plugin-satip.git synced 2023-10-10 13:37:42 +02:00

Add a preliminary RTP-over-TCP support.

This commit is contained in:
Rolf Ahrenberg 2016-12-15 08:49:47 +02:00
parent af64cb3011
commit a5d57e9390
13 changed files with 146 additions and 25 deletions

View File

@ -100,6 +100,11 @@ void cSatipMsearch::Process(void)
} }
} }
void cSatipMsearch::Process(unsigned char *dataP, int lengthP)
{
debug16("%s", __PRETTY_FUNCTION__);
}
cString cSatipMsearch::ToString(void) const cString cSatipMsearch::ToString(void) const
{ {
return "MSearch"; return "MSearch";

View File

@ -34,6 +34,7 @@ public:
public: public:
virtual int GetFd(void); virtual int GetFd(void);
virtual void Process(void); virtual void Process(void);
virtual void Process(unsigned char *dataP, int lengthP);
virtual cString ToString(void) const; virtual cString ToString(void) const;
}; };

View File

@ -14,6 +14,7 @@ public:
virtual ~cSatipPollerIf() {} virtual ~cSatipPollerIf() {}
virtual int GetFd(void) = 0; virtual int GetFd(void) = 0;
virtual void Process(void) = 0; virtual void Process(void) = 0;
virtual void Process(unsigned char *dataP, int lengthP) = 0;
virtual cString ToString(void) const = 0; virtual cString ToString(void) const = 0;
private: private:

10
rtcp.c
View File

@ -92,6 +92,16 @@ void cSatipRtcp::Process(void)
} }
} }
void cSatipRtcp::Process(unsigned char *dataP, int lengthP)
{
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
if (dataP && lengthP > 0) {
int offset = GetApplicationOffset(&lengthP);
if (offset >= 0)
tunerM.ProcessApplicationData(dataP + offset, lengthP);
}
}
cString cSatipRtcp::ToString(void) const cString cSatipRtcp::ToString(void) const
{ {
return cString::sprintf("RTCP [device %d]", tunerM.GetId()); return cString::sprintf("RTCP [device %d]", tunerM.GetId());

1
rtcp.h
View File

@ -30,6 +30,7 @@ public:
public: public:
virtual int GetFd(void); virtual int GetFd(void);
virtual void Process(void); virtual void Process(void);
virtual void Process(unsigned char *dataP, int lengthP);
virtual cString ToString(void) const; virtual cString ToString(void) const;
}; };

16
rtp.c
View File

@ -142,6 +142,22 @@ void cSatipRtp::Process(void)
} }
} }
void cSatipRtp::Process(unsigned char *dataP, int lengthP)
{
debug16("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
if (dataP && lengthP > 0) {
uint64_t elapsed;
cTimeMs processing(0);
int headerlen = GetHeaderLength(dataP, lengthP);
if ((headerlen >= 0) && (headerlen < lengthP))
tunerM.ProcessVideoData(dataP + headerlen, lengthP - headerlen);
elapsed = processing.Elapsed();
if (elapsed > 1)
debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, lengthP, elapsed, tunerM.GetId());
}
}
cString cSatipRtp::ToString(void) const cString cSatipRtp::ToString(void) const
{ {
return cString::sprintf("RTP [device %d]", tunerM.GetId()); return cString::sprintf("RTP [device %d]", tunerM.GetId());

1
rtp.h
View File

@ -36,6 +36,7 @@ public:
public: public:
virtual int GetFd(void); virtual int GetFd(void);
virtual void Process(void); virtual void Process(void);
virtual void Process(unsigned char *dataP, int lengthP);
virtual cString ToString(void) const; virtual cString ToString(void) const;
}; };

86
rtsp.c
View File

@ -21,7 +21,10 @@ cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
headerListM(NULL), headerListM(NULL),
errorNoMoreM(""), errorNoMoreM(""),
errorOutOfRangeM(""), errorOutOfRangeM(""),
errorCheckSyntaxM("") errorCheckSyntaxM(""),
modeM(cSatipConfig::eTransportModeUnicast),
interleavedRtpIdM(0),
interleavedRtcpIdM(1)
{ {
debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId()); debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
Create(); Create();
@ -57,6 +60,30 @@ size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *d
return len; return len;
} }
size_t cSatipRtsp::InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
{
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
size_t len = sizeP * nmembP;
debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
if (obj && ptrP && len > 0) {
char tag = ptrP[0] & 0xFF;
if (tag == '$') {
int count = ((ptrP[2] & 0xFF) << 8) | (ptrP[3] & 0xFF);
if (count > 0) {
unsigned int channel = ptrP[1] & 0xFF;
u_char *data = (u_char *)&ptrP[4];
if (channel == obj->interleavedRtpIdM)
obj->tunerM.ProcessRtpData(data, count);
else if (channel == obj->interleavedRtcpIdM)
obj->tunerM.ProcessRtcpData(data, count);
}
}
}
return len;
}
int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP) int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP)
{ {
cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP); cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(userPtrP);
@ -86,6 +113,21 @@ int cSatipRtsp::DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, s
return 0; return 0;
} }
cString cSatipRtsp::GetActiveMode(void)
{
switch (modeM) {
case cSatipConfig::eTransportModeUnicast:
return "Unicast";
case cSatipConfig::eTransportModeMulticast:
return "Multicast";
case cSatipConfig::eTransportModeRtpOverTcp:
return "RTP-over-TCP";
default:
break;
}
return "";
}
cString cSatipRtsp::RtspUnescapeString(const char *strP) cString cSatipRtsp::RtspUnescapeString(const char *strP)
{ {
debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId()); debug1("%s (%s) [device %d]", __PRETTY_FUNCTION__, strP, tunerM.GetId());
@ -122,6 +164,9 @@ void cSatipRtsp::Create(void)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_TIMEOUT_MS, (long)eConnectTimeoutMs);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_CONNECTTIMEOUT_MS, (long)eConnectTimeoutMs);
// Limit download speed (bytes/s)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_MAX_RECV_SPEED_LARGE, eMaxDownloadSpeedMBits * 131072L);
// Set user-agent // Set user-agent
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId())); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_USERAGENT, *cString::sprintf("vdr-%s/%s (device %d)", PLUGIN_NAME_I18N, VERSION, tunerM.GetId()));
} }
@ -189,7 +234,10 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTc
default: default:
// RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port> // RTP/AVP;unicast;client_port=<client RTP port>-<client RTCP port>
// RTP/AVP/TCP;unicast;client_port=<client RTP port>-<client RTCP port> // RTP/AVP/TCP;unicast;client_port=<client RTP port>-<client RTCP port>
transport = cString::sprintf("RTP/AVP%s;unicast;client_port=%d-%d", useTcpP ? "/TCP" : "", rtpPortP, rtcpPortP); if (useTcpP)
transport = cString::sprintf("RTP/AVP/TCP;unicast;interleaved=%u-%u", interleavedRtpIdM, interleavedRtcpIdM);
else
transport = cString::sprintf("RTP/AVP;unicast;client_port=%d-%d", rtpPortP, rtcpPortP);
break; break;
} }
@ -202,6 +250,9 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP, bool useTc
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
SATIP_CURL_EASY_PERFORM(handleM); SATIP_CURL_EASY_PERFORM(handleM);
// Session id is now known - disable header parsing // Session id is now known - disable header parsing
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
@ -309,6 +360,8 @@ bool cSatipRtsp::Teardown(const char *uriP)
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
SATIP_CURL_EASY_PERFORM(handleM); SATIP_CURL_EASY_PERFORM(handleM);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
@ -351,21 +404,30 @@ void cSatipRtsp::ParseHeader(void)
FREE_POINTER(session); FREE_POINTER(session);
} }
else if (strstr(r, "Transport:")) { else if (strstr(r, "Transport:")) {
CURLcode res = CURLE_OK;
int rtp = -1, rtcp = -1, ttl = -1; int rtp = -1, rtcp = -1, ttl = -1;
char *tmp = NULL, *destination = NULL, *source = NULL; char *tmp = NULL, *destination = NULL, *source = NULL;
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) interleavedRtpIdM = 0;
interleavedRtcpIdM = 1;
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, NULL);
SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, NULL);
if (sscanf(r, "Transport:%m[^;];unicast;client_port=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
modeM = cSatipConfig::eTransportModeUnicast;
tunerM.SetupTransport(rtp, rtcp, NULL, NULL); tunerM.SetupTransport(rtp, rtcp, NULL, NULL);
}
else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 || else if (sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d;source=%m[^;]", &tmp, &destination, &rtp, &rtcp, &ttl, &source) == 6 ||
sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) sscanf(r, "Transport:%m[^;];multicast;destination=%m[^;];port=%11d-%11d;ttl=%11d", &tmp, &destination, &rtp, &rtcp, &ttl) == 5) {
modeM = cSatipConfig::eTransportModeMulticast;
tunerM.SetupTransport(rtp, rtcp, destination, source); tunerM.SetupTransport(rtp, rtcp, destination, source);
// TODO: else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) }
// Stream data such as RTP packets is encapsulated by an ASCII dollar else if (sscanf(r, "Transport:%m[^;];interleaved=%11d-%11d", &tmp, &rtp, &rtcp) == 3) {
// sign (24 hexadecimal), followed by a one-byte channel identifier, interleavedRtpIdM = rtp;
// followed by the length of the encapsulated binary data as a binary, interleavedRtcpIdM = rtcp;
// two-byte integer in network byte order. The stream data follows SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEFUNCTION, cSatipRtsp::InterleaveCallback);
// immediately afterwards, without a CRLF, but including the upper-layer SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_INTERLEAVEDATA, this);
// protocol headers. Each $ block contains exactly one upper-layer modeM = cSatipConfig::eTransportModeRtpOverTcp;
// protocol data unit, e.g., one RTP packet. tunerM.SetupTransport(-1, -1, NULL, NULL);
}
FREE_POINTER(tmp); FREE_POINTER(tmp);
FREE_POINTER(destination); FREE_POINTER(destination);
FREE_POINTER(source); FREE_POINTER(source);

8
rtsp.h
View File

@ -22,10 +22,12 @@ class cSatipRtsp {
private: private:
static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP); static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP); static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
static size_t InterleaveCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP); static int DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
enum { enum {
eConnectTimeoutMs = 1500, // in milliseconds eConnectTimeoutMs = 1500, // in milliseconds
eMaxDownloadSpeedMBits = 20, // in megabits per second
}; };
cSatipTunerIf &tunerM; cSatipTunerIf &tunerM;
@ -36,6 +38,9 @@ private:
cString errorNoMoreM; cString errorNoMoreM;
cString errorOutOfRangeM; cString errorOutOfRangeM;
cString errorCheckSyntaxM; cString errorCheckSyntaxM;
int modeM;
unsigned int interleavedRtpIdM;
unsigned int interleavedRtcpIdM;
void Create(void); void Create(void);
void Destroy(void); void Destroy(void);
@ -51,6 +56,7 @@ public:
explicit cSatipRtsp(cSatipTunerIf &tunerP); explicit cSatipRtsp(cSatipTunerIf &tunerP);
virtual ~cSatipRtsp(); virtual ~cSatipRtsp();
cString GetActiveMode(void);
cString RtspUnescapeString(const char *strP); cString RtspUnescapeString(const char *strP);
void Reset(void); void Reset(void);
bool Options(const char *uriP); bool Options(const char *uriP);

View File

@ -416,7 +416,7 @@ void cSatipPluginSetup::Setup(void)
helpM.Append(tr("Define an ill-behaving filter to be blacklisted.")); helpM.Append(tr("Define an ill-behaving filter to be blacklisted."));
} }
} }
Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM) - 1, transportModeTextsM)); // TODO: RTP-over-TCP Add(new cMenuEditStraItem(tr("Transport mode"), &transportModeM, ELEMENTS(transportModeTextsM), transportModeTextsM));
helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP")); helpM.Append(tr("Define which transport mode shall be used.\n\nUnicast, Multicast, RTP-over-TCP"));
Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false)); Add(new cOsdItem(tr("Active SAT>IP servers:"), osUnknown, false));
helpM.Append(""); helpM.Append("");

36
tuner.c
View File

@ -297,6 +297,11 @@ void cSatipTuner::ProcessVideoData(u_char *bufferP, int lengthP)
reConnectM.Set(eConnectTimeoutMs); reConnectM.Set(eConnectTimeoutMs);
} }
void cSatipTuner::ProcessRtpData(u_char *bufferP, int lengthP)
{
rtpM.Process(bufferP, lengthP);
}
void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP) void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
{ {
debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIdM); debug16("%s (%d) [device %d]", __PRETTY_FUNCTION__, lengthP, deviceIdM);
@ -350,6 +355,11 @@ void cSatipTuner::ProcessApplicationData(u_char *bufferP, int lengthP)
reConnectM.Set(eConnectTimeoutMs); reConnectM.Set(eConnectTimeoutMs);
} }
void cSatipTuner::ProcessRtcpData(u_char *bufferP, int lengthP)
{
rtcpM.Process(bufferP, lengthP);
}
void cSatipTuner::SetStreamId(int streamIdP) void cSatipTuner::SetStreamId(int streamIdP)
{ {
cMutexLock MutexLock(&mutexM); cMutexLock MutexLock(&mutexM);
@ -376,21 +386,25 @@ void cSatipTuner::SetupTransport(int rtpPortP, int rtcpPortP, const char *stream
if (multicast != rtpM.IsMulticast() || rtpPortP != rtpM.Port()) { if (multicast != rtpM.IsMulticast() || rtpPortP != rtpM.Port()) {
cSatipPoller::GetInstance()->Unregister(rtpM); cSatipPoller::GetInstance()->Unregister(rtpM);
rtpM.Close(); rtpM.Close();
if (multicast) if (rtpPortP >= 0) {
rtpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP); if (multicast)
else rtpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
rtpM.Open(rtpPortP); else
cSatipPoller::GetInstance()->Register(rtpM); rtpM.Open(rtpPortP);
cSatipPoller::GetInstance()->Register(rtpM);
}
} }
// Adapt RTCP to any transport media change // Adapt RTCP to any transport media change
if (multicast != rtcpM.IsMulticast() || rtcpPortP != rtcpM.Port()) { if (multicast != rtcpM.IsMulticast() || rtcpPortP != rtcpM.Port()) {
cSatipPoller::GetInstance()->Unregister(rtcpM); cSatipPoller::GetInstance()->Unregister(rtcpM);
rtcpM.Close(); rtcpM.Close();
if (multicast) if (rtcpPortP >= 0) {
rtcpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP); if (multicast)
else rtcpM.OpenMulticast(rtpPortP, streamAddrP, sourceAddrP);
rtcpM.Open(rtpPortP); else
cSatipPoller::GetInstance()->Register(rtcpM); rtcpM.Open(rtpPortP);
cSatipPoller::GetInstance()->Register(rtcpM);
}
} }
} }
@ -674,5 +688,5 @@ cString cSatipTuner::GetSignalStatus(void)
cString cSatipTuner::GetInformation(void) cString cSatipTuner::GetInformation(void)
{ {
debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
return (currentStateM >= tsTuned) ? cString::sprintf("%s?%s [stream=%d]", *GetBaseUrl(*streamAddrM, streamPortM), *streamParamM, streamIdM) : "connection failed"; return (currentStateM >= tsTuned) ? cString::sprintf("%s?%s (%s) [stream=%d]", *GetBaseUrl(*streamAddrM, streamPortM), *streamParamM, *rtspM.GetActiveMode(), streamIdM) : "connection failed";
} }

View File

@ -157,6 +157,8 @@ public:
public: public:
virtual void ProcessVideoData(u_char *bufferP, int lengthP); virtual void ProcessVideoData(u_char *bufferP, int lengthP);
virtual void ProcessApplicationData(u_char *bufferP, int lengthP); virtual void ProcessApplicationData(u_char *bufferP, int lengthP);
virtual void ProcessRtpData(u_char *bufferP, int lengthP);
virtual void ProcessRtcpData(u_char *bufferP, int lengthP);
virtual void SetStreamId(int streamIdP); virtual void SetStreamId(int streamIdP);
virtual void SetSessionTimeout(const char *sessionP, int timeoutP); virtual void SetSessionTimeout(const char *sessionP, int timeoutP);
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP); virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP);

View File

@ -14,6 +14,8 @@ public:
virtual ~cSatipTunerIf() {} virtual ~cSatipTunerIf() {}
virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0; virtual void ProcessVideoData(u_char *bufferP, int lengthP) = 0;
virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0; virtual void ProcessApplicationData(u_char *bufferP, int lengthP) = 0;
virtual void ProcessRtpData(u_char *bufferP, int lengthP) = 0;
virtual void ProcessRtcpData(u_char *bufferP, int lengthP) = 0;
virtual void SetStreamId(int streamIdP) = 0; virtual void SetStreamId(int streamIdP) = 0;
virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0; virtual void SetSessionTimeout(const char *sessionP, int timeoutP) = 0;
virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) = 0; virtual void SetupTransport(int rtpPortP, int rtcpPortP, const char *streamAddrP, const char *sourceAddrP) = 0;