📄 ppffsrc.cpp
字号:
} pCompoundEnd = pCompound + ulCompoundLen; UINT8 uchVersion; UINT16 unLength; UINT8 uchType; BYTE* uchOff; do { uchOff = pCompound; uchVersion = (*uchOff++ & 0xc0) >> 6; uchType = *uchOff++; unLength = *uchOff++ << 8; unLength |= *uchOff++; // If it's our own RR, just ignore! if (RTCP_RR == uchType) { UINT32 ulRrSsrc; ulRrSsrc = ((UINT32)*uchOff++)<<24; ulRrSsrc |= ((UINT32)*uchOff++)<<16; ulRrSsrc |= ((UINT32)*uchOff++)<<8; ulRrSsrc |= ((UINT32)*uchOff++); if (ulRrSsrc == m_ulThisSrcID) { // this is our own RR goto done; } } pCompound = (pCompound + ((unLength + 1) * 4)); } while (pCompound < pCompoundEnd && uchVersion == 2); if (pCompound!= pCompoundEnd) { HX_ASSERT(uchVersion == 2); HX_ASSERT(pCompound > pCompoundEnd); HX_ASSERT(pCompound < pCompoundEnd); HX_ASSERT(FALSE && "invalid RTCP length"); /* something is worng */ goto done; } /* * This may be a compound RTCP packet so keep unpacking until we * have unpacked everything. */ while (pNext && pNext < (pFirst + pBuf->GetSize())) { RTCPPacket pkt; pNext = pkt.unpack(pNext, (pFirst + pBuf->GetSize()) - pNext); // erase: Look in rmartsp rtpwrap.h unpack // sometimes sdes_data is NULL for some reason. if (NULL == pNext) { HX_ASSERT(FALSE && "sdes_data empty"); continue; } switch (pkt.packet_type) { case RTCP_SR: { // get the right source from ssrc if (!GetStreamBySSRC(pkt.sr_ssrc, pStrm)) { /* * Unless we receive at least one RTP pkt (which can * be used to make sure payload type is the same), don't * take any SR */ goto done; } HX_ASSERT(pStrm); pStrm->m_bHeardSinceLastTime = TRUE; pStrm->m_ulNumRRIntervals = 0; if (!pStrm->m_bMadeCut) { goto done; } if (!pStrm->IsRMStream()) { pStrm->m_Syncer.HandleRTCPSync(NTPTime(pkt.ntp_sec, pkt.ntp_frac), pkt.rtp_ts); }#ifdef _SYNC_TRACE if (m_sfile) { fprintf(m_sfile, "syncing ssrc(%u): TS(%u) -> %u\n", pkt.sr_ssrc, pStrm->m_Syncer.GetSyncOffsetRTP(), pStrm->m_Syncer.GetSyncOffsetHX()); fflush(m_sfile); }#endif // _SYNC_TRACE // it's better come from sender of RTP pkt if (pStrm->m_ulSSRC != pkt.sr_ssrc) { HX_ASSERT(FALSE && "wrong ssrc in SR"); goto done; } /************* *** need to be tested later **************/ // save SR ts // the middle 32 bits out of 64 in the NTP timestamp pStrm->m_ulLSR = pkt.ntp_sec << 16; pStrm->m_ulLSR |= pkt.ntp_frac; // save current time for later use pStrm->m_ulLastSRArrivalTime = HX_GET_TICKCOUNT(); } break; case RTCP_BYE: { // In this RTCP, there should be nothing after Bye // UINT32* pByeSsrc; // remove all the source in this bye for (UINT32 i = 0; i < pkt.count; i++) { pByeSsrc = pkt.bye_src + i;#ifdef XXXGo_DEBUG if (m_pFFLog) { fprintf(m_pFFLog, "BYE!!!\n"); }#endif // we don't want to end this stream right away as it still // has some packets in the buffer that needs to be played if (!MarkAsEnd(*pByeSsrc)) { if (!RemoveSource(*pByeSsrc)) { // this is BYE from non-sender RemoveMember(*pByeSsrc); } } } theErr = HXR_OK; if (m_pByePkt && m_pRTCPInterval) { // RTCP_BYE is pending. m_pRTCPInterval->SetCurNumMembers(m_pRTCPInterval->GetCurNumMembers()+1); } goto done; } break; case RTCP_SDES: { if (!pStrm) { HX_ASSERT(pMember); if (!pMember) { goto done; } } else { pMember = pStrm; } /******************* * get at leat CNAME ********************/ // look for list of sdes item with source id CHXSimpleList* pSdesList; SDESItem* pSdes; if (pkt.m_mapSDESSources.Lookup(pMember->m_ulSSRC, (void*&)pSdesList)) { // set up variables to iterate over list int nNumElements = pSdesList->GetCount(); LISTPOSITION lpPosition = pSdesList->GetHeadPosition(); // Go through all list elements deleting the data at each node. for (int i=0; i < nNumElements; i++) { pSdes = (SDESItem*) pSdesList->GetNext(lpPosition); // set up CHXString** ppStr = NULL; if (SDES_CNAME == pSdes->sdes_type) ppStr = &pMember->m_pCName; else if (SDES_NAME == pSdes->sdes_type) ppStr = &pMember->m_pName; else if (SDES_EMAIL == pSdes->sdes_type) ppStr = &pMember->m_pEmail; else if (SDES_PHONE == pSdes->sdes_type) ppStr = &pMember->m_pPhone; else if (SDES_LOC == pSdes->sdes_type) ppStr = &pMember->m_pLoc; else if (SDES_TOOL == pSdes->sdes_type) ppStr = &pMember->m_pTool; else if (SDES_NOTE == pSdes->sdes_type) ppStr = &pMember->m_pNote; else if (SDES_PRIV== pSdes->sdes_type) ppStr = &pMember->m_pPriv; else HX_ASSERT(FALSE && "wrong sdes_type"); if (!*ppStr) { *ppStr = new CHXString(pSdes->data); } else if (**ppStr != (const char*)pSdes->data) { // since we keyed off from ssrc, ssrc might // have been changed (restart/collision) // XXXGH need to update maps /* char sz[100]; memset(sz, 0, 100); wsprintf( sz, "what we had = %s\n" "new one = %s ", (*ppStr)->GetBuffer(10), pSdes->data); ::MessageBox( NULL, sz, "SDES not the same", MB_OK ); HX_ASSERT(FALSE && "sdes not the same"); */ } ppStr = NULL; /* * XXXGH * somehow, we have to store ssrc that comes with * SDES, so we can correctly map it */ } } } break; case RTCP_RR: { if (pkt.rr_ssrc == m_ulThisSrcID) { // just ignore our own RR. goto done; } else { if (!GetStreamBySSRC(pkt.rr_ssrc, pStrm)) { // this is not a sender if (!GetMember(pkt.rr_ssrc, pMember)) { AddNewMember(pkt.rr_ssrc, pMember); }#ifdef XXXGo_DEBUG if (m_pFFLog) { fprintf(m_pFFLog, "put %d %d\n", pMember->m_binInfo.lBin, pMember->m_binInfo.pos); fflush(m_pFFLog); }#endif m_MemberTimeoutBins.PutInNewestBin(pMember, pMember->m_binInfo); } } } break; case RTCP_APP: { //::MessageBox( NULL, NULL, "RTCP_APP", MB_OK ); } break; default: break; } } // end while done: HX_RELEASE(pBuf); if (m_pRTCPSock) { m_pRTCPSock->Read(1024); } return theErr;}/** */HX_RESULTCPurePlaySource::UpdateStatistics(IHXRegistry* pReg, ULONG32 ulTimeNow){ /* * If we have had the registry ID of the place to put * our bandwidth info set then use it and set the proper * bandwidth for this stream */ CStream* pStream = NULL; CHXMapLongToObj::Iterator i; // if GetStreamByStrmId() doesn't find the Stream, it will return NULL for (i = m_SsrcToStream.Begin(); i != m_SsrcToStream.End(); ++i) { pStream = (CStream*) (*i); HX_ASSERT(pStream); // for each stream, update the stats if (pStream && (pStream->m_bMadeCut) && (pStream->m_ulClipBandwidthID != 0)) { pStream->UpdateStatistics(pReg, ulTimeNow); } } return HXR_OK;}HX_RESULTCPurePlaySource::MakeRR(REF(RTCPPacket) pktRR){/* if (GetNumSrc() == 0) { // it dones't make sense to even try to send RR when there is no sender return HXR_FAIL; }*/ /* * this is a good chance to look at any inactive source and get rid of it * from the map */ CHXMapLongToObj::Iterator i; UINT32 ulSrcCount = 0;// UINT32 ulNumInactive = 0; CStream* pStrm = NULL; for (i = m_SsrcToStream.Begin(); i != m_SsrcToStream.End(); ++i) { pStrm = (CStream*)(*i); if (pStrm->m_bHeardSinceLastTime) { ulSrcCount++; } else { if (pStrm->m_bMadeCut) { // 2 RTCP interval is too small. Once we remove this source, // it will call StreamDone on this stream. so, a little // congestion end up with end of feed. if (++pStrm->m_ulNumRRIntervals >= 5) {#ifdef XXXGo_DEBUG if (m_pFFLog) { fprintf(m_pLogFile, "SenderTimeout! Stream# %u\n", pStrm->m_unStreamNum); fflush(m_pLogFile); }#endif RemoveSource(pStrm->m_ulSSRC);// ulNumInactive++; } } else { // rest of sources can come and go. Much important to get the // number of sources right! if (++pStrm->m_ulNumRRIntervals >= 2) { RemoveSource(pStrm->m_ulSSRC); } } } }#if 0 // if we haven't heard from any of sources for 5 RR intervals, // assume end if ((GetNumSrc() != 0) && (GetNumSrc() == ulNumInactive)) { for (i = m_StrmIdToStrm.Begin(); i != m_StrmIdToStrm.End(); ++i) { RemoveSource(((CStream*)(*i))->m_ulSSRC); } return HXR_FAIL; }#endif pktRR.version_flag = 0x02; // protocol version pktRR.padding_flag = 0; // no padding pktRR.packet_type = RTCP_RR; // this is RR pktRR.rr_ssrc = m_ulThisSrcID; // receiver generating this report // If there is no data transmission or reception to report, just add empty // RR pkt with count = 0 if (0 == ulSrcCount) { pktRR.count = 0; pktRR.length = 1; } else { pktRR.count = (UINT8)ulSrcCount; // 6 bytes / report pktRR.length = 1 + 6 * (UINT16)ulSrcCount; ReceptionReport* pRr = new ReceptionReport[ulSrcCount]; if (!pRr) { return HXR_FAIL; } UINT32 ulCount = 0; for (i = m_SsrcToStream.Begin(); i != m_SsrcToStream.End() && ulCount < ulSrcCount; ++i) { if (((CStream*)(*i))->m_bHeardSinceLastTime) { ((CStream*)(*i))->GetReceptionReport(pRr[ulCount]); ((CStream*)(*i))->m_bHeardSinceLastTime = FALSE; ulCount++; } } HX_ASSERT(ulCount == ulSrcCount); // XXXGo ReceptionReport::static_size() returns 24 because lost is in fact // 24 bits. However, since it is represented as UINT32, I really want 25. // so, calling sizeof() for now.// pktRR.SetReceiverReport(pRr, sizeof(ReceptionReport) * ulSrcCount); pktRR.SetReceiverReport(pRr, ulSrcCount); // since SetReceiverReport is making a copy, delete what we have HX_VECTOR_DELETE(pRr); } return HXR_OK;}/** Schdule a callback with a relative time*/voidCPurePlaySource::Schedule(UINT32 ulNextTime, int lEvent){ if (!m_pScheduler) { return; } if (m_hStatusCallbackID != 0) {#ifdef XXXGo_DEBUG if (m_pLogFile) { fprintf(m_pLogFile, "Re - "); fflush(m_pLogFile); } #endif m_pScheduler->Remove(m_hStatusCallbackID); m_hStatusCallbackID = 0; } HX_ASSERT(0 == m_hStatusCallbackID); CRTCPSendStatusCallback* pSSCB = new CRTCPSendStatusCallback(this, lEvent); if (!pSSCB) { return; }#ifdef XXXGo_DEBUG if (m_pLogFile) { fprintf(m_pLogFile, "Schduling (%u)\n", ulNextTime); fflush(m_pLogFile); } #endif pSSCB->AddRef(); m_hStatusCallbackID = m_pScheduler->RelativeEnter(pSSCB, ulNextTime); pSSCB->Release();}voidCPurePlaySource::OnExpire(INT32 lEvent){#ifdef XXXGo_DEBUG if (m_pLogFile) { fprintf(m_pLogFile, "\tOnExpire\n"); fflush(m_pLogFile); } #endif // Remove any member that timeout. CleanupMemberTable(); /* * This func is responsible for deciding whether to send an RTCP report or * BYE packet now, or to reschedule transmission. * It is also responsible for updating the pmembers, initial, tp, and * avg_rtcp_size state var's. This func should be called upon expiration * of the event timer. */ UINT32 ulInterval = 0; /* Interval */// double tn; /* Next transmit time */ BOOL bSendIt = FALSE; /* flag for sending pkt */ UINT32 ulCurTime = GetCurrentSchedulerTimeInMsec(m_pScheduler); // HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime(); // in msec.// UINT32 ulCurTime = lTime.tv_sec * 1000 + lTime.tv_usec / 1000; UINT32 ulLastTime = m_pRTCPInterval->GetLastRTCPTime(); // ulNumMembers + ulNumSenders = Total num members UINT32 ulNumMembers = m_SsrcToMember.GetCount(); UINT32 ulNumSenders = GetTrueNumSrc(); /* * To compensate for OPTION B converging to a value below the intended * average. */ double const COMPENSATION = 2.71828 - 1.5; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -