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

📄 rtcp.cpp

📁 H.264 RTSP 串流(live 555)視窗版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      fNumBytesAlreadyRead = 0; // for next time    }    if (!readResult) break;    // Ignore the packet if it was looped-back from ourself:    if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) {      // However, we still want to handle incoming RTCP packets from      // *other processes* on the same machine.  To distinguish this      // case from a true loop-back, check whether we've just sent a      // packet of the same size.  (This check isn't perfect, but it seems      // to be the best we can do.)      if (fHaveJustSentPacket && fLastPacketSentSize == packetSize) {	// This is a true loop-back:	fHaveJustSentPacket = False;	break; // ignore this packet      }    }    unsigned char* pkt = fInBuf;    if (fIsSSMSource) {      // This packet was received via unicast.  'Reflect' it by resending      // it to the multicast group.      // NOTE: Denial-of-service attacks are possible here.      // Users of this software may wish to add their own,      // application-specific mechanism for 'authenticating' the      // validity of this packet before reflecting it.      fRTCPInterface.sendPacket(pkt, packetSize);      fHaveJustSentPacket = True;      fLastPacketSentSize = packetSize;    }#ifdef DEBUG    fprintf(stderr, "[%p]saw incoming RTCP packet (from address %s, port %d)\n", this, our_inet_ntoa(fromAddress.sin_addr), ntohs(fromAddress.sin_port));    for (unsigned i = 0; i < packetSize; ++i) {      if (i%4 == 0) fprintf(stderr, " ");      fprintf(stderr, "%02x", pkt[i]);    }    fprintf(stderr, "\n");#endif    int totPacketSize = IP_UDP_HDR_SIZE + packetSize;    // Check the RTCP packet for validity:    // It must at least contain a header (4 bytes), and this header    // must be version=2, with no padding bit, and a payload type of    // SR (200) or RR (201):    if (packetSize < 4) break;    unsigned rtcpHdr = ntohl(*(unsigned*)pkt);    if ((rtcpHdr & 0xE0FE0000) != (0x80000000 | (RTCP_PT_SR<<16))) {#ifdef DEBUG      fprintf(stderr, "rejected bad RTCP packet: header 0x%08x\n", rtcpHdr);#endif      break;    }    // Process each of the individual RTCP 'subpackets' in (what may be)    // a compound RTCP packet.    int typeOfPacket = PACKET_UNKNOWN_TYPE;    unsigned reportSenderSSRC = 0;    Boolean packetOK = False;    while (1) {      unsigned rc = (rtcpHdr>>24)&0x1F;      unsigned pt = (rtcpHdr>>16)&0xFF;      unsigned length = 4*(rtcpHdr&0xFFFF); // doesn't count hdr      ADVANCE(4); // skip over the header      if (length > packetSize) break;      // Assume that each RTCP subpacket begins with a 4-byte SSRC:      if (length < 4) break; length -= 4;      reportSenderSSRC = ntohl(*(unsigned*)pkt); ADVANCE(4);      Boolean subPacketOK = False;      switch (pt) {        case RTCP_PT_SR: {#ifdef DEBUG	  fprintf(stderr, "SR\n");#endif	  if (length < 20) break; length -= 20;	  // Extract the NTP timestamp, and note this:	  unsigned NTPmsw = ntohl(*(unsigned*)pkt); ADVANCE(4);	  unsigned NTPlsw = ntohl(*(unsigned*)pkt); ADVANCE(4);	  unsigned rtpTimestamp = ntohl(*(unsigned*)pkt); ADVANCE(4);	  if (fSource != NULL) {	    RTPReceptionStatsDB& receptionStats	      = fSource->receptionStatsDB();	    receptionStats.noteIncomingSR(reportSenderSSRC,					  NTPmsw, NTPlsw, rtpTimestamp);	  }	  ADVANCE(8); // skip over packet count, octet count	  // If a 'SR handler' was set, call it now:	  if (fSRHandlerTask != NULL) (*fSRHandlerTask)(fSRHandlerClientData);	  // The rest of the SR is handled like a RR (so, no "break;" here)	}        case RTCP_PT_RR: {#ifdef DEBUG	  fprintf(stderr, "RR\n");#endif	  unsigned reportBlocksSize = rc*(6*4);	  if (length < reportBlocksSize) break;	  length -= reportBlocksSize;          if (fSink != NULL) {	    // Use this information to update stats about our transmissions:            RTPTransmissionStatsDB& transmissionStats = fSink->transmissionStatsDB();            for (unsigned i = 0; i < rc; ++i) {              unsigned senderSSRC = ntohl(*(unsigned*)pkt); ADVANCE(4);              // We care only about reports about our own transmission, not others'              if (senderSSRC == fSink->SSRC()) {                unsigned lossStats = ntohl(*(unsigned*)pkt); ADVANCE(4);                unsigned highestReceived = ntohl(*(unsigned*)pkt); ADVANCE(4);                unsigned jitter = ntohl(*(unsigned*)pkt); ADVANCE(4);                unsigned timeLastSR = ntohl(*(unsigned*)pkt); ADVANCE(4);                unsigned timeSinceLastSR = ntohl(*(unsigned*)pkt); ADVANCE(4);                transmissionStats.noteIncomingRR(reportSenderSSRC, fromAddress,						 lossStats,						 highestReceived, jitter,						 timeLastSR, timeSinceLastSR);              } else {                ADVANCE(4*5);              }            }          } else {            ADVANCE(reportBlocksSize);          }	  if (pt == RTCP_PT_RR) { // i.e., we didn't fall through from 'SR'	    // If a 'RR handler' was set, call it now:	    // Specific RR handler:	    if (fSpecificRRHandlerTable != NULL) {	      netAddressBits fromAddr;	      portNumBits fromPortNum;	      if (tcpReadStreamSocketNum < 0) {		// Normal case: We read the RTCP packet over UDP		fromAddr = fromAddress.sin_addr.s_addr;		fromPortNum = ntohs(fromAddress.sin_port);	      } else {		// Special case: We read the RTCP packet over TCP (interleaved)		// Hack: Use the TCP socket and channel id to look up the handler		fromAddr = tcpReadStreamSocketNum;		fromPortNum = tcpReadStreamChannelId;	      }	      Port fromPort(fromPortNum);	      RRHandlerRecord* rrHandler		= (RRHandlerRecord*)(fSpecificRRHandlerTable->Lookup(fromAddr, (~0), fromPort));	      if (rrHandler != NULL) {		if (rrHandler->rrHandlerTask != NULL) {		  (*(rrHandler->rrHandlerTask))(rrHandler->rrHandlerClientData);		}	      }	    }	    // General RR handler:	    if (fRRHandlerTask != NULL) (*fRRHandlerTask)(fRRHandlerClientData);	  }	  subPacketOK = True;	  typeOfPacket = PACKET_RTCP_REPORT;	  break;	}        case RTCP_PT_BYE: {#ifdef DEBUG	  fprintf(stderr, "BYE\n");#endif	  // If a 'BYE handler' was set, call it now:	  TaskFunc* byeHandler = fByeHandlerTask;	  if (byeHandler != NULL	      && (!fByeHandleActiveParticipantsOnly		  || (fSource != NULL		      && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL)		  || (fSink != NULL		      && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) {	    fByeHandlerTask = NULL;	        // we call this only once by default	    (*byeHandler)(fByeHandlerClientData);	  }	  // We should really check for & handle >1 SSRCs being present #####	  subPacketOK = True;	  typeOfPacket = PACKET_BYE;	  break;	}	// Later handle SDES, APP, and compound RTCP packets #####        default:#ifdef DEBUG	  fprintf(stderr, "UNSUPPORTED TYPE(0x%x)\n", pt);#endif	  subPacketOK = True;	  break;      }      if (!subPacketOK) break;      // need to check for (& handle) SSRC collision! ######ifdef DEBUG      fprintf(stderr, "validated RTCP subpacket (type %d): %d, %d, %d, 0x%08x\n", typeOfPacket, rc, pt, length, reportSenderSSRC);#endif      // Skip over any remaining bytes in this subpacket:      ADVANCE(length);      // Check whether another RTCP 'subpacket' follows:      if (packetSize == 0) {	packetOK = True;	break;      } else if (packetSize < 4) {#ifdef DEBUG	fprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);#endif	break;      }      rtcpHdr = ntohl(*(unsigned*)pkt);      if ((rtcpHdr & 0xC0000000) != 0x80000000) {#ifdef DEBUG	fprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);#endif	break;      }    }    if (!packetOK) {#ifdef DEBUG      fprintf(stderr, "rejected bad RTCP subpacket: header 0x%08x\n", rtcpHdr);#endif      break;    } else {#ifdef DEBUG      fprintf(stderr, "validated entire RTCP packet\n");#endif    }    onReceive(typeOfPacket, totPacketSize, reportSenderSSRC);  } while (0);}void RTCPInstance::onReceive(int typeOfPacket, int totPacketSize,			     unsigned ssrc) {  fTypeOfPacket = typeOfPacket;  fLastReceivedSize = totPacketSize;  fLastReceivedSSRC = ssrc;  int members = (int)numMembers();  int senders = (fSink != NULL) ? 1 : 0;  OnReceive(this, // p	    this, // e	    &members, // members	    &fPrevNumMembers, // pmembers	    &senders, // senders	    &fAveRTCPSize, // avg_rtcp_size	    &fPrevReportTime, // tp	    dTimeNow(), // tc	    fNextReportTime);}void RTCPInstance::sendReport() {  // Hack: Don't send a SR during those (brief) times when the timestamp of the  // next outgoing RTP packet has been preset, to ensure that that timestamp gets  // used for that outgoing packet. (David Bertrand, 2006.07.18)  if (fSink != NULL && fSink->nextTimestampHasBeenPreset()) return;#ifdef DEBUG  fprintf(stderr, "sending REPORT\n");#endif  // Begin by including a SR and/or RR report:  addReport();  // Then, include a SDES:  addSDES();  // Send the report:  sendBuiltPacket();  // Periodically clean out old members from our SSRC membership database:  const unsigned membershipReapPeriod = 5;  if ((++fOutgoingReportCount) % membershipReapPeriod == 0) {    unsigned threshold = fOutgoingReportCount - membershipReapPeriod;    fKnownMembers->reapOldMembers(threshold);  }}void RTCPInstance::sendBYE() {#ifdef DEBUG  fprintf(stderr, "sending BYE\n");#endif  // The packet must begin with a SR and/or RR report:  addReport();  addBYE();  sendBuiltPacket();}void RTCPInstance::sendBuiltPacket() {#ifdef DEBUG  fprintf(stderr, "sending RTCP packet\n");  unsigned char* p = fOutBuf->packet();  for (unsigned i = 0; i < fOutBuf->curPacketSize(); ++i) {    if (i%4 == 0) fprintf(stderr," ");    fprintf(stderr, "%02x", p[i]);  }  fprintf(stderr, "\n");#endif  unsigned reportSize = fOutBuf->curPacketSize();  fRTCPInterface.sendPacket(fOutBuf->packet(), reportSize);  fOutBuf->resetOffset();  fLastSentSize = IP_UDP_HDR_SIZE + reportSize;  fHaveJustSentPacket = True;  fLastPacketSentSize = reportSize;}int RTCPInstance::checkNewSSRC() {  return fKnownMembers->noteMembership(fLastReceivedSSRC,				       fOutgoingReportCount);}void RTCPInstance::removeLastReceivedSSRC() {  removeSSRC(fLastReceivedSSRC, False/*keep stats around*/);}void RTCPInstance::removeSSRC(u_int32_t ssrc, Boolean alsoRemoveStats) {  fKnownMembers->remove(ssrc);  if (alsoRemoveStats) {    // Also, remove records of this SSRC from any reception or transmission stats    if (fSource != NULL) fSource->receptionStatsDB().removeRecord(ssrc);    if (fSink != NULL) fSink->transmissionStatsDB().removeRecord(ssrc);  }}void RTCPInstance::onExpire(RTCPInstance* instance) {  instance->onExpire1();}

⌨️ 快捷键说明

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