⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtspclient.cpp

📁 c++实现的流媒体库,和mplayer结合就可以实现多媒体的网络播放,属于开源项目,很值得研究.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	// Also, tell the RDT source to use the RTSP TCP socket:	RealRDTSource* rdtSource	  = (RealRDTSource*)(subsession.readSource());	rdtSource->setInputSocket(fInputSocketNum);      }    }#endif    char const *prefix, *separator, *suffix;    constructSubsessionURL(subsession, prefix, separator, suffix);    char* transportFmt;    if (strcmp(subsession.protocolName(), "UDP") == 0) {      char const* setupFmt = "SETUP %s%s RTSP/1.0\r\n";      unsigned setupSize = strlen(setupFmt)        + strlen(prefix) + strlen (separator);      setupStr = new char[setupSize];      sprintf(setupStr, setupFmt, prefix, separator);      transportFmt = "Transport: RAW/RAW/UDP%s%s%s=%d-%d\r\n";    } else {      char const* setupFmt = "SETUP %s%s%s RTSP/1.0\r\n";      unsigned setupSize = strlen(setupFmt)        + strlen(prefix) + strlen (separator) + strlen(suffix);      setupStr = new char[setupSize];      sprintf(setupStr, setupFmt, prefix, separator, suffix);      transportFmt = "Transport: RTP/AVP%s%s%s=%d-%d\r\n";    }    if (transportStr == NULL) {      // Construct a "Transport:" header.      char const* transportTypeStr;      char const* modeStr = streamOutgoing ? ";mode=receive" : "";          // Note: I think the above is nonstandard, but DSS wants it this way      char const* portTypeStr;      unsigned short rtpNumber, rtcpNumber;      if (streamUsingTCP) { // streaming over the RTSP connection	transportTypeStr = "/TCP;unicast";	portTypeStr = ";interleaved";	rtpNumber = fTCPStreamIdCount++;	rtcpNumber = fTCPStreamIdCount++;      } else { // normal RTP streaming      	unsigned connectionAddress = subsession.connectionEndpointAddress();	Boolean requestMulticastStreaming = IsMulticastAddress(connectionAddress)	  || (connectionAddress == 0 && forceMulticastOnUnspecified);	transportTypeStr = requestMulticastStreaming ? ";multicast" : ";unicast";	portTypeStr = ";client_port";	rtpNumber = subsession.clientPortNum();	if (rtpNumber == 0) {	  envir().setResultMsg("Client port number unknown\n");	  break;	}	rtcpNumber = rtpNumber + 1;      }      unsigned transportSize = strlen(transportFmt)	+ strlen(transportTypeStr) + strlen(modeStr) + strlen(portTypeStr) + 2*5 /* max port len */;      transportStr = new char[transportSize];      sprintf(transportStr, transportFmt,	      transportTypeStr, modeStr, portTypeStr, rtpNumber, rtcpNumber);    }    // (Later implement more, as specified in the RTSP spec, sec D.1 #####)    char* const cmdFmt =      "%s"      "CSeq: %d\r\n"      "%s"      "%s"      "%s"      "%s"      "\r\n";    unsigned cmdSize = strlen(cmdFmt)      + strlen(setupStr)      + 20 /* max int len */      + strlen(transportStr)      + strlen(sessionStr)      + strlen(authenticatorStr)      + fUserAgentHeaderStrSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    setupStr,	    ++fCSeq,	    transportStr,	    sessionStr,	    authenticatorStr,	    fUserAgentHeaderStr);    delete[] authenticatorStr;    if (sessionStr[0] != '\0') delete[] sessionStr;    delete[] setupStr; delete[] transportStr;    // And then send it:    if (!sendRequest(cmd, "SETUP")) break;    // Get the response from the server:    unsigned bytesRead; unsigned responseCode;    char* firstLine; char* nextLineStart;    if (!getResponse("SETUP", bytesRead, responseCode, firstLine, nextLineStart)) break;    // 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    unsigned cLength = 0;    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);	// Also look for an optional "; timeout = " parameter following this:	char* afterSessionId	  = lineStart + strlen(sessionId) + strlen ("Session: ");;	int timeoutVal;	if (sscanf(afterSessionId, "; timeout = %d", &timeoutVal) == 1) {	  fSessionTimeoutParameter = timeoutVal;	}	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;      }      // Also check for a "Content-Length:" header.  Some weird servers include this      // in the RTSP "SETUP" response.      if (sscanf(lineStart, "Content-Length: %d", &cLength) == 1) continue;    }     delete[] sessionId;    if (subsession.sessionId == NULL) {      envir().setResultMsg("\"Session:\" header is missing in the response");      break;    }    // If we saw a "Content-Length:" header in the response, then discard whatever    // included data it refers to:    if (cLength > 0) {      char* dummyBuf = new char[cLength];      getResponse1(dummyBuf, cLength);      delete[] dummyBuf;    }    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 (if present):       netAddressBits destAddress = subsession.connectionEndpointAddress();      if (destAddress == 0) destAddress = fServerAddress;      subsession.setDestinations(destAddress);    }    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 {    Locale("C", LC_NUMERIC);    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:    Locale("C", LC_NUMERIC);    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    Locale("C", LC_NUMERIC);    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";    char const* sessURL = sessionURL(session);    unsigned cmdSize = strlen(cmdFmt)      + strlen(sessURL)      + 20 /* max int len */      + strlen(fLastSessionId)      + strlen(scaleStr)      + strlen(rangeStr)      + strlen(authenticatorStr)      + fUserAgentHeaderStrSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    sessURL,	    ++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())) continue;      if (parseRangeHeader(lineStart, session.playStartTime(), session.playEndTime())) continue;      u_int16_t seqNum; u_int32_t timestamp;      if (parseRTPInfoHeader(lineStart, seqNum, timestamp)) {	// This is data for our first subsession.  Fill it in, and do the same for our other subsessions:	MediaSubsessionIterator iter(session);	MediaSubsession* subsession;	while ((subsession = iter.next()) != NULL) {	  subsession->rtpInfo.seqNum = seqNum;	  subsession->rtpInfo.timestamp = timestamp;	  subsession->rtpInfo.infoIsNew = True;	  if (!parseRTPInfoHeader(lineStart, seqNum, timestamp)) break;	}	continue;      }    }    if (fTCPStreamIdCount == 0) { // we're not receiving RTP-over-TCP      // Arrange to handle incoming requests sent by the server      envir().taskScheduler().turnOnBackgroundReadHandling(fInputSocketNum,	   (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);    }    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 (parseScaleHeader(lineStart, subsession.scale())) continue;      if (parseRangeHeader(lineStart, subsession._playStartTime(), subsession._playEndTime())) continue;      u_int16_t seqNum; u_int32_t timestamp;      if (parseRTPInfoHeader(lineStart, seqNum, timestamp)) {	subsession.rtpInfo.seqNum = seqNum;	subsession.rtpInfo.timestamp = timestamp;	subsession.rtpInfo.infoIsNew = True;	continue;      }    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -