Add max-inter-packet-gap-time to proxyServer

This commit is contained in:
Roman Gaufman
2016-10-12 15:35:57 +01:00
parent 7aaacef814
commit c32916d06d
5 changed files with 345 additions and 15 deletions

View File

@@ -0,0 +1,254 @@
diff -pru livemedia.2016.09.22_org/liveMedia/include/ProxyServerMediaSession.hh livemedia.2016.09.22_noprints/liveMedia/include/ProxyServerMediaSession.hh
--- livemedia.2016.09.22_org/liveMedia/include/ProxyServerMediaSession.hh 2016-09-23 00:53:55.000000000 +0200
+++ livemedia.2016.09.22_noprints/liveMedia/include/ProxyServerMediaSession.hh 2016-10-02 10:06:07.077121273 +0200
@@ -43,7 +43,8 @@ class ProxyRTSPClient: public RTSPClient
public:
ProxyRTSPClient(class ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
char const* username, char const* password,
- portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer);
+ portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
+ unsigned interPacketGapMaxTime = 0);
virtual ~ProxyRTSPClient();
void continueAfterDESCRIBE(char const* sdpDescription);
@@ -58,6 +59,8 @@ private:
void scheduleLivenessCommand();
static void sendLivenessCommand(void* clientData);
+ void checkInterPacketGaps_();
+ static void checkInterPacketGaps(void* clientData);
void scheduleDESCRIBECommand();
static void sendDESCRIBE(void* clientData);
@@ -75,8 +78,10 @@ private:
class ProxyServerMediaSubsession *fSetupQueueHead, *fSetupQueueTail;
unsigned fNumSetupsDone;
unsigned fNextDESCRIBEDelay; // in seconds
+ unsigned fTotNumPacketsReceived;
+ unsigned fInterPacketGapMaxTime; // in seconds
Boolean fServerSupportsGetParameter, fLastCommandWasPLAY, fResetOnNextLivenessTest;
- TaskToken fLivenessCommandTask, fDESCRIBECommandTask, fSubsessionTimerTask;
+ TaskToken fLivenessCommandTask, fDESCRIBECommandTask, fSubsessionTimerTask, fInterPacketGapsTask;
};
@@ -85,13 +90,13 @@ createNewProxyRTSPClientFunc(ProxyServer
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
- int socketNumToServer);
+ int socketNumToServer, unsigned interPacketGapMaxTime);
ProxyRTSPClient*
defaultCreateNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSession,
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
- int socketNumToServer);
+ int socketNumToServer, unsigned interPacketGapMaxTime);
class ProxyServerMediaSession: public ServerMediaSession {
public:
@@ -104,7 +109,8 @@ public:
// for streaming the *proxied* (i.e., back-end) stream
int verbosityLevel = 0,
int socketNumToServer = -1,
- MediaTranscodingTable* transcodingTable = NULL);
+ MediaTranscodingTable* transcodingTable = NULL,
+ unsigned interPacketGapMaxTime = 0);
// Hack: "tunnelOverHTTPPortNum" == 0xFFFF (i.e., all-ones) means: Stream RTP/RTCP-over-TCP, but *not* using HTTP
// "verbosityLevel" == 1 means display basic proxy setup info; "verbosityLevel" == 2 means display RTSP client protocol also.
// If "socketNumToServer" is >= 0, then it is the socket number of an already-existing TCP connection to the server.
@@ -127,6 +133,7 @@ protected:
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer,
MediaTranscodingTable* transcodingTable,
+ unsigned interPacketGapMaxTime = 0,
createNewProxyRTSPClientFunc* ourCreateNewProxyRTSPClientFunc
= defaultCreateNewProxyRTSPClientFunc,
portNumBits initialPortNum = 6970,
diff -pru livemedia.2016.09.22_org/liveMedia/ProxyServerMediaSession.cpp livemedia.2016.09.22_noprints/liveMedia/ProxyServerMediaSession.cpp
--- livemedia.2016.09.22_org/liveMedia/ProxyServerMediaSession.cpp 2016-09-23 00:53:55.000000000 +0200
+++ livemedia.2016.09.22_noprints/liveMedia/ProxyServerMediaSession.cpp 2016-10-02 15:53:35.116204035 +0200
@@ -75,9 +75,9 @@ defaultCreateNewProxyRTSPClientFunc(Prox
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
- int socketNumToServer) {
+ int socketNumToServer, unsigned interPacketGapMaxTime) {
return new ProxyRTSPClient(ourServerMediaSession, rtspURL, username, password,
- tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer);
+ tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer, interPacketGapMaxTime);
}
ProxyServerMediaSession* ProxyServerMediaSession
@@ -85,10 +85,10 @@ ProxyServerMediaSession* ProxyServerMedi
char const* inputStreamURL, char const* streamName,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
- MediaTranscodingTable* transcodingTable) {
+ MediaTranscodingTable* transcodingTable, unsigned interPacketGapMaxTime) {
return new ProxyServerMediaSession(env, ourMediaServer, inputStreamURL, streamName, username, password,
tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer,
- transcodingTable);
+ transcodingTable, interPacketGapMaxTime);
}
@@ -99,6 +99,7 @@ ProxyServerMediaSession
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer,
MediaTranscodingTable* transcodingTable,
+ unsigned interPacketGapMaxTime,
createNewProxyRTSPClientFunc* ourCreateNewProxyRTSPClientFunc,
portNumBits initialPortNum, Boolean multiplexRTCPWithRTP)
: ServerMediaSession(env, streamName, NULL, NULL, False, NULL),
@@ -114,7 +115,7 @@ ProxyServerMediaSession
= (*fCreateNewProxyRTSPClientFunc)(*this, inputStreamURL, username, password,
tunnelOverHTTPPortNum,
verbosityLevel > 0 ? verbosityLevel-1 : verbosityLevel,
- socketNumToServer);
+ socketNumToServer, interPacketGapMaxTime);
ProxyRTSPClient::sendDESCRIBE(fProxyRTSPClient);
}
@@ -243,13 +244,15 @@ UsageEnvironment& operator<<(UsageEnviro
ProxyRTSPClient::ProxyRTSPClient(ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
char const* username, char const* password,
- portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer)
+ portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
+ unsigned interPacketGapMaxTime)
: RTSPClient(ourServerMediaSession.envir(), rtspURL, verbosityLevel, "ProxyRTSPClient",
tunnelOverHTTPPortNum == (portNumBits)(~0) ? 0 : tunnelOverHTTPPortNum, socketNumToServer),
fOurServerMediaSession(ourServerMediaSession), fOurURL(strDup(rtspURL)), fStreamRTPOverTCP(tunnelOverHTTPPortNum != 0),
fSetupQueueHead(NULL), fSetupQueueTail(NULL), fNumSetupsDone(0), fNextDESCRIBEDelay(1),
+ fTotNumPacketsReceived(~0), fInterPacketGapMaxTime(interPacketGapMaxTime),
fServerSupportsGetParameter(False), fLastCommandWasPLAY(False), fResetOnNextLivenessTest(False),
- fLivenessCommandTask(NULL), fDESCRIBECommandTask(NULL), fSubsessionTimerTask(NULL) {
+ fLivenessCommandTask(NULL), fDESCRIBECommandTask(NULL), fSubsessionTimerTask(NULL) , fInterPacketGapsTask(NULL) {
if (username != NULL && password != NULL) {
fOurAuthenticator = new Authenticator(username, password);
} else {
@@ -261,11 +264,13 @@ void ProxyRTSPClient::reset() {
envir().taskScheduler().unscheduleDelayedTask(fLivenessCommandTask); fLivenessCommandTask = NULL;
envir().taskScheduler().unscheduleDelayedTask(fDESCRIBECommandTask); fDESCRIBECommandTask = NULL;
envir().taskScheduler().unscheduleDelayedTask(fSubsessionTimerTask); fSubsessionTimerTask = NULL;
+ envir().taskScheduler().unscheduleDelayedTask(fInterPacketGapsTask); fInterPacketGapsTask = NULL;
fSetupQueueHead = fSetupQueueTail = NULL;
fNumSetupsDone = 0;
fNextDESCRIBEDelay = 1;
fLastCommandWasPLAY = False;
+ fTotNumPacketsReceived = ~0;
RTSPClient::reset();
}
@@ -392,6 +397,7 @@ void ProxyRTSPClient::continueAfterPLAY(
envir().taskScheduler().rescheduleDelayedTask(fLivenessCommandTask, 0, sendLivenessCommand, this);
return;
}
+ if (fInterPacketGapsTask == NULL) checkInterPacketGaps_();
}
void ProxyRTSPClient::scheduleLivenessCommand() {
@@ -432,6 +438,44 @@ void ProxyRTSPClient::sendLivenessComman
#endif
}
+void ProxyRTSPClient::checkInterPacketGaps_() {
+ if (fInterPacketGapMaxTime == 0) return; // we're not checking
+
+ // Check each subsession, counting up how many packets have been received:
+ unsigned newTotNumPacketsReceived = 0;
+
+ MediaSubsessionIterator iter(*fOurServerMediaSession.fClientMediaSession);
+ MediaSubsession* subsession;
+ while ((subsession = iter.next()) != NULL) {
+ RTPSource* src = subsession->rtpSource();
+ if (src == NULL) continue;
+ newTotNumPacketsReceived += src->receptionStatsDB().totNumPacketsReceived();
+ }
+
+ //envir() << *this << "::doLivenessCheck fTotNumPacketsReceived: " << fTotNumPacketsReceived
+ // << ", newTotNumPacketsReceived: " << newTotNumPacketsReceived << "\n";
+
+ if (newTotNumPacketsReceived == fTotNumPacketsReceived) {
+ // No additional packets have been received since the last time we
+ // checked, so end this stream:
+ // *env << "Closing session, because we stopped receiving packets.\n";
+ if (fVerbosityLevel > 0) {
+ envir() << *this << "::doLivenessCheck last packet received: >" << fInterPacketGapMaxTime
+ << " seconds ago. Resetting session\n";
+ }
+ continueAfterLivenessCommand(1/*hack*/, fServerSupportsGetParameter);
+ } else {
+ fTotNumPacketsReceived = newTotNumPacketsReceived;
+ // Check again, after the specified delay:
+ fInterPacketGapsTask = envir().taskScheduler().scheduleDelayedTask(fInterPacketGapMaxTime*MILLION, checkInterPacketGaps, this);
+ }
+}
+
+void ProxyRTSPClient::checkInterPacketGaps(void* clientData) {
+ ProxyRTSPClient* rtspClient = (ProxyRTSPClient*)clientData;
+ rtspClient->checkInterPacketGaps_();
+}
+
void ProxyRTSPClient::scheduleDESCRIBECommand() {
// Delay 1s, 2s, 4s, 8s ... 256s until sending the next "DESCRIBE". Then, keep delaying a random time from [256..511] seconds:
unsigned secondsToDelay;
@@ -621,6 +665,7 @@ void ProxyServerMediaSubsession::closeSt
// Send a "PAUSE" for the whole stream.
proxyRTSPClient->sendPauseCommand(fClientMediaSubsession.parentSession(), NULL, proxyRTSPClient->auth());
proxyRTSPClient->fLastCommandWasPLAY = False;
+ envir().taskScheduler().unscheduleDelayedTask(proxyRTSPClient->fInterPacketGapsTask); proxyRTSPClient->fInterPacketGapsTask = NULL;
}
}
}
diff -pru livemedia.2016.09.22_org/proxyServer/live555ProxyServer.cpp livemedia.2016.09.22_noprints/proxyServer/live555ProxyServer.cpp
--- livemedia.2016.09.22_org/proxyServer/live555ProxyServer.cpp 2016-09-23 00:53:55.000000000 +0200
+++ livemedia.2016.09.22_noprints/proxyServer/live555ProxyServer.cpp 2016-10-02 10:13:18.893102276 +0200
@@ -35,6 +35,7 @@ char* password = NULL;
Boolean proxyREGISTERRequests = False;
char* usernameForREGISTER = NULL;
char* passwordForREGISTER = NULL;
+unsigned interPacketGapMaxTime = 0;
static RTSPServer* createRTSPServer(Port port) {
if (proxyREGISTERRequests) {
@@ -51,6 +52,7 @@ void usage() {
<< " [-p <rtspServer-port>]"
<< " [-u <username> <password>]"
<< " [-R] [-U <username-for-REGISTER> <password-for-REGISTER>]"
+ << " [-D <max-inter-packet-gap-time>]"
<< " <rtsp-url-1> ... <rtsp-url-n>\n";
exit(1);
}
@@ -151,6 +153,19 @@ int main(int argc, char** argv) {
break;
}
+ case 'D': { // specify maximum number of seconds to wait for packets:
+ if (argc > 2 && argv[2][0] != '-') {
+ if (sscanf(argv[2], "%u", &interPacketGapMaxTime) == 1) {
+ ++argv; --argc;
+ break;
+ }
+ }
+
+ // If we get here, the option was specified incorrectly:
+ usage();
+ break;
+ }
+
default: {
usage();
break;
@@ -221,7 +236,7 @@ int main(int argc, char** argv) {
ServerMediaSession* sms
= ProxyServerMediaSession::createNew(*env, rtspServer,
proxiedStreamURL, streamName,
- username, password, tunnelOverHTTPPortNum, verbosityLevel);
+ username, password, tunnelOverHTTPPortNum, verbosityLevel, -1, NULL, interPacketGapMaxTime);
rtspServer->addServerMediaSession(sms);
char* proxyStreamURL = rtspServer->rtspURL(sms);

View File

@@ -17,7 +17,7 @@ You will find various executables:
# Changes to Master
See modifications.patch to see exactly what was changed compared to vanilla.
See modifications.patch and Proxyserver_check_interPacketGap.patch to see exactly what was changed compared to vanilla.
### Buffer sizes
@@ -26,4 +26,13 @@ OutPacketBuffer::maxSize is increased to 2,000,000 bytes which makes live555 wor
### Force port re-use
Added -DALLOW_RTSP_SERVER_PORT_REUSE=1 to force reusing existing port (e.g. when restarting the proxy). Please ensure
you never run multiple instances of the proxy on the same port!
you never run multiple instances of the proxy on the same port!
### Max Inter Packet Gap Time
Erik Montnemery wrote a fantastic patch, in his own words: The new functionality is based on the implementation of the same option in openRTSP. When the -D option is used, the proxy server will reset the connection to a 'back end' server if at least one subsession *might* be in state playing, but no data has been received during max-inter-packet-gap-time seconds.
[-D <max-inter-packet-gap-time>]
* Note 1: This option does not make sense for all streams. It is useful for IP cameras where the camera should be sending data at all times. As discussed in another thread, theres no good way for the proxy server code to know exactly what subsession(s) are and are not currently streaming.

View File

@@ -75,9 +75,9 @@ defaultCreateNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSessi
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer) {
int socketNumToServer, unsigned interPacketGapMaxTime) {
return new ProxyRTSPClient(ourServerMediaSession, rtspURL, username, password,
tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer);
tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer, interPacketGapMaxTime);
}
ProxyServerMediaSession* ProxyServerMediaSession
@@ -85,10 +85,10 @@ ProxyServerMediaSession* ProxyServerMediaSession
char const* inputStreamURL, char const* streamName,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
MediaTranscodingTable* transcodingTable) {
MediaTranscodingTable* transcodingTable, unsigned interPacketGapMaxTime) {
return new ProxyServerMediaSession(env, ourMediaServer, inputStreamURL, streamName, username, password,
tunnelOverHTTPPortNum, verbosityLevel, socketNumToServer,
transcodingTable);
transcodingTable, interPacketGapMaxTime);
}
@@ -99,6 +99,7 @@ ProxyServerMediaSession
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer,
MediaTranscodingTable* transcodingTable,
unsigned interPacketGapMaxTime,
createNewProxyRTSPClientFunc* ourCreateNewProxyRTSPClientFunc,
portNumBits initialPortNum, Boolean multiplexRTCPWithRTP)
: ServerMediaSession(env, streamName, NULL, NULL, False, NULL),
@@ -114,7 +115,7 @@ ProxyServerMediaSession
= (*fCreateNewProxyRTSPClientFunc)(*this, inputStreamURL, username, password,
tunnelOverHTTPPortNum,
verbosityLevel > 0 ? verbosityLevel-1 : verbosityLevel,
socketNumToServer);
socketNumToServer, interPacketGapMaxTime);
ProxyRTSPClient::sendDESCRIBE(fProxyRTSPClient);
}
@@ -243,13 +244,15 @@ UsageEnvironment& operator<<(UsageEnvironment& env, const ProxyRTSPClient& proxy
ProxyRTSPClient::ProxyRTSPClient(ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer)
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
unsigned interPacketGapMaxTime)
: RTSPClient(ourServerMediaSession.envir(), rtspURL, verbosityLevel, "ProxyRTSPClient",
tunnelOverHTTPPortNum == (portNumBits)(~0) ? 0 : tunnelOverHTTPPortNum, socketNumToServer),
fOurServerMediaSession(ourServerMediaSession), fOurURL(strDup(rtspURL)), fStreamRTPOverTCP(tunnelOverHTTPPortNum != 0),
fSetupQueueHead(NULL), fSetupQueueTail(NULL), fNumSetupsDone(0), fNextDESCRIBEDelay(1),
fTotNumPacketsReceived(~0), fInterPacketGapMaxTime(interPacketGapMaxTime),
fServerSupportsGetParameter(False), fLastCommandWasPLAY(False), fResetOnNextLivenessTest(False),
fLivenessCommandTask(NULL), fDESCRIBECommandTask(NULL), fSubsessionTimerTask(NULL) {
fLivenessCommandTask(NULL), fDESCRIBECommandTask(NULL), fSubsessionTimerTask(NULL) , fInterPacketGapsTask(NULL) {
if (username != NULL && password != NULL) {
fOurAuthenticator = new Authenticator(username, password);
} else {
@@ -261,11 +264,13 @@ void ProxyRTSPClient::reset() {
envir().taskScheduler().unscheduleDelayedTask(fLivenessCommandTask); fLivenessCommandTask = NULL;
envir().taskScheduler().unscheduleDelayedTask(fDESCRIBECommandTask); fDESCRIBECommandTask = NULL;
envir().taskScheduler().unscheduleDelayedTask(fSubsessionTimerTask); fSubsessionTimerTask = NULL;
envir().taskScheduler().unscheduleDelayedTask(fInterPacketGapsTask); fInterPacketGapsTask = NULL;
fSetupQueueHead = fSetupQueueTail = NULL;
fNumSetupsDone = 0;
fNextDESCRIBEDelay = 1;
fLastCommandWasPLAY = False;
fTotNumPacketsReceived = ~0;
RTSPClient::reset();
}
@@ -392,6 +397,7 @@ void ProxyRTSPClient::continueAfterPLAY(int resultCode) {
envir().taskScheduler().rescheduleDelayedTask(fLivenessCommandTask, 0, sendLivenessCommand, this);
return;
}
if (fInterPacketGapsTask == NULL) checkInterPacketGaps_();
}
void ProxyRTSPClient::scheduleLivenessCommand() {
@@ -432,6 +438,44 @@ void ProxyRTSPClient::sendLivenessCommand(void* clientData) {
#endif
}
void ProxyRTSPClient::checkInterPacketGaps_() {
if (fInterPacketGapMaxTime == 0) return; // we're not checking
// Check each subsession, counting up how many packets have been received:
unsigned newTotNumPacketsReceived = 0;
MediaSubsessionIterator iter(*fOurServerMediaSession.fClientMediaSession);
MediaSubsession* subsession;
while ((subsession = iter.next()) != NULL) {
RTPSource* src = subsession->rtpSource();
if (src == NULL) continue;
newTotNumPacketsReceived += src->receptionStatsDB().totNumPacketsReceived();
}
//envir() << *this << "::doLivenessCheck fTotNumPacketsReceived: " << fTotNumPacketsReceived
// << ", newTotNumPacketsReceived: " << newTotNumPacketsReceived << "\n";
if (newTotNumPacketsReceived == fTotNumPacketsReceived) {
// No additional packets have been received since the last time we
// checked, so end this stream:
// *env << "Closing session, because we stopped receiving packets.\n";
if (fVerbosityLevel > 0) {
envir() << *this << "::doLivenessCheck last packet received: >" << fInterPacketGapMaxTime
<< " seconds ago. Resetting session\n";
}
continueAfterLivenessCommand(1/*hack*/, fServerSupportsGetParameter);
} else {
fTotNumPacketsReceived = newTotNumPacketsReceived;
// Check again, after the specified delay:
fInterPacketGapsTask = envir().taskScheduler().scheduleDelayedTask(fInterPacketGapMaxTime*MILLION, checkInterPacketGaps, this);
}
}
void ProxyRTSPClient::checkInterPacketGaps(void* clientData) {
ProxyRTSPClient* rtspClient = (ProxyRTSPClient*)clientData;
rtspClient->checkInterPacketGaps_();
}
void ProxyRTSPClient::scheduleDESCRIBECommand() {
// Delay 1s, 2s, 4s, 8s ... 256s until sending the next "DESCRIBE". Then, keep delaying a random time from [256..511] seconds:
unsigned secondsToDelay;
@@ -621,6 +665,7 @@ void ProxyServerMediaSubsession::closeStreamSource(FramedSource* inputSource) {
// Send a "PAUSE" for the whole stream.
proxyRTSPClient->sendPauseCommand(fClientMediaSubsession.parentSession(), NULL, proxyRTSPClient->auth());
proxyRTSPClient->fLastCommandWasPLAY = False;
envir().taskScheduler().unscheduleDelayedTask(proxyRTSPClient->fInterPacketGapsTask); proxyRTSPClient->fInterPacketGapsTask = NULL;
}
}
}

View File

@@ -43,7 +43,8 @@ class ProxyRTSPClient: public RTSPClient {
public:
ProxyRTSPClient(class ProxyServerMediaSession& ourServerMediaSession, char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer);
portNumBits tunnelOverHTTPPortNum, int verbosityLevel, int socketNumToServer,
unsigned interPacketGapMaxTime = 0);
virtual ~ProxyRTSPClient();
void continueAfterDESCRIBE(char const* sdpDescription);
@@ -58,6 +59,8 @@ private:
void scheduleLivenessCommand();
static void sendLivenessCommand(void* clientData);
void checkInterPacketGaps_();
static void checkInterPacketGaps(void* clientData);
void scheduleDESCRIBECommand();
static void sendDESCRIBE(void* clientData);
@@ -75,8 +78,10 @@ private:
class ProxyServerMediaSubsession *fSetupQueueHead, *fSetupQueueTail;
unsigned fNumSetupsDone;
unsigned fNextDESCRIBEDelay; // in seconds
unsigned fTotNumPacketsReceived;
unsigned fInterPacketGapMaxTime; // in seconds
Boolean fServerSupportsGetParameter, fLastCommandWasPLAY, fResetOnNextLivenessTest;
TaskToken fLivenessCommandTask, fDESCRIBECommandTask, fSubsessionTimerTask;
TaskToken fLivenessCommandTask, fDESCRIBECommandTask, fSubsessionTimerTask, fInterPacketGapsTask;
};
@@ -85,13 +90,13 @@ createNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSession,
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer);
int socketNumToServer, unsigned interPacketGapMaxTime);
ProxyRTSPClient*
defaultCreateNewProxyRTSPClientFunc(ProxyServerMediaSession& ourServerMediaSession,
char const* rtspURL,
char const* username, char const* password,
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer);
int socketNumToServer, unsigned interPacketGapMaxTime);
class ProxyServerMediaSession: public ServerMediaSession {
public:
@@ -104,7 +109,8 @@ public:
// for streaming the *proxied* (i.e., back-end) stream
int verbosityLevel = 0,
int socketNumToServer = -1,
MediaTranscodingTable* transcodingTable = NULL);
MediaTranscodingTable* transcodingTable = NULL,
unsigned interPacketGapMaxTime = 0);
// Hack: "tunnelOverHTTPPortNum" == 0xFFFF (i.e., all-ones) means: Stream RTP/RTCP-over-TCP, but *not* using HTTP
// "verbosityLevel" == 1 means display basic proxy setup info; "verbosityLevel" == 2 means display RTSP client protocol also.
// If "socketNumToServer" is >= 0, then it is the socket number of an already-existing TCP connection to the server.
@@ -127,6 +133,7 @@ protected:
portNumBits tunnelOverHTTPPortNum, int verbosityLevel,
int socketNumToServer,
MediaTranscodingTable* transcodingTable,
unsigned interPacketGapMaxTime = 0,
createNewProxyRTSPClientFunc* ourCreateNewProxyRTSPClientFunc
= defaultCreateNewProxyRTSPClientFunc,
portNumBits initialPortNum = 6970,

View File

@@ -35,6 +35,7 @@ char* password = NULL;
Boolean proxyREGISTERRequests = False;
char* usernameForREGISTER = NULL;
char* passwordForREGISTER = NULL;
unsigned interPacketGapMaxTime = 0;
static RTSPServer* createRTSPServer(Port port) {
if (proxyREGISTERRequests) {
@@ -51,6 +52,7 @@ void usage() {
<< " [-p <rtspServer-port>]"
<< " [-u <username> <password>]"
<< " [-R] [-U <username-for-REGISTER> <password-for-REGISTER>]"
<< " [-D <max-inter-packet-gap-time>]"
<< " <rtsp-url-1> ... <rtsp-url-n>\n";
exit(1);
}
@@ -151,6 +153,19 @@ int main(int argc, char** argv) {
break;
}
case 'D': { // specify maximum number of seconds to wait for packets:
if (argc > 2 && argv[2][0] != '-') {
if (sscanf(argv[2], "%u", &interPacketGapMaxTime) == 1) {
++argv; --argc;
break;
}
}
// If we get here, the option was specified incorrectly:
usage();
break;
}
default: {
usage();
break;
@@ -221,7 +236,7 @@ int main(int argc, char** argv) {
ServerMediaSession* sms
= ProxyServerMediaSession::createNew(*env, rtspServer,
proxiedStreamURL, streamName,
username, password, tunnelOverHTTPPortNum, verbosityLevel);
username, password, tunnelOverHTTPPortNum, verbosityLevel, -1, NULL, interPacketGapMaxTime);
rtspServer->addServerMediaSession(sms);
char* proxyStreamURL = rtspServer->rtspURL(sms);