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

📄 rtspclient.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	+ 20; // max int length      char* sdpBuf = new char[sdpBufSize];      sprintf(sdpBuf, sdpFmt,	      byte1, byte2, byte3, byte4,	      url,	      byte1, byte2, byte3, byte4,	      (unsigned)(mh_duration/1000000),	      videoPid);            char* result = strDup(sdpBuf);      delete[] sdpBuf; delete[] currentWord;      delete[] cmd;      return result;    }    ////////// END Kasenna BS //////////        delete[] cmd;    return strDup(bodyStart);  } while (0);    delete[] cmd;  if (fDescribeStatusCode == 0) fDescribeStatusCode = 2;  return NULL;}char* RTSPClient::describeWithPassword(char const* url,		       char const* username, char const* password) {  Authenticator authenticator;  authenticator.setUsernameAndPassword(username, password);  char* describeResult = describeURL(url, &authenticator);  if (describeResult != NULL) {    // We are already authorized    return describeResult;  }  // The "realm" field should have been filled in:  if (authenticator.realm() == NULL) {    // We haven't been given enough information to try again, so fail:    return NULL;  }  // Try again:  describeResult = describeURL(url, &authenticator);  if (describeResult != NULL) {    // The authenticator worked, so use it in future requests:    fCurrentAuthenticator = authenticator;  }  return describeResult;}char* RTSPClient::sendOptionsCmd(char const* url) {  char* result = NULL;  char* cmd = NULL;  do {    if (!openConnectionFromURL(url)) break;    // Send the OPTIONS command:    char* const cmdFmt =      "OPTIONS %s RTSP/1.0\r\n"      "CSeq: %d\r\n"      "%s"#ifdef SUPPORT_REAL_RTSP      REAL_OPTIONS_HEADERS#endif      "\r\n";    unsigned cmdSize = strlen(cmdFmt)      + strlen(url)      + 20 /* max int len */      + fUserAgentHeaderStrSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    url,	    ++fCSeq,	    fUserAgentHeaderStr);    if (!sendRequest(cmd, "OPTIONS")) break;    // Get the response from the server:    unsigned bytesRead; unsigned responseCode;    char* firstLine; char* nextLineStart;    if (!getResponse("OPTIONS", bytesRead, responseCode, firstLine, nextLineStart)) break;    // Look for a "Public:" header (which will contain our result str):    char* lineStart;    while (1) {      lineStart = nextLineStart;      if (lineStart == NULL) break;      nextLineStart = getLine(lineStart);      if (_strncasecmp(lineStart, "Public: ", 8) == 0) {	delete[] result; result = strDup(&lineStart[8]);#ifdef SUPPORT_REAL_RTSP      } else if (_strncasecmp(lineStart, "RealChallenge1: ", 16) == 0) {	delete[] fRealChallengeStr; fRealChallengeStr = strDup(&lineStart[16]);#endif      }    }  } while (0);  delete[] cmd;  return result;}static Boolean isAbsoluteURL(char const* url) {  // Assumption: "url" is absolute if it contains a ':', before any  // occurrence of '/'  while (*url != '\0' && *url != '/') {    if (*url == ':') return True;    ++url;  }  return False;}void RTSPClient::constructSubsessionURL(MediaSubsession const& subsession,					char const*& prefix,					char const*& separator,					char const*& suffix) {  // Figure out what the URL describing "subsession" will look like.  // The URL is returned in three parts: prefix; separator; suffix  //##### NOTE: This code doesn't really do the right thing if "fBaseURL"  // doesn't end with a "/", and "subsession.controlPath()" is relative.  // The right thing would have been to truncate "fBaseURL" back to the  // rightmost "/", and then add "subsession.controlPath()".  // In practice, though, each "DESCRIBE" response typically contains  // a "Content-Base:" header that consists of "fBaseURL" followed by  // a "/", in which case this code ends up giving the correct result.  // However, we should really fix this code to do the right thing, and  // also check for and use the "Content-Base:" header appropriately. #####  prefix = fBaseURL;  if (prefix == NULL) prefix = "";  suffix = subsession.controlPath();  if (suffix == NULL) suffix = "";  if (isAbsoluteURL(suffix)) {    prefix = separator = "";  } else {    unsigned prefixLen = strlen(prefix);    separator = (prefix[prefixLen-1] == '/' || suffix[0] == '/') ? "" : "/";  }}Boolean RTSPClient::announceSDPDescription(char const* url,					   char const* sdpDescription,					   Authenticator* authenticator) {  char* cmd = NULL;  do {    if (!openConnectionFromURL(url)) break;    // Send the ANNOUNCE command:    // First, construct an authenticator string:    fCurrentAuthenticator.reset();    char* authenticatorStr      = createAuthenticatorString(authenticator, "ANNOUNCE", url);    char* const cmdFmt =      "ANNOUNCE %s RTSP/1.0\r\n"      "CSeq: %d\r\n"      "Content-Type: application/sdp\r\n"      "%s"      "Content-length: %d\r\n\r\n"      "%s";	    // Note: QTSS hangs if an "ANNOUNCE" contains a "User-Agent:" field (go figure), so don't include one here    unsigned sdpSize = strlen(sdpDescription);    unsigned cmdSize = strlen(cmdFmt)      + strlen(url)      + 20 /* max int len */      + strlen(authenticatorStr)      + 20 /* max int len */      + sdpSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    url,	    ++fCSeq,	    authenticatorStr,	    sdpSize,	    sdpDescription);    delete[] authenticatorStr;    if (!sendRequest(cmd, "ANNOUNCE")) break;    // Get the response from the server:    unsigned bytesRead; unsigned responseCode;    char* firstLine; char* nextLineStart;    if (!getResponse("ANNOUNCE", bytesRead, responseCode, firstLine, nextLineStart,		     False /*don't check for response code 200*/)) break;    // Inspect the first line to check whether it's a result code 200    if (responseCode != 200) {      checkForAuthenticationFailure(responseCode, nextLineStart, authenticator);      envir().setResultMsg("cannot handle ANNOUNCE response: ", firstLine);      break;    }    delete[] cmd;    return True;  } while (0);  delete[] cmd;  return False;}Boolean RTSPClient::announceWithPassword(char const* url, char const* sdpDescription,		       char const* username, char const* password) {  Authenticator authenticator;  authenticator.setUsernameAndPassword(username, password);  if (announceSDPDescription(url, sdpDescription, &authenticator)) {    // We are already authorized    return True;  }  // The "realm" field should have been filled in:  if (authenticator.realm() == NULL) {    // We haven't been given enough information to try again, so fail:    return False;  }  // Try again:  Boolean secondTrySuccess    = announceSDPDescription(url, sdpDescription, &authenticator);  if (secondTrySuccess) {    // The authenticator worked, so use it in future requests:    fCurrentAuthenticator = authenticator;  }  return secondTrySuccess;}Boolean RTSPClient::setupMediaSubsession(MediaSubsession& subsession,					 Boolean streamOutgoing,					 Boolean streamUsingTCP) {  char* cmd = NULL;  char* setupStr = NULL;  do {    // Construct the SETUP command:    // First, construct an authenticator string:    char* authenticatorStr      = createAuthenticatorString(&fCurrentAuthenticator,				  "SETUP", fBaseURL);    // When sending more than one "SETUP" request, include a "Session:"    // header in the 2nd and later "SETUP"s.    char* sessionStr;    if (fLastSessionId != NULL) {      sessionStr = new char[20+strlen(fLastSessionId)];      sprintf(sessionStr, "Session: %s\r\n", fLastSessionId);    } else {      sessionStr = "";    }    char* transportStr = NULL;#ifdef SUPPORT_REAL_RTSP    if (usingRealNetworksChallengeResponse()) {      // Use a special "Transport:" header, and also add a 'challenge response'.      char challenge2[64];      char checksum[34];      RealCalculateChallengeResponse(fRealChallengeStr, challenge2, checksum);      char const* etag = fRealETagStr == NULL ? "" : fRealETagStr;      char* transportHeader;      if (subsession.parentSession().isRealNetworksRDT) {	transportHeader = strDup("Transport: x-pn-tng/tcp;mode=play,rtp/avp/unicast;mode=play\r\n");      } else {	// Use a regular "Transport:" header:	char const* transportHeaderFmt	  = "Transport: RTP/AVP%s%s=%d-%d\r\n";	char const* transportTypeStr;	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();	  transportTypeStr	    = IsMulticastAddress(connectionAddress) ? ";multicast" : ";unicast";	  portTypeStr = ";client_port";	  rtpNumber = subsession.clientPortNum();	  if (rtpNumber == 0) {	    envir().setResultMsg("Client port number unknown\n");	    break;	  }	  rtcpNumber = rtpNumber + 1;	}	unsigned transportHeaderSize = strlen(transportHeaderFmt)	  + strlen(transportTypeStr) + strlen(portTypeStr) + 2*5 /* max port len */;	transportHeader = new char[transportHeaderSize];	sprintf(transportHeader, transportHeaderFmt,		transportTypeStr, portTypeStr, rtpNumber, rtcpNumber);      }      char const* transportFmt =	"%s"	"RealChallenge2: %s, sd=%s\r\n"	"If-Match: %s\r\n";      unsigned transportSize = strlen(transportFmt)	+ strlen(transportHeader)	+ sizeof challenge2 + sizeof checksum	+ strlen(etag);      transportStr = new char[transportSize];      sprintf(transportStr, transportFmt,	      transportHeader,	      challenge2, checksum,	      etag);      delete[] transportHeader;      if (subsession.parentSession().isRealNetworksRDT) {	// 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();	transportTypeStr	  = IsMulticastAddress(connectionAddress) ? ";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;

⌨️ 快捷键说明

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