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

📄 mediasession.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
						 fRTPPayloadFormat,						 fRTPTimestampFrequency,						 mimeType);	delete[] mimeType;      } else if (  strcmp(fCodecName, "PCMU") == 0 // PCM u-law audio		   || strcmp(fCodecName, "GSM") == 0 // GSM audio		   || strcmp(fCodecName, "PCMA") == 0 // PCM a-law audio		   || strcmp(fCodecName, "L16") == 0 // 16-bit linear audio		   || strcmp(fCodecName, "MP1S") == 0 // MPEG-1 System Stream		   || strcmp(fCodecName, "MP2P") == 0 // MPEG-2 Program Stream		   || strcmp(fCodecName, "L8") == 0 // 8-bit linear audio		   || strcmp(fCodecName, "G726-16") == 0 // G.726, 16 kbps		   || strcmp(fCodecName, "G726-24") == 0 // G.726, 24 kbps		   || strcmp(fCodecName, "G726-32") == 0 // G.726, 32 kbps		   || strcmp(fCodecName, "G726-40") == 0 // G.726, 40 kbps		   || strcmp(fCodecName, "SPEEX") == 0 // SPEEX audio		   || strcmp(fCodecName, "T140") == 0 // T.140 text (RFC 4103)		   ) {	createSimpleRTPSource = True;	useSpecialRTPoffset = 0;      } else if (useSpecialRTPoffset >= 0) {	// We don't know this RTP payload format, but try to receive	// it using a 'SimpleRTPSource' with the specified header offset:	createSimpleRTPSource = True;      } else {	env().setResultMsg("RTP payload format unknown or not supported");	break;      }      if (createSimpleRTPSource) {	char* mimeType	  = new char[strlen(mediumName()) + strlen(codecName()) + 2] ;	sprintf(mimeType, "%s/%s", mediumName(), codecName());	fReadSource = fRTPSource	  = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,				       fRTPTimestampFrequency, mimeType,				       (unsigned)useSpecialRTPoffset,				       doNormalMBitRule);	delete[] mimeType;      }    }    if (fReadSource == NULL) {      env().setResultMsg("Failed to create read source");      break;    }    // Finally, create our RTCP instance. (It starts running automatically)    if (fRTPSource != NULL) {      // If bandwidth is specified, use it and add 5% for RTCP overhead.      // Otherwise make a guess at 500 kbps.      unsigned totSessionBandwidth	= fBandwidth ? fBandwidth + fBandwidth / 20 : 500;      fRTCPInstance = RTCPInstance::createNew(env(), fRTCPSocket,					      totSessionBandwidth,					      (unsigned char const*)					      fParent.CNAME(),					      NULL /* we're a client */,					      fRTPSource);      if (fRTCPInstance == NULL) {	env().setResultMsg("Failed to create RTCP instance");	break;      }    }    return True;  } while (0);  delete fRTPSocket; fRTPSocket = NULL;  delete fRTCPSocket; fRTCPSocket = NULL;  Medium::close(fRTCPInstance); fRTCPInstance = NULL;  Medium::close(fReadSource); fReadSource = fRTPSource = NULL;  fClientPortNum = 0;  return False;}void MediaSubsession::deInitiate() {  Medium::close(fRTCPInstance);  fRTCPInstance = NULL;  Medium::close(fReadSource); // this is assumed to also close fRTPSource  fReadSource = NULL; fRTPSource = NULL;  delete fRTCPSocket; delete fRTPSocket;  fRTCPSocket = fRTPSocket = NULL;}Boolean MediaSubsession::setClientPortNum(unsigned short portNum) {  if (fReadSource != NULL) {    env().setResultMsg("A read source has already been created");    return False;  }  fClientPortNum = portNum;  return True;}netAddressBits MediaSubsession::connectionEndpointAddress() const {  do {    // Get the endpoint name from with us, or our parent session:    char const* endpointString = connectionEndpointName();    if (endpointString == NULL) {      endpointString = parentSession().connectionEndpointName();    }    if (endpointString == NULL) break;    // Now, convert this name to an address, if we can:    NetAddressList addresses(endpointString);    if (addresses.numAddresses() == 0) break;    return *(netAddressBits*)(addresses.firstAddress()->data());  } while (0);  // No address known:  return 0;}void MediaSubsession::setDestinations(netAddressBits defaultDestAddress) {  // Get the destination address from the connection endpoint name  // (This will be 0 if it's not known, in which case we use the default)  netAddressBits destAddress = connectionEndpointAddress();  if (destAddress == 0) destAddress = defaultDestAddress;  struct in_addr destAddr; destAddr.s_addr = destAddress;  // The destination TTL remains unchanged:  int destTTL = ~0; // means: don't change  if (fRTPSocket != NULL) {    Port destPort(serverPortNum);    fRTPSocket->changeDestinationParameters(destAddr, destPort, destTTL);  }  if (fRTCPSocket != NULL && !isSSM()) {    // Note: For SSM sessions, the dest address for RTCP was already set.    Port destPort(serverPortNum+1);    fRTCPSocket->      changeDestinationParameters(destAddr, destPort, destTTL);  }}double MediaSubsession::getNormalPlayTime(struct timeval const& presentationTime) {  // First, check whether our "RTPSource" object has already been synchronized using RTCP.  // If it hasn't, then - as a special case - we need to use the RTP timestamp to compute the NPT.  if (rtpSource() == NULL || rtpSource()->timestampFrequency() == 0) return 0.0; // no RTP source, or bad freq!  if (!rtpSource()->hasBeenSynchronizedUsingRTCP()) {    if (!rtpInfo.infoIsNew) return 0.0; // the "rtpInfo" structure has not been filled in    u_int32_t timestampOffset = rtpSource()->curPacketRTPTimestamp() - rtpInfo.timestamp;    double nptOffset = (timestampOffset/(double)(rtpSource()->timestampFrequency()))*scale();    double npt = playStartTime() + nptOffset;    return npt;  } else {    // Common case: We have been synchronized using RTCP.  This means that the "presentationTime" parameter    // will be accurate, and so we should use this to compute the NPT.    double ptsDouble = (double)(presentationTime.tv_sec + presentationTime.tv_usec/1000000.0);    if (rtpInfo.infoIsNew) {      // This is the first time we've been called with a synchronized presentation time since the "rtpInfo"      // structure was last filled in.  Use this "presentationTime" to compute "fNPT_PTS_Offset":      u_int32_t timestampOffset = rtpSource()->curPacketRTPTimestamp() - rtpInfo.timestamp;      double nptOffset = (timestampOffset/(double)(rtpSource()->timestampFrequency()))*scale();      double npt = playStartTime() + nptOffset;      fNPT_PTS_Offset = npt - ptsDouble*scale();      rtpInfo.infoIsNew = False; // for next time      return npt;    } else {      // Use the precomputed "fNPT_PTS_Offset" to compute the NPT from the PTS:      if (fNPT_PTS_Offset == 0.0) return 0.0; // error: The "rtpInfo" structure was apparently never filled in      return (double)(ptsDouble*scale() + fNPT_PTS_Offset);    }  }}Boolean MediaSubsession::parseSDPLine_c(char const* sdpLine) {  // Check for "c=IN IP4 <connection-endpoint>"  // or "c=IN IP4 <connection-endpoint>/<ttl+numAddresses>"  // (Later, do something with <ttl+numAddresses> also #####)  char* connectionEndpointName = parseCLine(sdpLine);  if (connectionEndpointName != NULL) {    delete[] fConnectionEndpointName;    fConnectionEndpointName = connectionEndpointName;    return True;  }  return False;}Boolean MediaSubsession::parseSDPLine_b(char const* sdpLine) {  // Check for "b=<bwtype>:<bandwidth>" line  // RTP applications are expected to use bwtype="AS"  return sscanf(sdpLine, "b=AS:%u", &fBandwidth) == 1;}Boolean MediaSubsession::parseSDPAttribute_rtpmap(char const* sdpLine) {  // Check for a "a=rtpmap:<fmt> <codec>/<freq>" line:  // (Also check without the "/<freq>"; RealNetworks omits this)  // Also check for a trailing "/<numChannels>".  Boolean parseSuccess = False;  unsigned rtpmapPayloadFormat;  char* codecName = strDupSize(sdpLine); // ensures we have enough space  unsigned rtpTimestampFrequency = 0;  unsigned numChannels = 1;  if (sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u/%u",	     &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency,	     &numChannels) == 4      || sscanf(sdpLine, "a=rtpmap: %u %[^/]/%u",	     &rtpmapPayloadFormat, codecName, &rtpTimestampFrequency) == 3      || sscanf(sdpLine, "a=rtpmap: %u %s",		&rtpmapPayloadFormat, codecName) == 2) {    parseSuccess = True;    if (rtpmapPayloadFormat == fRTPPayloadFormat) {      // This "rtpmap" matches our payload format, so set our      // codec name and timestamp frequency:      // (First, make sure the codec name is upper case)      {	Locale l("POSIX");	for (char* p = codecName; *p != '\0'; ++p) *p = toupper(*p);      }      delete[] fCodecName; fCodecName = strDup(codecName);      fRTPTimestampFrequency = rtpTimestampFrequency;      fNumChannels = numChannels;    }  }  delete[] codecName;  return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_control(char const* sdpLine) {  // Check for a "a=control:<control-path>" line:  Boolean parseSuccess = False;  char* controlPath = strDupSize(sdpLine); // ensures we have enough space  if (sscanf(sdpLine, "a=control: %s", controlPath) == 1) {    parseSuccess = True;    delete[] fControlPath; fControlPath = strDup(controlPath);  }  delete[] controlPath;  return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_range(char const* sdpLine) {  // Check for a "a=range:npt=<startTime>-<endTime>" line:  // (Later handle other kinds of "a=range" attributes also???#####)  Boolean parseSuccess = False;  double playStartTime;  double playEndTime;  if (parseRangeAttribute(sdpLine, playStartTime, playEndTime)) {    parseSuccess = True;    if (playStartTime > fPlayStartTime) {      fPlayStartTime = playStartTime;      if (playStartTime > fParent.playStartTime()) {	fParent.playStartTime() = playStartTime;      }    }    if (playEndTime > fPlayEndTime) {      fPlayEndTime = playEndTime;      if (playEndTime > fParent.playEndTime()) {	fParent.playEndTime() = playEndTime;      }    }  }  return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_fmtp(char const* sdpLine) {  // Check for a "a=fmtp:" line:  // TEMP: We check only for a handful of expected parameter names #####  // Later: (i) check that payload format number matches; #####  //        (ii) look for other parameters also (generalize?) #####  do {    if (strncmp(sdpLine, "a=fmtp:", 7) != 0) break; sdpLine += 7;    while (isdigit(*sdpLine)) ++sdpLine;    // The remaining "sdpLine" should be a sequence of    //     <name>=<value>;    // parameter assignments.  Look at each of these.    // First, convert the line to lower-case, to ease comparison:    char* const lineCopy = strDup(sdpLine); char* line = lineCopy;    {      Locale l("POSIX");      for (char* c = line; *c != '\0'; ++c) *c = tolower(*c);    }    while (*line != '\0' && *line != '\r' && *line != '\n') {      unsigned u;      char* valueStr = strDupSize(line);      if (sscanf(line, " auxiliarydatasizelength = %u", &u) == 1) {	fAuxiliarydatasizelength = u;      } else if (sscanf(line, " constantduration = %u", &u) == 1) {	fConstantduration = u;      } else if (sscanf(line, " constantsize; = %u", &u) == 1) {	fConstantsize = u;      } else if (sscanf(line, " crc = %u", &u) == 1) {	fCRC = u;      } else if (sscanf(line, " ctsdeltalength = %u", &u) == 1) {	fCtsdeltalength = u;      } else if (sscanf(line, " de-interleavebuffersize = %u", &u) == 1) {	fDe_interleavebuffersize = u;      } else if (sscanf(line, " dtsdeltalength = %u", &u) == 1) {	fDtsdeltalength = u;      } else if (sscanf(line, " indexdeltalength = %u", &u) == 1) {	fIndexdeltalength = u;      } else if (sscanf(line, " indexlength = %u", &u) == 1) {	fIndexlength = u;      } else if (sscanf(line, " interleaving = %u", &u) == 1) {	fInterleaving = u;      } else if (sscanf(line, " maxdisplacement = %u", &u) == 1) {	fMaxdisplacement = u;      } else if (sscanf(line, " objecttype = %u", &u) == 1) {	fObjecttype = u;      } else if (sscanf(line, " octet-align = %u", &u) == 1) {	fOctetalign = u;      } else if (sscanf(line, " profile-level-id = %x", &u) == 1) {	// Note that the "profile-level-id" parameter is assumed to be hexadecimal	fProfile_level_id = u;      } else if (sscanf(line, " robust-sorting = %u", &u) == 1) {	fRobustsorting = u;      } else if (sscanf(line, " sizelength = %u", &u) == 1) {	fSizelength = u;      } else if (sscanf(line, " streamstateindication = %u", &u) == 1) {	fStreamstateindication = u;      } else if (sscanf(line, " streamtype = %u", &u) == 1) {	fStreamtype = u;      } else if (sscanf(line, " cpresent = %u", &u) == 1) {	fCpresent = u != 0;      } else if (sscanf(line, " randomaccessindication = %u", &u) == 1) {	fRandomaccessindication = u != 0;      } else if (sscanf(line, " config = %[^; \t\r\n]", valueStr) == 1) {	delete[] fConfig; fConfig = strDup(valueStr);      } else if (sscanf(line, " mode = %[^; \t\r\n]", valueStr) == 1) {	delete[] fMode; fMode = strDup(valueStr);      } else if (sscanf(sdpLine, " sprop-parameter-sets = %[^; \t\r\n]", valueStr) == 1) {	// Note: We used "sdpLine" here, because the value is case-sensitive.	delete[] fSpropParameterSets; fSpropParameterSets = strDup(valueStr);      } else {	// Some of the above parameters are Boolean.  Check whether the parameter	// names appear alone, without a "= 1" at the end:	if (sscanf(line, " %[^; \t\r\n]", valueStr) == 1) {	  if (strcmp(valueStr, "octet-align") == 0) {	    fOctetalign = 1;	  } else if (strcmp(valueStr, "cpresent") == 0) {            fCpresent = True;	  } else if (strcmp(valueStr, "crc") == 0) {	    fCRC = 1;	  } else if (strcmp(valueStr, "robust-sorting") == 0) {	    fRobustsorting = 1;	  } else if (strcmp(valueStr, "randomaccessindication") == 0) {	    fRandomaccessindication = True;	  }	}      }      delete[] valueStr;      // Move to the next parameter assignment string:      while (*line != '\0' && *line != '\r' && *line != '\n'	     && *line != ';') ++line;      while (*line == ';') ++line;      // Do the same with sdpLine; needed for finding case sensitive values:      while (*sdpLine != '\0' && *sdpLine != '\r' && *sdpLine != '\n'	     && *sdpLine != ';') ++sdpLine;      while (*sdpLine == ';') ++sdpLine;    }    delete[] lineCopy;    return True;  } while (0);  return False;}Boolean MediaSubsession::parseSDPAttribute_source_filter(char const* sdpLine) {  return parseSourceFilterAttribute(sdpLine, fSourceFilterAddr);}Boolean MediaSubsession::parseSDPAttribute_x_dimensions(char const* sdpLine) {  // Check for a "a=x-dimensions:<width>,<height>" line:  Boolean parseSuccess = False;  int width, height;  if (sscanf(sdpLine, "a=x-dimensions:%d,%d", &width, &height) == 2) {    parseSuccess = True;    fVideoWidth = (unsigned short)width;    fVideoHeight = (unsigned short)height;  }  return parseSuccess;}Boolean MediaSubsession::parseSDPAttribute_framerate(char const* sdpLine) {  // Check for a "a=framerate: <fps>" or "a=x-framerate: <fps>" line:  Boolean parseSuccess = False;  float frate;  int rate;  if (sscanf(sdpLine, "a=framerate: %f", &frate) == 1 || sscanf(sdpLine, "a=framerate:%f", &frate) == 1) {    parseSuccess = True;    fVideoFPS = (unsigned)frate;  } else if (sscanf(sdpLine, "a=x-framerate: %d", &rate) == 1) {    parseSuccess = True;    fVideoFPS = (unsigned)rate;  }  return parseSuccess;}

⌨️ 快捷键说明

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