rtcp 接收部分
来源:互联网 发布:windows xp自动诊断 编辑:程序博客网 时间:2024/06/05 03:41
rtcp 接收是在rtcp 初始化时注册个scheduler的一个handler,具体调用如下函数
void RTCPInstance::incomingReportHandler1() { do { Boolean callByeHandler = False; int tcpReadStreamSocketNum = fRTCPInterface.nextTCPReadStreamSocketNum(); unsigned char tcpReadStreamChannelId = fRTCPInterface.nextTCPReadStreamChannelId(); unsigned packetSize = 0; unsigned numBytesRead; struct sockaddr_in fromAddress; Boolean packetReadWasIncomplete; if (fNumBytesAlreadyRead >= maxRTCPPacketSize) { envir() << "RTCPInstance error: Hit limit when reading incoming packet over TCP. Increase \"maxRTCPPacketSize\"\n"; break; } Boolean readResult = fRTCPInterface.handleRead(&fInBuf[fNumBytesAlreadyRead], maxRTCPPacketSize - fNumBytesAlreadyRead, numBytesRead, fromAddress, packetReadWasIncomplete); if (packetReadWasIncomplete) { fNumBytesAlreadyRead += numBytesRead; return; // more reads are needed to get the entire packet } else { // normal case: We've read the entire packet packetSize = fNumBytesAlreadyRead + numBytesRead; fNumBytesAlreadyRead = 0; // for next time } if (!readResult) break; // Ignore the packet if it was looped-back from ourself: Boolean packetWasFromOurHost = False; if (RTCPgs()->wasLoopedBackFromUs(envir(), fromAddress)) { packetWasFromOurHost = True; // 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 && !packetWasFromOurHost) { // This packet is assumed to have been received via unicast (because we're a SSM source, and SSM receivers send back RTCP "RR" // packets via unicast). 'Reflect' the packet by resending it to the multicast group, so that any other receivers can also // get to see it. // 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. // NOTE: The test for "!packetWasFromOurHost" means that we won't reflect RTCP packets that come from other processes on // the same host as us. The reason for this is that the 'packet size' test above is not 100% reliable; some packets // that were truly looped back from us might not be detected as such, and this might lead to infinite forwarding/receiving // of some packets. To avoid this possibility, we only reflect RTCP packets that we know for sure originated elsewhere. // (Note, though, that if we ever re-enable the code in "Groupsock::multicastSendOnly()", then we could remove the test for // "!packetWasFromOurHost".) fRTCPInterface.sendPacket(pkt, packetSize); fHaveJustSentPacket = True; fLastPacketSentSize = packetSize; }#ifdef DEBUG fprintf(stderr, "[%p]saw incoming RTCP packet", this); if (tcpReadStreamSocketNum < 0) { // Note that "fromAddress" is valid only if we're receiving over UDP (not over TCP): fprintf(stderr, " (from address %s, port %d)", AddressString(fromAddress).val(), ntohs(fromAddress.sin_port)); } fprintf(stderr, "\n"); 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(*(u_int32_t*)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(*(u_int32_t*)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(*(u_int32_t*)pkt); ADVANCE(4); unsigned NTPlsw = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned rtpTimestamp = ntohl(*(u_int32_t*)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(*(u_int32_t*)pkt); ADVANCE(4); // We care only about reports about our own transmission, not others' if (senderSSRC == fSink->SSRC()) { unsigned lossStats = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned highestReceived = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned jitter = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned timeLastSR = ntohl(*(u_int32_t*)pkt); ADVANCE(4); unsigned timeSinceLastSR = ntohl(*(u_int32_t*)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 UDPfromAddr = 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 handlerfromAddr = 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, arrange for it to be called at the end of this routine. // (Note: We don't call it immediately, in case it happens to cause "this" to be deleted.) if (fByeHandlerTask != NULL && (!fByeHandleActiveParticipantsOnly || (fSource != NULL && fSource->receptionStatsDB().lookup(reportSenderSSRC) != NULL) || (fSink != NULL && fSink->transmissionStatsDB().lookup(reportSenderSSRC) != NULL))) { callByeHandler = True; } // 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 DEBUGfprintf(stderr, "extraneous %d bytes at end of RTCP packet!\n", packetSize);#endifbreak; } rtcpHdr = ntohl(*(u_int32_t*)pkt); if ((rtcpHdr & 0xC0000000) != 0x80000000) {#ifdef DEBUGfprintf(stderr, "bad RTCP subpacket: header 0x%08x\n", rtcpHdr);#endifbreak; } } 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); // Finally, if we need to call a "BYE" handler, do so now (in case it causes "this" to get deleted): if (callByeHandler && fByeHandlerTask != NULL/*sanity check*/) { TaskFunc* byeHandler = fByeHandlerTask; fByeHandlerTask = NULL; // because we call the handler only once, by default (*byeHandler)(fByeHandlerClientData); } } while (0);}
- rtcp 接收部分
- 接收RTCP包的流程
- RTCP
- RTCP
- RTCP
- RTCP
- RTCP
- rtcp
- RTCP
- UART(接收部分)
- RTP RTCP 客户端接收RTSP中媒体数据
- RTP RTCP 客户端接收RTSP中媒体数据
- 串口接收数据部分代码
- 统计文件未接收的部分
- Zigbee ZED接收,与部分NWK
- android 4.4短信接收部分的变化
- android 4.4短信接收部分的变化
- fpga hdmi接收和发送部分调试
- Linux基础学习3
- SSO(三) cas自定义登录页面
- Effective Objective-C 2.0: Class-Continuation Category == Class Extention
- iOS快速更新drawRect方法
- PL-SQL存储过程 ppt课件
- rtcp 接收部分
- 令人惊讶!Java是最快的服务器端Web应用开发语言
- 交通灯管理系统
- Java之父评价C语言之父:我用尽了形容词
- 网络协议之二(IP网际协议)
- java连接池配置详解
- i2c总线测试程序
- Android学习总结(第二周)
- ubuntu wifi 反复询问密码问题