rtcputil.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:21k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxtypes.h"
- #include "hxcom.h"
- #include "hlxclib/string.h"
- #include "rtpwrap.h"
- #include "hxtick.h"
- #include "hxengin.h"
- #include "tconverter.h"
- #include "interval.h"
- #include "ntptime.h"
- #include "rtcputil.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- //#define DUMP_REPORTS
- //#define DUMP_RECEIVE_REPORTS
- //#define DUMP_MEMBER_COUNT
- /* Used in UpdateSeqNo */
- const UINT32 MAX_DROPOUT = 3000;
- const UINT32 MAX_MISORDER = 100;
- const UINT32 MIN_SEQUENTIAL = 2;
- const UINT32 RTP_SEQ_MOD = (1 << 16);
- //ReportHandler::ReportHandler(BOOL bIsSender, BOOL bIsReceiver, UINT32 ulSsrc, UINT32 ulDefaultProbation)
- ReportHandler::ReportHandler(BOOL bIsSender, BOOL bIsReceiver, UINT32 ulSsrc)
- : m_pSenderMe(NULL)
- , m_ulMySsrc(ulSsrc)
- , m_pReceiverMe(NULL)
- // , m_ulDefaultProbation(ulDefaultProbation)
- , m_ulAvgRTCPSize(128)
- , m_bInitialIntervalCalc(TRUE)
- , m_pNTPBase(NULL)
- , m_nRTPTSBase(0)
- , m_pTSConverter(NULL)
- {
- /* it is "either or" in RealSystem */
- HX_ASSERT((bIsSender || bIsReceiver) && !(bIsSender && bIsReceiver));
- if (bIsSender)
- {
- m_pSenderMe = new MyselfAsSender();
- m_pSenderMe->m_ulSsrc = ulSsrc;
- }
- else
- {
- m_pReceiverMe = new MyselfAsReceiver();
- m_pReceiverMe->m_ulSsrc = ulSsrc;;
- }
- }
- ReportHandler::~ReportHandler()
- {
- CHXMapLongToObj::Iterator i;
- for (i = m_mapReceivers.Begin(); i != m_mapReceivers.End(); ++i)
- {
- delete (ReceiverInfo*)(*i);
- }
- for (i = m_mapSenders.Begin(); i != m_mapSenders.End(); ++i)
- {
- delete (ReceptionInfo*)(*i);
- }
- HX_DELETE(m_pSenderMe);
- HX_DELETE(m_pReceiverMe);
- HX_DELETE(m_pNTPBase);
- HX_DELETE(m_pTSConverter);
- }
- void
- ReportHandler::Init(REF(Timeval) tvInitial,
- INT64 nInitialRTP,
- CHXTimestampConverter* pConverter)
- {
- HX_ASSERT(!m_pNTPBase && "Are you sure to reset this?");
- HX_DELETE(m_pNTPBase);
- HX_DELETE(m_pTSConverter);
- m_pNTPBase = new NTPTime(tvInitial);
- m_nRTPTSBase = nInitialRTP;
- if (pConverter)
- {
- m_pTSConverter = new CHXTimestampConverter();
- *m_pTSConverter = *pConverter;
- }
- }
- void
- ReportHandler::OnRTPReceive(UINT32 ulSsrc, UINT16 unSeqNo,
- UINT32 ulHXTimestamp, UINT32 ulNow)
- {
- HX_ASSERT(m_pReceiverMe && !m_pSenderMe);
-
- ReceptionInfo* pRInfo = GetOrCreateReceptionInfo(ulSsrc);
- pRInfo->m_bHeardSinceLastTime = TRUE;
- // in the same unit
- INT32 lTransit = ulNow - ulHXTimestamp;
- if (0 == pRInfo->m_ulNumPktReceived)
- {
- pRInfo->InitSeqNo(unSeqNo);
- /* so it won't be some crazy number */
- pRInfo->m_ulTransit = lTransit;
- }
- // all updates will be done here.
- pRInfo->UpdateSeqNo(unSeqNo);
- /************************
- * calculate jitter (rfc 1889 Appendix A.8)
- * this doesn't belong to UpdateSeqNo() so just do it here...
- */
- INT32 lDiff = lTransit - pRInfo->m_ulTransit;
- pRInfo->m_ulTransit = lTransit;
- if (lDiff < 0)
- {
- lDiff = -lDiff;
- }
- pRInfo->m_ulJitter += lDiff - ((pRInfo->m_ulJitter + 8) >> 4);
- }
- void
- ReportHandler::OnRTCPReceive(RTCPPacket* pPkt, UINT32 ulNow)
- {
- HX_ASSERT(m_pSenderMe || m_pReceiverMe);
- #ifdef DUMP_RECEIVE_REPORTS
- printf("n%u", pPkt->packet_type);
- #endif
- if (RTCP_SR == pPkt->packet_type)
- {
- HX_ASSERT(m_pReceiverMe);
- // it IS possible to get RTCP before RTP if this is multicast.
- ReceptionInfo* pRInfo = GetOrCreateReceptionInfo(pPkt->sr_ssrc);
- // the middle 32 bits out of 64 in the NTP timestamp
- pRInfo->m_ulLSR = pPkt->ntp_sec << 16;
- pRInfo->m_ulLSR |= (pPkt->ntp_frac >> 16);
- pRInfo->m_ulLastSRReceived = ulNow;
- pRInfo->m_bHeardSinceLastTime = TRUE;
- #ifdef DUMP_RECEIVE_REPORTS
- printf("tSR %u:n", pPkt->sr_ssrc);
- printf("ttrtp_ts: %un", pPkt->rtp_ts);
- printf("ttntp: %u: %un", pPkt->ntp_sec, pPkt->ntp_frac);
- printf("ttpsent: %u osent: %un", pPkt->psent, pPkt->osent);
- fflush(stdout);
- #endif
- }
- else if (RTCP_RR == pPkt->packet_type)
- {
- // just need to keep track of them. Ignore the returned value...
- GetOrCreateReceiverInfo(pPkt->rr_ssrc);
- #ifdef DUMP_RECEIVE_REPORTS
- printf("tRR %un", pPkt->rr_ssrc);
- for (UINT32 i = 0; i < pPkt->count; i++)
- {
- ReceptionReport rr = pPkt->rr_data[i];
- printf("ttssrc: %un", rr.ssrc);
- printf("ttlast_seq: %un", rr.last_seq);
- printf("ttlost: %un", rr.lost);
- printf("ttfraction: %un", rr.fraction);
- printf("ttjitter: %un", rr.jitter);
- printf("ttlsr: %un", rr.lsr);
- printf("ttdlsr: %un", rr.dlsr);
- }
- fflush(stdout);
- #endif
- }
- else if (RTCP_BYE == pPkt->packet_type)
- {
- UINT32 ulSsrc;
- for (UINT32 i = 0; i < pPkt->count; i++)
- {
- ulSsrc = *(pPkt->bye_src + i);
- // remove this entry
- DeleteReceiverInfo(ulSsrc);
- DeleteReceptionInfo(ulSsrc);
- }
- }
- #ifdef DUMP_RECEIVE_REPORTS
- else if (RTCP_SDES == pPkt->packet_type)
- {
- printf("tSDESn");
- SDESItem* pItem = NULL;
- CHXSimpleList* pSdesList = NULL;
- CHXSimpleList::Iterator j;
- CHXMapLongToObj::Iterator i;
- for (i = pPkt->m_mapSDESSources.Begin(); i != pPkt->m_mapSDESSources.End(); ++i)
- {
- pSdesList = (CHXSimpleList*)(*i);
- for (j = pSdesList->Begin(); j != pSdesList->End(); ++j)
- {
- pItem = (SDESItem*)(*j);
- printf("tttype %u: %sn", pItem->sdes_type, pItem->data);
- }
- }
- }
- printf("n");
- fflush(stdout);
- #endif
- }
- HX_RESULT
- ReportHandler::MakeSR(RTCPPacket* pPkt, UINT32 ulNow)
- {
- Timeval tvNow((INT32)(ulNow / 1000), (INT32)(ulNow % 1000 * 1000));
- return MakeSR(pPkt, tvNow);
- }
- HX_RESULT
- ReportHandler::MakeSR(RTCPPacket* pPkt, REF(Timeval) tvNow)
- {
- HX_ASSERT(m_pSenderMe);
- HX_ASSERT(pPkt);
- if (!m_pSenderMe->m_bWeSent)
- {
- // no pkt has been sent, wait!
- return HXR_UNEXPECTED;
- }
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_SR;
- pPkt->sr_ssrc = m_pSenderMe->m_ulSsrc;
- pPkt->psent = m_pSenderMe->m_ulNumPktSentSoFar;
- pPkt->osent = m_pSenderMe->m_ulNumByteSentSoFar;
- /* since a sender is never a receiver */
- pPkt->count = 0;
- pPkt->sr_data = NULL;
- pPkt->length = 6;
- /* NTP time when this report is generated */
- NTPTime ntpNow(tvNow);
- /*
- * RTP TS that corresponds to NTP time above
- * m_pNTPBase and m_nRTPTSBase are the same time in diff unit
- */
- INT64 nRTPNow = m_nRTPTSBase;
- if (m_pTSConverter)
- {
- nRTPNow += m_pTSConverter->hxa2rtp((UINT32)(ntpNow - *m_pNTPBase));
- }
- else
- {
- nRTPNow += (UINT32)(ntpNow - *m_pNTPBase);
- }
- HX_ASSERT(nRTPNow >= 0);
- // NTP
- pPkt->ntp_sec = ntpNow.m_ulSecond;
- pPkt->ntp_frac = ntpNow.m_ulFraction;
- // RTP
- pPkt->rtp_ts = INT64_TO_UINT32(nRTPNow);
- #ifdef DUMP_REPORTS
- printf("SR %u:n", pPkt->sr_ssrc);
- printf("trtp_ts: %un", pPkt->rtp_ts);
- printf("tntp: %u: %un", pPkt->ntp_sec, pPkt->ntp_frac);
- printf("tpsent: %u osent: %un", pPkt->psent, pPkt->osent);
- fflush(stdout);
- #endif
- return HXR_OK;
- }
- /*
- * Make RR. We need this even if there is no reception report
- */
- HX_RESULT
- ReportHandler::MakeRR(RTCPPacket* pPkt, UINT32 ulNow)
- {
- // Timeval tvNow((INT32)(ulNow / 1000), (INT32)(ulNow % 1000 * 1000));
- // return MakeRR(pPkt, tvNow);
- HX_ASSERT(m_pReceiverMe);
- HX_ASSERT(pPkt);
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_RR;
- pPkt->rr_ssrc = m_pReceiverMe->m_ulSsrc;
- // can't be more than this
- ReceptionReport* pRr = new ReceptionReport[m_mapSenders.GetCount()];
- if (!pRr)
- {
- return HXR_OUTOFMEMORY;
- }
- #ifdef DUMP_REPORTS
- printf("RR %u:n", pPkt->rr_ssrc);
- #endif
- UINT8 chRRCount = 0;
- ReceptionInfo* pRInfo = NULL;
- CHXMapLongToObj::Iterator i;
- for (i = m_mapSenders.Begin(); i != m_mapSenders.End(); ++i)
- {
- pRInfo = (ReceptionInfo*)(*i);
- if (pRInfo->m_bHeardSinceLastTime)
- {
- // need to make a report for this sender
- pRInfo->MakeReceptionReport(i.get_key(), pRr[chRRCount++], ulNow);
- pRInfo->m_bHeardSinceLastTime = FALSE;
- }
- }
- pPkt->count = chRRCount;
- pPkt->length = 1 + 6 * (UINT16)pPkt->count;
- pPkt->SetReceiverReport(pRr, pPkt->count);
- // SetReceiverReport is making a copy.
- HX_VECTOR_DELETE(pRr);
-
- return HXR_OK;
- }
- /*
- * CNAME is the only one required
- */
- HX_RESULT
- ReportHandler::MakeSDES(RTCPPacket* pPkt, const BYTE* pcCNAME)
- {
- HX_ASSERT(m_pSenderMe || m_pReceiverMe);
- HX_ASSERT(pPkt);
- HX_ASSERT(pcCNAME);
-
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_SDES;
- pPkt->count = 1;
-
- UINT16 unByteCount = 0;
-
- SDESItem item;
- item.sdes_type = SDES_CNAME;
- item.length = strlen((const char*)pcCNAME);
- item.data = (BYTE*)pcCNAME;
- if (m_pSenderMe)
- {
- pPkt->AddSDESItem(m_pSenderMe->m_ulSsrc, item);
- }
- else
- {
- pPkt->AddSDESItem(m_pReceiverMe->m_ulSsrc, item);
- }
- // 2 for sdes_type and length
- unByteCount += item.length + 2;
- /*
- * Increment item byte count for null termination
- */
- unByteCount++;
-
- // Align on word boundary
- // RTCP pkt length is in 32-bits word!
- unByteCount += (unByteCount % 4) ? 4 - (unByteCount % 4) : 0;
- HX_ASSERT(unByteCount % 4 == 0);
- // I am counting 32-bits word
- pPkt->length = (unByteCount / 4); // count of words - 1
- //one more 32-bits for SSRC
- pPkt->length++;
-
- return HXR_OK;
- }
- HX_RESULT
- ReportHandler::MakeBye(RTCPPacket* pPkt)
- {
- HX_ASSERT(m_pSenderMe || m_pReceiverMe);
- HX_ASSERT(pPkt);
-
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_BYE;
- pPkt->length = 1; // len in 32-bits words minus one
- pPkt->count = 1;
- // use access function
- if (m_pSenderMe)
- {
- pPkt->SetByeSrc(&m_pSenderMe->m_ulSsrc, pPkt->count);
- #ifdef DUMP_REPORTS
- printf("BYE %u:n", m_pSenderMe->m_ulSsrc);
- #endif
- }
- else
- {
- pPkt->SetByeSrc(&m_pReceiverMe->m_ulSsrc, pPkt->count);
- #ifdef DUMP_REPORTS
- printf("BYE %un", m_pReceiverMe->m_ulSsrc);
- #endif
- }
- #ifdef DUMP_REPORTS
- fflush(stdout);
- #endif
- return HXR_OK;
- }
- /*
- * for now this is the only APP.
- */
- HX_RESULT
- ReportHandler::MakeEOSApp(RTCPPacket* pPkt)
- {
- HX_ASSERT(m_pSenderMe);
- HX_ASSERT(pPkt);
-
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_APP;
- pPkt->app_ssrc = m_pSenderMe->m_ulSsrc;
- pPkt->count = 1;
- pPkt->length = 4; // 2 + the length of APPItem...fortunately, we don't
- // have to align them
- memcpy(pPkt->app_name, "RNWK", 4); /* Flawfinder: ignore */
- // this is application dependent...
- APPItem item;
- item.app_type = APP_EOS;
- item.seq_no = m_pSenderMe->m_unLastSeqNo;
- item.packet_sent = (UINT8)m_pSenderMe->m_ulNumPktSentSoFar ? 1 : 0;
- item.timestamp = m_pSenderMe->m_ulLastRTPTimestamp;
- pPkt->SetAPPItem(&item, pPkt->count);
- return HXR_OK;
- }
- HX_RESULT
- ReportHandler::MakeBufInfoApp(RTCPPacket* pPkt,
- UINT32 ulLowTS, UINT32 ulHighTS,
- UINT32 ulBytesBuffered)
- {
- HX_RESULT res = HXR_UNEXPECTED;
- if (pPkt)
- {
- pPkt->version_flag = 0x02;
- pPkt->padding_flag = 0;
- pPkt->packet_type = RTCP_APP;
- pPkt->count = 1;
- pPkt->app_ssrc = m_pReceiverMe->m_ulSsrc;
- memcpy(pPkt->app_name, "HELX", 4);
- pPkt->length = 2;
- APPItem item;
- item.app_type = APP_BUFINFO;
- item.lowest_timestamp = ulLowTS;
- item.highest_timestamp = ulHighTS;
- item.bytes_buffered = ulBytesBuffered;
- item.padding0 = 0;
- pPkt->SetAPPItem(&item, 1);
- pPkt->length += 4;
- res = HXR_OK;
- }
- return res;
- }
- ReceiverInfo*
- ReportHandler::GetOrCreateReceiverInfo(UINT32 ulSsrc)
- {
- ReceiverInfo* pReceiver = NULL;
- if (!m_mapReceivers.Lookup(ulSsrc, (void*&)pReceiver))
- {
- #ifdef DUMP_MEMBER_COUNT
- printf("New Receiver (#%u): %un", m_mapReceivers.GetCount()+1, ulSsrc);
- fflush(stdout);
- #endif
- // doesn't exist, create one.
- pReceiver = new ReceiverInfo;
- if (!pReceiver)
- {
- return NULL;
- }
- m_mapReceivers.SetAt(ulSsrc, (void*)pReceiver);
- #if _DEBUG
- ReceiverInfo* pTmp = NULL;
- HX_ASSERT(m_mapReceivers.Lookup(ulSsrc, (void*&)pTmp));
- HX_ASSERT(pTmp);
- #endif
- }
- HX_ASSERT(pReceiver);
- return pReceiver;
- }
- void
- ReportHandler::DeleteReceiverInfo(UINT32 ulSsrc)
- {
- /* since we need to do timeout, we might as well do the right thing for
- * this as well....mark as delete, and delete after a fixed timeout...so,
- * we know we don't receive any late pkt after we delete this entry...
- */
- ReceiverInfo* pReceiver = NULL;
- if (m_mapReceivers.Lookup(ulSsrc, (void*&)pReceiver))
- {
- #ifdef DUMP_MEMBER_COUNT
- printf("Deleteing Receiver: %un", ulSsrc);
- fflush(stdout);
- #endif
- HX_ASSERT(pReceiver);
- m_mapReceivers.RemoveKey(ulSsrc);
- delete pReceiver;
- }
- }
- ReceptionInfo*
- ReportHandler::GetOrCreateReceptionInfo(UINT32 ulSsrc)
- {
- ReceptionInfo* pRInfo = NULL;
- if (!m_mapSenders.Lookup(ulSsrc, (void*&)pRInfo))
- {
- #ifdef DUMP_MEMBER_COUNT
- printf("New Sender (#%u): %un", m_mapSenders.GetCount()+1, ulSsrc);
- fflush(stdout);
- #endif
- // doesn't exist, create one.
- pRInfo = new ReceptionInfo();
- if (!pRInfo)
- {
- return NULL;
- }
- // pRInfo->m_ulProbation = m_ulDefaultProbation;
-
- m_mapSenders.SetAt(ulSsrc, (void*)pRInfo);
- #if _DEBUG
- ReceptionInfo* pTmp = NULL;
- HX_ASSERT(m_mapSenders.Lookup(ulSsrc, (void*&)pTmp));
- HX_ASSERT(pTmp);
- #endif
- }
- HX_ASSERT(pRInfo);
- return pRInfo;
- }
- void
- ReportHandler::DeleteReceptionInfo(UINT32 ulSsrc)
- {
- /* since we need to do timeout, we might as well do the right thing for
- * this as well....mark as delete, and delete after a fixed timeout...so,
- * we know we don't receive any late pkt after we delete this entry...
- */
- ReceptionInfo* pRInfo= NULL;
- if (m_mapSenders.Lookup(ulSsrc, (void*&)pRInfo))
- {
- #ifdef DUMP_MEMBER_COUNT
- printf("Deleteing Sender: %un", ulSsrc);
- fflush(stdout);
- #endif
- HX_ASSERT(pRInfo);
- m_mapSenders.RemoveKey(ulSsrc);
- delete pRInfo;
- }
- }
- /*
- */
- double
- ReportHandler::GetRTCPInterval()
- {
- // include myself
- double interval =
- rtcp_interval(m_mapReceivers.GetCount() + 1,
- m_pSenderMe ? m_mapSenders.GetCount()+1 : m_mapSenders.GetCount(),
- m_ulRSByteRate,
- m_ulRRByteRate,
- m_pSenderMe ? m_pSenderMe->m_bWeSent : 0,
- m_ulAvgRTCPSize,
- m_bInitialIntervalCalc,
- m_minRTCPInterval);
- m_bInitialIntervalCalc = FALSE;
- return interval;
- }
- void ReportHandler::SetRTCPIntervalParams(UINT32 ulRSBitRate,
- UINT32 ulRRBitRate,
- UINT32 ulMinRTCPIntervalMs)
- {
- m_ulRSByteRate = ulRSBitRate >> 3; // bitrate -> byterate
- m_ulRRByteRate = ulRRBitRate >> 3; // bitrate -> byterate
- m_minRTCPInterval = ((double)ulMinRTCPIntervalMs) / 1000.0; // ms -> sec
- }
- /*
- * ReceptionInfo Func's
- */
- void
- ReceptionInfo::InitSeqNo(UINT16 unSeqNo)
- {
- #ifdef _DEBUG
- HX_ASSERT(INIT == m_state);
- m_state = UPDATE;
- #endif
- // m_ulBaseSeqNo = unSeqNo - 1;
- m_ulBaseSeqNo = unSeqNo;
- m_unMaxSeqNo = unSeqNo;
- m_ulBadSeqNo = RTP_SEQ_MOD + 1;
- m_ulCycles = 0;
- m_ulNumPktReceived = 0;
- m_ulExpectedPrior = 0;
- m_ulReceivedPrior = 0;
- }
- BOOL
- ReceptionInfo::UpdateSeqNo(UINT16 unSeqNo)
- {
- #ifdef _DEBUG
- HX_ASSERT(UPDATE == m_state);
- #endif
- UINT16 unDelta = unSeqNo - m_unMaxSeqNo;
- #if 0 /* don't ever throu pkt away! */
- if (m_ulProbation)
- {
- if (unSeqNo == m_unMaxSeqNo + 1)
- {
- // pkt is in sequence
- m_ulProbation--;
- m_unMaxSeqNo = unSeqNo;
- if (0 == m_ulProbation)
- {
- InitSeqNo(unSeqNo);
- m_ulNumPktReceived++;
- return TRUE;
- }
- }
- else
- {
- // pkt is NOT in sequence
- m_ulProbation = MIN_SEQUENTIAL - 1;
- m_unMaxSeqNo = unSeqNo;
- }
- return FALSE;
- }
- else
- #endif
- if (unDelta < MAX_DROPOUT)
- {
- // in order, with permissible gap
- if (unSeqNo < m_unMaxSeqNo)
- {
- // seq# wrapped - count another 64k cycle
- m_ulCycles += RTP_SEQ_MOD;
- }
-
- m_unMaxSeqNo = unSeqNo;
- }
- else if (unDelta <= RTP_SEQ_MOD - MAX_MISORDER)
- {
- // seq# made a very large jump
- if (unSeqNo == m_ulBadSeqNo)
- {
- // two sequential pkts -- assume that the other side
- // restarted w/o telling us, so just re-sync
- // (i.e., pretned this was the first pkt)
- InitSeqNo(unSeqNo);
- }
- else
- {
-
- m_ulBadSeqNo = (unSeqNo + 1) & (RTP_SEQ_MOD - 1);
- // (i.e. m_ulBadSeq = unSeq + 1;)
- return FALSE;
- }
- }
- else
- {
- /* duplicate or reordered packet */
- }
- m_ulNumPktReceived++;
- return TRUE;
- }
- void
- ReceptionInfo::MakeReceptionReport(UINT32 ulSsrc, REF(ReceptionReport) rr, UINT32 ulNow)
- {
- #ifdef DUMP_REPROTS
- printf("making rr for %un", ulSsrc);
- fflush(stdout);
- #endif
- // ssrc of a sender that we are reporting
- rr.ssrc = ulSsrc;
-
- /* extended last seqno received */
- rr.last_seq = m_ulCycles + m_unMaxSeqNo;
- /* simply #pkt expected - received */
- UINT32 ulExpected = rr.last_seq - m_ulBaseSeqNo + 1;
- rr.lost = ulExpected - m_ulNumPktReceived;
- UINT32 ulExpectedInterval = ulExpected - m_ulExpectedPrior;
- UINT32 ulReceivedInterval = m_ulNumPktReceived - m_ulReceivedPrior;
- INT32 lLostInterval = ulExpectedInterval - ulReceivedInterval;
- // save them for the next time
- m_ulExpectedPrior = ulExpected;
- m_ulReceivedPrior = m_ulNumPktReceived;
- /*
- * The resulting fraction is an 8-bit fixed point number with the binary
- * point at the left edge.
- */
- if (0 == ulExpectedInterval || lLostInterval <= 0)
- {
- rr.fraction = 0;
- }
- else
- {
- rr.fraction = (UINT8)((lLostInterval << 8) / ulExpectedInterval);
- }
-
- rr.jitter = m_ulJitter >> 4;
- rr.lsr = m_ulLSR ? m_ulLSR : 0;
- /* expressed in 1/65536 sec...ahhh...make it 66 */
- rr.dlsr = (m_ulLastSRReceived ?
- CALCULATE_ELAPSED_TICKS(m_ulLastSRReceived, ulNow) :
- 0 /* SR not yet received */) * 66;
-
- #ifdef DUMP_REPROTS
- printf("tssrc: %un", rr.ssrc);
- printf("tlast_seq: %un", rr.last_seq);
- printf("tlost: %un", rr.lost);
- printf("tfraction: %un", rr.fraction);
- printf("tjitter: %un", rr.jitter);
- printf("tlsr: %un", rr.lsr);
- printf("tdlsr: %un", rr.dlsr);
- fflush(stdout);
- #endif
- }