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

📄 rtspclient.cpp

📁 c++实现的流媒体库,和mplayer结合就可以实现多媒体的网络播放,属于开源项目,很值得研究.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	}            if (fKasennaContentType != NULL	  && strcmp(fKasennaContentType, "PARTNER_41_MPEG-4") == 0) {          char* describeSDP = describeURL(url, authenticator, True);	  	  delete[] currentWord;          delete[] cmd;          return describeSDP;      }            unsigned char byte1 = fServerAddress & 0x000000ff;      unsigned char byte2 = (fServerAddress & 0x0000ff00) >>  8;      unsigned char byte3 = (fServerAddress & 0x00ff0000) >> 16;      unsigned char byte4 = (fServerAddress & 0xff000000) >> 24;            char const* sdpFmt =	"v=0\r\n"	"o=NoSpacesAllowed 1 1 IN IP4 %u.%u.%u.%u\r\n"	"s=%s\r\n"	"c=IN IP4 %u.%u.%u.%u\r\n"	"t=0 0\r\n"	"a=control:*\r\n"	"a=range:npt=0-%llu\r\n"	"m=video 1554 RAW/RAW/UDP 33\r\n"	"a=control:trackID=%d\r\n";      unsigned sdpBufSize = strlen(sdpFmt)	+ 4*3 // IP address	+ strlen(url)	+ 20 // max int length	+ 20; // max int length      char* sdpBuf = new char[sdpBufSize];      sprintf(sdpBuf, sdpFmt,	      byte1, byte2, byte3, byte4,	      url,	      byte1, byte2, byte3, byte4,	      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,		       Boolean allowKasennaProtocol) {  Authenticator authenticator;  authenticator.setUsernameAndPassword(username, password);  char* describeResult = describeURL(url, &authenticator, allowKasennaProtocol);  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, allowKasennaProtocol);  if (describeResult != NULL) {    // The authenticator worked, so use it in future requests:    fCurrentAuthenticator = authenticator;  }  return describeResult;}char* RTSPClient::sendOptionsCmd(char const* url,				 char* username, char* password,				 Authenticator* authenticator) {  char* result = NULL;  char* cmd = NULL;  Boolean haveAllocatedAuthenticator = False;  do {    if (authenticator == NULL) {      // First, check whether "url" contains a username:password to be used      // (and no username,password pair was supplied separately):      if (username == NULL && password == NULL	  && parseRTSPURLUsernamePassword(url, username, password)) {	Authenticator authenticator;	authenticator.setUsernameAndPassword(username, password);	result = sendOptionsCmd(url, username, password, &authenticator);	delete[] username; delete[] password; // they were dynamically allocated	break;      } else if (username != NULL && password != NULL) {	// Use the separately supplied username and password:	authenticator = new Authenticator;	haveAllocatedAuthenticator = True;	authenticator->setUsernameAndPassword(username, password);	result = sendOptionsCmd(url, username, password, authenticator);	if (result != NULL) break; // We are already authorized	// The "realm" field should have been filled in:	if (authenticator->realm() == NULL) {	  // We haven't been given enough information to try again, so fail:	  break;	}	// Try again:      }    }    if (!openConnectionFromURL(url, authenticator)) break;    // Send the OPTIONS command:    // First, construct an authenticator string:    char* authenticatorStr      = createAuthenticatorString(authenticator, "OPTIONS", url);    char* const cmdFmt =      "OPTIONS %s RTSP/1.0\r\n"      "CSeq: %d\r\n"      "%s"      "%s"#ifdef SUPPORT_REAL_RTSP      REAL_OPTIONS_HEADERS#endif      "\r\n";    unsigned cmdSize = strlen(cmdFmt)      + strlen(url)      + 20 /* max int len */      + strlen(authenticatorStr)      + fUserAgentHeaderStrSize;    cmd = new char[cmdSize];    sprintf(cmd, cmdFmt,	    url,	    ++fCSeq,	    authenticatorStr,	    fUserAgentHeaderStr);    delete[] authenticatorStr;    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,		     False /*don't check for response code 200*/)) break;    if (responseCode != 200) {      checkForAuthenticationFailure(responseCode, nextLineStart, authenticator);      envir().setResultMsg("cannot handle OPTIONS response: ", firstLine);      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;  if (haveAllocatedAuthenticator) delete authenticator;  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;}char const* RTSPClient::sessionURL(MediaSession const& session) const {  char const* url = session.controlPath();  if (url == NULL || strcmp(url, "*") == 0) url = fBaseURL;  return url;}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 "sessionURL()"  // doesn't end with a "/", and "subsession.controlPath()" is relative.  // The right thing would have been to truncate "sessionURL()" back to the  // rightmost "/", and then add "subsession.controlPath()".  // In practice, though, each "DESCRIBE" response typically contains  // a "Content-Base:" header that consists of "sessionURL()" 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 = sessionURL(subsession.parentSession());  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, authenticator)) 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,					 Boolean forceMulticastOnUnspecified) {  char* cmd = NULL;  char* setupStr = NULL;  if (fServerIsMicrosoft) {    // Microsoft doesn't send the right endTime on live streams.  Correct this:    char *tmpStr = subsession.parentSession().mediaSessionType();    if (tmpStr != NULL && strncmp(tmpStr, "broadcast", 9) == 0) {      subsession.parentSession().playEndTime() = 0.0;    }  }  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();	  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 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) {

⌨️ 快捷键说明

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