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

📄 mediasession.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  // Look up the codec name and timestamp frequency for known (static)  // RTP payload formats.  char const* temp = NULL;  switch (rtpPayloadType) {  case 0: {temp = "PCMU"; freq = 8000; nCh = 1; break;}  case 2: {temp = "G726-32"; freq = 8000; nCh = 1; break;}  case 3: {temp = "GSM"; freq = 8000; nCh = 1; break;}  case 4: {temp = "G723"; freq = 8000; nCh = 1; break;}  case 5: {temp = "DVI4"; freq = 8000; nCh = 1; break;}  case 6: {temp = "DVI4"; freq = 16000; nCh = 1; break;}  case 7: {temp = "LPC"; freq = 8000; nCh = 1; break;}  case 8: {temp = "PCMA"; freq = 8000; nCh = 1; break;}  case 9: {temp = "G722"; freq = 8000; nCh = 1; break;}  case 10: {temp = "L16"; freq = 44100; nCh = 2; break;}  case 11: {temp = "L16"; freq = 44100; nCh = 1; break;}  case 12: {temp = "QCELP"; freq = 8000; nCh = 1; break;}  case 14: {temp = "MPA"; freq = 90000; nCh = 1; break;}    // 'number of channels' is actually encoded in the media stream  case 15: {temp = "G728"; freq = 8000; nCh = 1; break;}  case 16: {temp = "DVI4"; freq = 11025; nCh = 1; break;}  case 17: {temp = "DVI4"; freq = 22050; nCh = 1; break;}  case 18: {temp = "G729"; freq = 8000; nCh = 1; break;}  case 25: {temp = "CELB"; freq = 90000; nCh = 1; break;}  case 26: {temp = "JPEG"; freq = 90000; nCh = 1; break;}  case 28: {temp = "NV"; freq = 90000; nCh = 1; break;}  case 31: {temp = "H261"; freq = 90000; nCh = 1; break;}  case 32: {temp = "MPV"; freq = 90000; nCh = 1; break;}  case 33: {temp = "MP2T"; freq = 90000; nCh = 1; break;}  case 34: {temp = "H263"; freq = 90000; nCh = 1; break;}  };  return strDup(temp);}unsigned MediaSession::guessRTPTimestampFrequency(char const* mediumName,						  char const* codecName) {  // By default, we assume that audio sessions use a frequency of 8000,  // video sessions use a frequency of 90000,  // and text sessions use a frequency of 1000.  // Begin by checking for known exceptions to this rule  // (where the frequency is known unambiguously (e.g., not like "DVI4"))  if (strcmp(codecName, "L16") == 0) return 44100;  if (strcmp(codecName, "MPA") == 0      || strcmp(codecName, "MPA-ROBUST") == 0      || strcmp(codecName, "X-MP3-DRAFT-00")) return 90000;  // Now, guess default values:  if (strcmp(mediumName, "video") == 0) return 90000;  else if (strcmp(mediumName, "text") == 0) return 1000;  return 8000; // for "audio", and any other medium}Boolean MediaSession::initiateByMediaType(char const* mimeType,		      MediaSubsession*& resultSubsession,		      int useSpecialRTPoffset) {  // Look through this session's subsessions for media that match "mimeType"  resultSubsession = NULL;  MediaSubsessionIterator iter(*this);  MediaSubsession* subsession;  while ((subsession = iter.next()) != NULL) {    Boolean wasAlreadyInitiated = subsession->readSource() != NULL;    if (!wasAlreadyInitiated) {      // Try to create a source for this subsession:      if (!subsession->initiate(useSpecialRTPoffset)) return False;    }    // Make sure the source's MIME type is one that we handle:    if (strcmp(subsession->readSource()->MIMEtype(), mimeType) != 0) {      if (!wasAlreadyInitiated) subsession->deInitiate();      continue;    }    resultSubsession = subsession;    break; // use this  }  if (resultSubsession == NULL) {    envir().setResultMsg("Session has no usable media subsession");    return False;  }  return True;}////////// MediaSubsessionIterator //////////MediaSubsessionIterator::MediaSubsessionIterator(MediaSession& session)  : fOurSession(session) {  reset();}MediaSubsessionIterator::~MediaSubsessionIterator() {}MediaSubsession* MediaSubsessionIterator::next() {  MediaSubsession* result = fNextPtr;  if (fNextPtr != NULL) fNextPtr = fNextPtr->fNext;  return result;}void MediaSubsessionIterator::reset() {  fNextPtr = fOurSession.fSubsessionsHead;}////////// MediaSubsession //////////MediaSubsession::MediaSubsession(MediaSession& parent)  : sessionId(NULL), serverPortNum(0), sink(NULL), miscPtr(NULL),    fParent(parent), fNext(NULL),    fConnectionEndpointName(NULL),    fClientPortNum(0), fRTPPayloadFormat(0xFF),    fSavedSDPLines(NULL), fMediumName(NULL), fCodecName(NULL), fProtocolName(NULL),    fRTPTimestampFrequency(0), fControlPath(NULL),    fSourceFilterAddr(parent.sourceFilterAddr()), fBandwidth(0),    fAuxiliarydatasizelength(0), fConstantduration(0), fConstantsize(0),    fCRC(0), fCtsdeltalength(0), fDe_interleavebuffersize(0), fDtsdeltalength(0),    fIndexdeltalength(0), fIndexlength(0), fInterleaving(0), fMaxdisplacement(0),    fObjecttype(0), fOctetalign(0), fProfile_level_id(0), fRobustsorting(0),    fSizelength(0), fStreamstateindication(0), fStreamtype(0),    fCpresent(False), fRandomaccessindication(False),    fConfig(NULL), fMode(NULL), fSpropParameterSets(NULL),    fPlayStartTime(0.0), fPlayEndTime(0.0),    fVideoWidth(0), fVideoHeight(0), fVideoFPS(0), fNumChannels(1), fScale(1.0f), fNPT_PTS_Offset(0.0f),    fRTPSocket(NULL), fRTCPSocket(NULL),    fRTPSource(NULL), fRTCPInstance(NULL), fReadSource(NULL) {  rtpInfo.seqNum = 0; rtpInfo.timestamp = 0; rtpInfo.infoIsNew = False;}MediaSubsession::~MediaSubsession() {  deInitiate();  delete[] fConnectionEndpointName; delete[] fSavedSDPLines;  delete[] fMediumName; delete[] fCodecName; delete[] fProtocolName;  delete[] fControlPath; delete[] fConfig; delete[] fMode; delete[] fSpropParameterSets;  delete fNext;}double MediaSubsession::playStartTime() const {  if (fPlayStartTime > 0) return fPlayStartTime;  return fParent.playStartTime();}double MediaSubsession::playEndTime() const {  if (fPlayEndTime > 0) return fPlayEndTime;  return fParent.playEndTime();}Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {  if (fReadSource != NULL) return True; // has already been initiated  do {    if (fCodecName == NULL) {      env().setResultMsg("Codec is unspecified");      break;    }    // Create RTP and RTCP 'Groupsocks' on which to receive incoming data.    // (Groupsocks will work even for unicast addresses)    struct in_addr tempAddr;    tempAddr.s_addr = connectionEndpointAddress();        // This could get changed later, as a result of a RTSP "SETUP"    if (fClientPortNum != 0) {      // The sockets' port numbers were specified for us.  Use these:      fClientPortNum = fClientPortNum&~1; // even      if (isSSM()) {	fRTPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, fClientPortNum);      } else {	fRTPSocket = new Groupsock(env(), tempAddr, fClientPortNum, 255);      }      if (fRTPSocket == NULL) {	env().setResultMsg("Failed to create RTP socket");	break;      }            // Set our RTCP port to be the RTP port +1      portNumBits const rtcpPortNum = fClientPortNum|1;      if (isSSM()) {	fRTCPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, rtcpPortNum);      } else {	fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);      }      if (fRTCPSocket == NULL) {	char tmpBuf[100];	sprintf(tmpBuf, "Failed to create RTCP socket (port %d)", rtcpPortNum);	env().setResultMsg(tmpBuf);	break;      }    } else {      // Port numbers were not specified in advance, so we use ephemeral port numbers.      // Create sockets until we get a port-number pair (even: RTP; even+1: RTCP).      // We need to make sure that we don't keep trying to use the same bad port numbers over and over again.      // so we store bad sockets in a table, and delete them all when we're done.      HashTable* socketHashTable = HashTable::create(ONE_WORD_HASH_KEYS);      if (socketHashTable == NULL) break;      Boolean success = False;      NoReuse dummy; // ensures that our new ephemeral port number won't be one that's already in use      while (1) {	// Create a new socket:	if (isSSM()) {	  fRTPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, 0);	} else {	  fRTPSocket = new Groupsock(env(), tempAddr, 0, 255);	}	if (fRTPSocket == NULL) {	  env().setResultMsg("MediaSession::initiate(): unable to create RTP and RTCP sockets");	  break;	}	// Get the client port number, and check whether it's even (for RTP):	Port clientPort(0);	if (!getSourcePort(env(), fRTPSocket->socketNum(), clientPort)) {	  break;	}	fClientPortNum = ntohs(clientPort.num()); 	if ((fClientPortNum&1) != 0) { // it's odd	  // Record this socket in our table, and keep trying:	  unsigned key = (unsigned)fClientPortNum;	  Groupsock* existing = (Groupsock*)socketHashTable->Add((char const*)key, fRTPSocket);	  delete existing; // in case it wasn't NULL	  continue;	}	// Make sure we can use the next (i.e., odd) port number, for RTCP:	portNumBits rtcpPortNum = fClientPortNum|1;	if (isSSM()) {	  fRTCPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, rtcpPortNum);	} else {	  fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);	}	if (fRTCPSocket != NULL) {	  // Success! Use these two sockets.	  success = True;	  break;	} else {	  // We couldn't create the RTCP socket (perhaps that port number's already in use elsewhere?).	  // Record the first socket in our table, and keep trying:	  unsigned key = (unsigned)fClientPortNum;	  Groupsock* existing = (Groupsock*)socketHashTable->Add((char const*)key, fRTPSocket);	  delete existing; // in case it wasn't NULL	  continue;	}      }      // Clean up the socket hash table (and contents):      Groupsock* oldGS;      while ((oldGS = (Groupsock*)socketHashTable->RemoveNext()) != NULL) {	delete oldGS;      }      delete socketHashTable;      if (!success) break; // a fatal error occurred trying to create the RTP and RTCP sockets; we can't continue    }    // Try to use a big receive buffer for RTP - at least 0.1 second of    // specified bandwidth and at least 50 KB    unsigned rtpBufSize = fBandwidth * 25 / 2; // 1 kbps * 0.1 s = 12.5 bytes    if (rtpBufSize < 50 * 1024)      rtpBufSize = 50 * 1024;    increaseReceiveBufferTo(env(), fRTPSocket->socketNum(), rtpBufSize);    // ASSERT: fRTPSocket != NULL && fRTCPSocket != NULL    if (isSSM()) {      // Special case for RTCP SSM: Send RTCP packets back to the source via unicast:      fRTCPSocket->changeDestinationParameters(fSourceFilterAddr,0,~0);    }    // Check "fProtocolName"    if (strcmp(fProtocolName, "UDP") == 0) {      // A UDP-packetized stream (*not* a RTP stream)      fReadSource = BasicUDPSource::createNew(env(), fRTPSocket);      fRTPSource = NULL; // Note!      if (strcmp(fCodecName, "MP2T") == 0) { // MPEG-2 Transport Stream	fReadSource = MPEG2TransportStreamFramer::createNew(env(), fReadSource);	    // this sets "durationInMicroseconds" correctly, based on the PCR values      }    } else {      // Check "fCodecName" against the set of codecs that we support,      // and create our RTP source accordingly      // (Later make this code more efficient, as this set grows #####)      // (Also, add more fmts that can be implemented by SimpleRTPSource#####)      Boolean createSimpleRTPSource = False; // by default; can be changed below      Boolean doNormalMBitRule = False; // default behavior if "createSimpleRTPSource" is True      if (strcmp(fCodecName, "QCELP") == 0) { // QCELP audio	fReadSource =	  QCELPAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,					 fRTPPayloadFormat,					 fRTPTimestampFrequency);	// Note that fReadSource will differ from fRTPSource in this case      } else if (strcmp(fCodecName, "AMR") == 0) { // AMR audio (narrowband)	fReadSource =	  AMRAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,				       fRTPPayloadFormat, 0 /*isWideband*/,				       fNumChannels, fOctetalign, fInterleaving,				       fRobustsorting, fCRC);	// Note that fReadSource will differ from fRTPSource in this case      } else if (strcmp(fCodecName, "AMR-WB") == 0) { // AMR audio (wideband)	fReadSource =	  AMRAudioRTPSource::createNew(env(), fRTPSocket, fRTPSource,				       fRTPPayloadFormat, 1 /*isWideband*/,				       fNumChannels, fOctetalign, fInterleaving,				       fRobustsorting, fCRC);	// Note that fReadSource will differ from fRTPSource in this case      } else if (strcmp(fCodecName, "MPA") == 0) { // MPEG-1 or 2 audio	fReadSource = fRTPSource	  = MPEG1or2AudioRTPSource::createNew(env(), fRTPSocket,					      fRTPPayloadFormat,					      fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "MPA-ROBUST") == 0) { // robust MP3 audio	fRTPSource	  = MP3ADURTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,				       fRTPTimestampFrequency);	if (fRTPSource == NULL) break;	// Add a filter that deinterleaves the ADUs after depacketizing them:	MP3ADUdeinterleaver* deinterleaver	  = MP3ADUdeinterleaver::createNew(env(), fRTPSource);	if (deinterleaver == NULL) break;	// Add another filter that converts these ADUs to MP3 frames:	fReadSource = MP3FromADUSource::createNew(env(), deinterleaver);      } else if (strcmp(fCodecName, "X-MP3-DRAFT-00") == 0) {	// a non-standard variant of "MPA-ROBUST" used by RealNetworks	// (one 'ADU'ized MP3 frame per packet; no headers)	fRTPSource	  = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,				       fRTPTimestampFrequency,				       "audio/MPA-ROBUST" /*hack*/);	if (fRTPSource == NULL) break;	// Add a filter that converts these ADUs to MP3 frames:	fReadSource = MP3FromADUSource::createNew(env(), fRTPSource,						  False /*no ADU header*/);      } else if (strcmp(fCodecName, "MP4A-LATM") == 0) { // MPEG-4 LATM audio	fReadSource = fRTPSource	  = MPEG4LATMAudioRTPSource::createNew(env(), fRTPSocket,					       fRTPPayloadFormat,					       fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "AC3") == 0) { // AC3 audio	fReadSource = fRTPSource	  = AC3AudioRTPSource::createNew(env(), fRTPSocket,					 fRTPPayloadFormat,					 fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "MP4V-ES") == 0) { // MPEG-4 Elem Str vid	fReadSource = fRTPSource	  = MPEG4ESVideoRTPSource::createNew(env(), fRTPSocket,					     fRTPPayloadFormat,					     fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "MPEG4-GENERIC") == 0) {	fReadSource = fRTPSource	  = MPEG4GenericRTPSource::createNew(env(), fRTPSocket,					     fRTPPayloadFormat,					     fRTPTimestampFrequency,					     fMediumName, fMode,					     fSizelength, fIndexlength,					     fIndexdeltalength);      } else if (strcmp(fCodecName, "MPV") == 0) { // MPEG-1 or 2 video	fReadSource = fRTPSource	  = MPEG1or2VideoRTPSource::createNew(env(), fRTPSocket,					      fRTPPayloadFormat,					      fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "MP2T") == 0) { // MPEG-2 Transport Stream	fRTPSource = SimpleRTPSource::createNew(env(), fRTPSocket, fRTPPayloadFormat,						fRTPTimestampFrequency, "video/MP2T",						0, False);	fReadSource = MPEG2TransportStreamFramer::createNew(env(), fRTPSource);	    // this sets "durationInMicroseconds" correctly, based on the PCR values      } else if (strcmp(fCodecName, "H261") == 0) { // H.261	fReadSource = fRTPSource	  = H261VideoRTPSource::createNew(env(), fRTPSocket,					  fRTPPayloadFormat,					  fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "H263-1998") == 0 ||		 strcmp(fCodecName, "H263-2000") == 0) { // H.263+	fReadSource = fRTPSource	  = H263plusVideoRTPSource::createNew(env(), fRTPSocket,					      fRTPPayloadFormat,					      fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "H264") == 0) {	fReadSource = fRTPSource	  = H264VideoRTPSource::createNew(env(), fRTPSocket,					  fRTPPayloadFormat,					  fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "DV") == 0) {	fReadSource = fRTPSource	  = DVVideoRTPSource::createNew(env(), fRTPSocket,					fRTPPayloadFormat,					fRTPTimestampFrequency);      } else if (strcmp(fCodecName, "JPEG") == 0) { // motion JPEG	fReadSource = fRTPSource	  = JPEGVideoRTPSource::createNew(env(), fRTPSocket,					  fRTPPayloadFormat,					  fRTPTimestampFrequency,					  videoWidth(),					  videoHeight());      } else if (strcmp(fCodecName, "X-QT") == 0		 || strcmp(fCodecName, "X-QUICKTIME") == 0) {	// Generic QuickTime streams, as defined in	// <http://developer.apple.com/quicktime/icefloe/dispatch026.html>	char* mimeType	  = new char[strlen(mediumName()) + strlen(codecName()) + 2] ;	sprintf(mimeType, "%s/%s", mediumName(), codecName());	fReadSource = fRTPSource	  = QuickTimeGenericRTPSource::createNew(env(), fRTPSocket,

⌨️ 快捷键说明

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