[Live-devel] patch for rtspclient to support speed header
Anon Sricharoenchai
anon.hui at gmail.com
Thu Jun 25 04:35:12 PDT 2009
Hi,
rtspclient should support "Speed: " header.
It is easy to implement.
The attached file is the patch for this.
Thank you,
Anon.
-------------- next part --------------
diff -urN liblivemedia-2008.07.25.orig/liveMedia/MediaSession.cpp liblivemedia-2008.07.25.develop/liveMedia/MediaSession.cpp
--- liblivemedia-2008.07.25.orig/liveMedia/MediaSession.cpp 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/liveMedia/MediaSession.cpp 2009-06-25 14:44:39.000000000 +0700
@@ -63,7 +63,7 @@
: Medium(env),
fSubsessionsHead(NULL), fSubsessionsTail(NULL),
fConnectionEndpointName(NULL), fMaxPlayStartTime(0.0f), fMaxPlayEndTime(0.0f),
- fScale(1.0f), fMediaSessionType(NULL), fSessionName(NULL), fSessionDescription(NULL),
+ fSpeed(1.0f), fScale(1.0f), fMediaSessionType(NULL), fSessionName(NULL), fSessionDescription(NULL),
fControlPath(NULL) {
#ifdef SUPPORT_REAL_RTSP
RealInitSDPAttributes(this);
@@ -549,7 +549,7 @@
fCpresent(False), fRandomaccessindication(False),
fConfig(NULL), fMode(NULL), fSpropParameterSets(NULL),
fPlayStartTime(0.0), fPlayEndTime(0.0),
- fVideoWidth(0), fVideoHeight(0), fVideoFPS(0), fNumChannels(1), fScale(1.0f), fNPT_PTS_Offset(0.0f),
+ fVideoWidth(0), fVideoHeight(0), fVideoFPS(0), fNumChannels(1), fSpeed(1.0f), fScale(1.0f), fNPT_PTS_Offset(0.0f),
fRTPSocket(NULL), fRTCPSocket(NULL),
fRTPSource(NULL), fRTCPInstance(NULL), fReadSource(NULL) {
rtpInfo.seqNum = 0; rtpInfo.timestamp = 0; rtpInfo.infoIsNew = False;
diff -urN liblivemedia-2008.07.25.orig/liveMedia/RTSPClient.cpp liblivemedia-2008.07.25.develop/liveMedia/RTSPClient.cpp
--- liblivemedia-2008.07.25.orig/liveMedia/RTSPClient.cpp 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/liveMedia/RTSPClient.cpp 2009-06-25 18:16:08.000000000 +0700
@@ -1011,6 +1011,28 @@
return False;
}
+static char* createSpeedString(float speed, float currentSpeed) {
+ char buf[100];
+ if (speed == 1.0f && currentSpeed == 1.0f) {
+ // This is the default value; we don't need a "Speed:" header:
+ buf[0] = '\0';
+ } else {
+ Locale("C", LC_NUMERIC);
+ // Eventhough the default decimal-point is 6, but there's no limit on big
+ // value.
+ // While this may not be injected by streaming server.
+ // But the client application may be injected in some situation, for
+ // example,
+ // * One may write some web application that accept the query,
+ // "rtsp-proxy.cgi?speed=2.0&url=...". rtsp-proxy.cgi may call
+ // this rtsp client library with arbitrary speed value, without knowing
+ // what range of value is safe.
+ snprintf(buf, sizeof(buf)/sizeof(buf[0]), "Speed: %f\r\n", speed);
+ }
+
+ return strDup(buf);
+}
+
static char* createScaleString(float scale, float currentScale) {
char buf[100];
if (scale == 1.0f && currentScale == 1.0f) {
@@ -1045,7 +1067,8 @@
static char const* NoSessionErr = "No RTSP session is currently in progress\n";
Boolean RTSPClient::playMediaSession(MediaSession& session,
- float start, float end, float scale) {
+ float start, float end,
+ float scale, float speed) {
#ifdef SUPPORT_REAL_RTSP
if (session.isRealNetworksRDT) {
// This is a RealNetworks stream; set the "Subscribe" parameter before proceeding:
@@ -1067,6 +1090,8 @@
// First, construct an authenticator string:
char* authenticatorStr
= createAuthenticatorString(&fCurrentAuthenticator, "PLAY", fBaseURL);
+ // And then a "Speed:" string:
+ char* speedStr = createSpeedString(speed, session.speed());
// And then a "Scale:" string:
char* scaleStr = createScaleString(scale, session.scale());
// And then a "Range:" string:
@@ -1080,6 +1105,7 @@
"%s"
"%s"
"%s"
+ "%s"
"\r\n";
char const* sessURL = sessionURL(session);
@@ -1087,6 +1113,7 @@
+ strlen(sessURL)
+ 20 /* max int len */
+ strlen(fLastSessionId)
+ + strlen(speedStr)
+ strlen(scaleStr)
+ strlen(rangeStr)
+ strlen(authenticatorStr)
@@ -1096,10 +1123,12 @@
sessURL,
++fCSeq,
fLastSessionId,
+ speedStr,
scaleStr,
rangeStr,
authenticatorStr,
fUserAgentHeaderStr);
+ delete[] speedStr;
delete[] scaleStr;
delete[] rangeStr;
delete[] authenticatorStr;
@@ -1119,6 +1148,7 @@
nextLineStart = getLine(lineStart);
+ if (parseSpeedHeader(lineStart, session.speed())) continue;
if (parseScaleHeader(lineStart, session.scale())) continue;
if (parseRangeHeader(lineStart, session.playStartTime(), session.playEndTime())) continue;
@@ -1153,7 +1183,8 @@
}
Boolean RTSPClient::playMediaSubsession(MediaSubsession& subsession,
- float start, float end, float scale,
+ float start, float end,
+ float scale, float speed,
Boolean hackForDSS) {
char* cmd = NULL;
do {
@@ -1168,6 +1199,8 @@
// First, construct an authenticator string:
char* authenticatorStr
= createAuthenticatorString(&fCurrentAuthenticator, "PLAY", fBaseURL);
+ // And then a "Speed:" string:
+ char* speedStr = createSpeedString(speed, subsession.speed());
// And then a "Scale:" string:
char* scaleStr = createScaleString(scale, subsession.scale());
// And then a "Range:" string:
@@ -1181,6 +1214,7 @@
"%s"
"%s"
"%s"
+ "%s"
"\r\n";
char const *prefix, *separator, *suffix;
@@ -1197,6 +1231,7 @@
+ strlen(prefix) + strlen(separator) + strlen(suffix)
+ 20 /* max int len */
+ strlen(subsession.sessionId)
+ + strlen(speedStr)
+ strlen(scaleStr)
+ strlen(rangeStr)
+ strlen(authenticatorStr)
@@ -1206,10 +1241,12 @@
prefix, separator, suffix,
++fCSeq,
subsession.sessionId,
+ speedStr,
scaleStr,
rangeStr,
authenticatorStr,
fUserAgentHeaderStr);
+ delete[] speedStr;
delete[] scaleStr;
delete[] rangeStr;
delete[] authenticatorStr;
@@ -1229,6 +1266,7 @@
nextLineStart = getLine(lineStart);
+ if (parseSpeedHeader(lineStart, subsession.speed())) continue;
if (parseScaleHeader(lineStart, subsession.scale())) continue;
if (parseRangeHeader(lineStart, subsession._playStartTime(), subsession._playEndTime())) continue;
@@ -2302,6 +2340,14 @@
return True;
}
+Boolean RTSPClient::parseSpeedHeader(char const* line, float& speed) {
+ if (_strncasecmp(line, "Speed: ", 7) != 0) return False;
+ line += 7;
+
+ Locale("C", LC_NUMERIC);
+ return sscanf(line, "%f", &speed) == 1;
+}
+
Boolean RTSPClient::parseScaleHeader(char const* line, float& scale) {
if (_strncasecmp(line, "Scale: ", 7) != 0) return False;
line += 7;
diff -urN liblivemedia-2008.07.25.orig/liveMedia/include/MediaSession.hh liblivemedia-2008.07.25.develop/liveMedia/include/MediaSession.hh
--- liblivemedia-2008.07.25.orig/liveMedia/include/MediaSession.hh 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/liveMedia/include/MediaSession.hh 2009-06-25 14:33:33.000000000 +0700
@@ -44,6 +44,7 @@
char* connectionEndpointName() const { return fConnectionEndpointName; }
char const* CNAME() const { return fCNAME; }
struct in_addr const& sourceFilterAddr() const { return fSourceFilterAddr; }
+ float& speed() { return fSpeed; }
float& scale() { return fScale; }
char* mediaSessionType() const { return fMediaSessionType; }
char* sessionName() const { return fSessionName; }
@@ -103,6 +104,7 @@
float fMaxPlayStartTime;
float fMaxPlayEndTime;
struct in_addr fSourceFilterAddr; // used for SSM
+ float fSpeed; // set from a RTSP "Speed:" header
float fScale; // set from a RTSP "Scale:" header
char* fMediaSessionType; // holds a=type value
char* fSessionName; // holds s=<session name> value
@@ -143,6 +145,7 @@
unsigned short videoHeight() const { return fVideoHeight; }
unsigned videoFPS() const { return fVideoFPS; }
unsigned numChannels() const { return fNumChannels; }
+ float& speed() { return fSpeed; }
float& scale() { return fScale; }
RTPSource* rtpSource() { return fRTPSource; }
@@ -293,6 +296,7 @@
// frame rate (set by an optional "a=framerate: <fps>" or "a=x-framerate: <fps>" line)
unsigned fNumChannels;
// optionally set by "a=rtpmap:" lines for audio sessions. Default: 1
+ float fSpeed; // set from a RTSP "Speed:" header
float fScale; // set from a RTSP "Scale:" header
double fNPT_PTS_Offset; // set by "getNormalPlayTime()"; add this to a PTS to get NPT
diff -urN liblivemedia-2008.07.25.orig/liveMedia/include/RTSPClient.hh liblivemedia-2008.07.25.develop/liveMedia/include/RTSPClient.hh
--- liblivemedia-2008.07.25.orig/liveMedia/include/RTSPClient.hh 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/liveMedia/include/RTSPClient.hh 2009-06-25 14:30:49.000000000 +0700
@@ -90,13 +90,13 @@
Boolean playMediaSession(MediaSession& session,
float start = 0.0f, float end = -1.0f,
- float scale = 1.0f);
+ float scale = 1.0f, float speed = 1.0f);
// Issues an aggregate RTSP "PLAY" command on "session".
// Returns True iff this command succeeds
// (Note: start=-1 means 'resume'; end=-1 means 'play to end')
Boolean playMediaSubsession(MediaSubsession& subsession,
float start = 0.0f, float end = -1.0f,
- float scale = 1.0f,
+ float scale = 1.0f, float speed = 1.0f,
Boolean hackForDSS = False);
// Issues a RTSP "PLAY" command on "subsession".
// Returns True iff this command succeeds
@@ -184,6 +184,7 @@
unsigned char& rtpChannelId,
unsigned char& rtcpChannelId);
Boolean parseRTPInfoHeader(char*& line, u_int16_t& seqNum, u_int32_t& timestamp);
+ Boolean parseSpeedHeader(char const* line, float& speed);
Boolean parseScaleHeader(char const* line, float& scale);
Boolean parseGetParameterHeader(char const* line,
const char* param,
diff -urN liblivemedia-2008.07.25.orig/testProgs/openRTSP.cpp liblivemedia-2008.07.25.develop/testProgs/openRTSP.cpp
--- liblivemedia-2008.07.25.orig/testProgs/openRTSP.cpp 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/testProgs/openRTSP.cpp 2009-06-25 14:54:18.000000000 +0700
@@ -60,7 +60,7 @@
Boolean clientStartPlayingSession(Medium* client,
MediaSession* session) {
- extern double initialSeekTime, duration, scale;
+ extern double initialSeekTime, duration, scale, speed;
double endTime = initialSeekTime;
if (scale > 0) {
if (duration <= 0) endTime = -1.0f;
@@ -72,7 +72,7 @@
if (client == NULL || session == NULL) return False;
RTSPClient* rtspClient = (RTSPClient*)client;
- return rtspClient->playMediaSession(*session, (float)initialSeekTime, (float)endTime, (float)scale);
+ return rtspClient->playMediaSession(*session, (float)initialSeekTime, (float)endTime, (float)scale, (float)speed);
}
Boolean clientTearDownSession(Medium* client,
diff -urN liblivemedia-2008.07.25.orig/testProgs/playCommon.cpp liblivemedia-2008.07.25.develop/testProgs/playCommon.cpp
--- liblivemedia-2008.07.25.orig/testProgs/playCommon.cpp 2008-07-25 07:40:05.000000000 +0700
+++ liblivemedia-2008.07.25.develop/testProgs/playCommon.cpp 2009-06-25 14:53:53.000000000 +0700
@@ -68,6 +68,7 @@
double durationSlop = -1.0; // extra seconds to play at the end
double initialSeekTime = 0.0f;
double scale = 1.0f;
+double speed = 1.0f;
unsigned interPacketGapMaxTime = 0;
unsigned totNumPacketsReceived = ~0; // used if checking inter-packet gaps
Boolean playContinuously = False;
@@ -108,7 +109,7 @@
<< " [-u <username> <password>"
<< (allowProxyServers ? " [<proxy-server> [<proxy-server-port>]]" : "")
<< "]" << (supportCodecSelection ? " [-A <audio-codec-rtp-payload-format-code>|-M <mime-subtype-name>]" : "")
- << " [-s <initial-seek-time>] [-z <scale>]"
+ << " [-s <initial-seek-time>] [-z <scale>] [-Z <bandwidth-scale>]"
<< " [-w <width> -h <height>] [-f <frames-per-second>] [-y] [-H] [-Q [<measurement-interval>]] [-F <filename-prefix>] [-b <file-sink-buffer-size>] [-B <input-socket-buffer-size>] [-I <input-interface-ip-address>] [-m] <url> (or " << progName << " -o [-V] <url>)\n";
//##### Add "-R <dest-rtsp-url>" #####
shutdown();
@@ -429,6 +430,16 @@
break;
}
+ case 'Z': { // speed (trick play)
+ float arg;
+ if (sscanf(argv[2], "%g", &arg) != 1 || arg == 0.0f) {
+ usage();
+ }
+ speed = arg;
+ ++argv; --argc;
+ break;
+ }
+
default: {
usage();
break;
More information about the live-devel
mailing list