📄 rtspclient.cpp
字号:
// Look for a "Session:" header (to set our session id), and // a "Transport: " header (to set the server address/port) // For now, ignore other headers. char* lineStart; char* sessionId = new char[fResponseBufferSize]; // ensures we have enough space while (1) { lineStart = nextLineStart; if (lineStart == NULL) break; nextLineStart = getLine(lineStart); if (sscanf(lineStart, "Session: %[^;]", sessionId) == 1) { subsession.sessionId = strDup(sessionId); delete[] fLastSessionId; fLastSessionId = strDup(sessionId); continue; } char* serverAddressStr; portNumBits serverPortNum; unsigned char rtpChannelId, rtcpChannelId; if (parseTransportResponse(lineStart, serverAddressStr, serverPortNum, rtpChannelId, rtcpChannelId)) { delete[] subsession.connectionEndpointName(); subsession.connectionEndpointName() = serverAddressStr; subsession.serverPortNum = serverPortNum; subsession.rtpChannelId = rtpChannelId; subsession.rtcpChannelId = rtcpChannelId; continue; } } delete[] sessionId; if (subsession.sessionId == NULL) { envir().setResultMsg("\"Session:\" header is missing in the response"); break; } if (streamUsingTCP) { // Tell the subsession to receive RTP (and send/receive RTCP) // over the RTSP stream: if (subsession.rtpSource() != NULL) subsession.rtpSource()->setStreamSocket(fInputSocketNum, subsession.rtpChannelId); if (subsession.rtcpInstance() != NULL) subsession.rtcpInstance()->setStreamSocket(fInputSocketNum, subsession.rtcpChannelId); } else { // Normal case. // Set the RTP and RTCP sockets' destination address and port // from the information in the SETUP response: subsession.setDestinations(fServerAddress); } delete[] cmd; return True; } while (0); delete[] cmd; return False;}static char* createScaleString(float scale, float currentScale) { char buf[100]; if (scale == 1.0f && currentScale == 1.0f) { // This is the default value; we don't need a "Scale:" header: buf[0] = '\0'; } else { sprintf(buf, "Scale: %f\r\n", scale); } return strDup(buf);} static char* createRangeString(float start, float end) { char buf[100]; if (start < 0) { // We're resuming from a PAUSE; there's no "Range:" header at all buf[0] = '\0'; } else if (end < 0) { // There's no end time: sprintf(buf, "Range: npt=%.3f-\r\n", start); } else { // There's both a start and an end time; include them both in the "Range:" hdr sprintf(buf, "Range: npt=%.3f-%.3f\r\n", start, end); } return strDup(buf);} static char const* NoSessionErr = "No RTSP session is currently in progress\n";Boolean RTSPClient::playMediaSession(MediaSession& session, float start, float end, float scale) {#ifdef SUPPORT_REAL_RTSP if (session.isRealNetworksRDT) { // This is a RealNetworks stream; set the "Subscribe" parameter before proceeding: char* streamRuleString = RealGetSubscribeRuleString(&session); setMediaSessionParameter(session, "Subscribe", streamRuleString); delete[] streamRuleString; }#endif char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (fLastSessionId == NULL) { envir().setResultMsg(NoSessionErr); break; } // Send the PLAY command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "PLAY", fBaseURL); // And then a "Scale:" string: char* scaleStr = createScaleString(scale, session.scale()); // And then a "Range:" string: char* rangeStr = createRangeString(start, end); char* const cmdFmt = "PLAY %s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "%s" "%s" "\r\n"; unsigned cmdSize = strlen(cmdFmt) + strlen(fBaseURL) + 20 /* max int len */ + strlen(fLastSessionId) + strlen(scaleStr) + strlen(rangeStr) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, fBaseURL, ++fCSeq, fLastSessionId, scaleStr, rangeStr, authenticatorStr, fUserAgentHeaderStr); delete[] scaleStr; delete[] rangeStr; delete[] authenticatorStr; if (!sendRequest(cmd, "PLAY")) break; // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("PLAY", bytesRead, responseCode, firstLine, nextLineStart)) break; // Look for various headers that we understand: char* lineStart; while (1) { lineStart = nextLineStart; if (lineStart == NULL) break; nextLineStart = getLine(lineStart); if (parseScaleHeader(lineStart, session.scale())) break; } delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::playMediaSubsession(MediaSubsession& subsession, float start, float end, float scale, Boolean hackForDSS) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (subsession.sessionId == NULL) { envir().setResultMsg(NoSessionErr); break; } // Send the PLAY command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "PLAY", fBaseURL); // And then a "Scale:" string: char* scaleStr = createScaleString(scale, subsession.scale()); // And then a "Range:" string: char* rangeStr = createRangeString(start, end); char* const cmdFmt = "PLAY %s%s%s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "%s" "%s" "\r\n"; char const *prefix, *separator, *suffix; constructSubsessionURL(subsession, prefix, separator, suffix); if (hackForDSS || fServerIsKasenna) { // When "PLAY" is used to inject RTP packets into a DSS // (violating the RTSP spec, btw; "RECORD" should have been used) // the DSS can crash (or hang) if the '/trackid=...' portion of // the URL is present. separator = suffix = ""; } unsigned cmdSize = strlen(cmdFmt) + strlen(prefix) + strlen(separator) + strlen(suffix) + 20 /* max int len */ + strlen(subsession.sessionId) + strlen(scaleStr) + strlen(rangeStr) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, prefix, separator, suffix, ++fCSeq, subsession.sessionId, scaleStr, rangeStr, authenticatorStr, fUserAgentHeaderStr); delete[] scaleStr; delete[] rangeStr; delete[] authenticatorStr; if (!sendRequest(cmd, "PLAY")) break; // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("PLAY", bytesRead, responseCode, firstLine, nextLineStart)) break; // Look for various headers that we understand: char* lineStart; while (1) { lineStart = nextLineStart; if (lineStart == NULL) break; nextLineStart = getLine(lineStart); if (parseRTPInfoHeader(lineStart, subsession.rtpInfo.trackId, subsession.rtpInfo.seqNum, subsession.rtpInfo.timestamp)) { continue; } if (parseScaleHeader(lineStart, subsession.scale())) continue; } delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::pauseMediaSession(MediaSession& session) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (fLastSessionId == NULL) { envir().setResultMsg(NoSessionErr); break; } // Send the PAUSE command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "PAUSE", fBaseURL); char* const cmdFmt = "PAUSE %s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "\r\n"; unsigned cmdSize = strlen(cmdFmt) + strlen(fBaseURL) + 20 /* max int len */ + strlen(fLastSessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, fBaseURL, ++fCSeq, fLastSessionId, authenticatorStr, fUserAgentHeaderStr); delete[] authenticatorStr; if (!sendRequest(cmd, "PAUSE")) break; if (fTCPStreamIdCount == 0) { // When TCP streaming, don't look for a response // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("PAUSE", bytesRead, responseCode, firstLine, nextLineStart)) break; } delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::pauseMediaSubsession(MediaSubsession& subsession) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (subsession.sessionId == NULL) { envir().setResultMsg(NoSessionErr); break; } // Send the PAUSE command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "PAUSE", fBaseURL); char* const cmdFmt = "PAUSE %s%s%s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "%s" "%s" "\r\n"; char const *prefix, *separator, *suffix; constructSubsessionURL(subsession, prefix, separator, suffix); if (fServerIsKasenna) separator = suffix = ""; unsigned cmdSize = strlen(cmdFmt) + strlen(prefix) + strlen(separator) + strlen(suffix) + 20 /* max int len */ + strlen(subsession.sessionId) + strlen(authenticatorStr) + fUserAgentHeaderStrSize; cmd = new char[cmdSize]; sprintf(cmd, cmdFmt, prefix, separator, suffix, ++fCSeq, subsession.sessionId, authenticatorStr, fUserAgentHeaderStr); delete[] authenticatorStr; if (!sendRequest(cmd, "PAUSE")) break; if (fTCPStreamIdCount == 0) { // When TCP streaming, don't look for a response // Get the response from the server: unsigned bytesRead; unsigned responseCode; char* firstLine; char* nextLineStart; if (!getResponse("PAUSE", bytesRead, responseCode, firstLine, nextLineStart)) break; } delete[] cmd; return True; } while (0); delete[] cmd; return False;}Boolean RTSPClient::recordMediaSubsession(MediaSubsession& subsession) { char* cmd = NULL; do { // First, make sure that we have a RTSP session in progress if (subsession.sessionId == NULL) { envir().setResultMsg(NoSessionErr); break; } // Send the RECORD command: // First, construct an authenticator string: char* authenticatorStr = createAuthenticatorString(&fCurrentAuthenticator, "RECORD", fBaseURL); char* const cmdFmt = "RECORD %s%s%s RTSP/1.0\r\n" "CSeq: %d\r\n" "Session: %s\r\n" "Range: npt=0-\r\n" "%s" "%s" "\r\n"; char const *prefix, *separator, *suffix; constructSubsessionURL(subsession, prefix, separator, suffix); unsigned cmdSize = strlen(cmdFmt) + strlen(prefix) + strlen(separator) + strlen(suffix) + 20 /* max int len */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -