/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "rtcp_receiver_help.h" #include "rtp_utility.h" #include //memset #include //assert namespace webrtc { using namespace RTCPHelp; RTCPPacketInformation::RTCPPacketInformation() : rtcpPacketTypeFlags(0), nackSequenceNumbers(0), nackSequenceNumbersLength(0), applicationSubType(0), applicationName(0), applicationData(), applicationLength(0), reportBlock(false), fractionLost(0), roundTripTime(0), lastReceivedExtendedHighSeqNum(0), jitter(0), sliPictureId(0), rpsiPictureId(0), VoIPMetric(NULL) { } RTCPPacketInformation::~RTCPPacketInformation() { delete [] nackSequenceNumbers; delete [] applicationData; delete VoIPMetric; } void RTCPPacketInformation::AddVoIPMetric(const RTCPVoIPMetric* metric) { VoIPMetric = new RTCPVoIPMetric(); memcpy(VoIPMetric, metric, sizeof(RTCPVoIPMetric)); } void RTCPPacketInformation::AddApplicationData(const WebRtc_UWord8* data, const WebRtc_UWord16 size) { WebRtc_UWord8* oldData = applicationData; WebRtc_UWord16 oldLength = applicationLength; applicationLength += size; applicationData = new WebRtc_UWord8[applicationLength]; if(oldData) { memcpy(applicationData, oldData, oldLength); memcpy(applicationData+oldLength, data, size); delete [] oldData; } else { memcpy(applicationData, data, size); } } void RTCPPacketInformation::ResetNACKPacketIdArray() { if(NULL == nackSequenceNumbers) { nackSequenceNumbers = new WebRtc_UWord16[NACK_PACKETS_MAX_SIZE]; } nackSequenceNumbersLength = 0; } void RTCPPacketInformation::AddNACKPacket(const WebRtc_UWord16 packetID) { assert(nackSequenceNumbers); WebRtc_UWord16& idx = nackSequenceNumbersLength; if (idx < NACK_PACKETS_MAX_SIZE) { nackSequenceNumbers[idx++] = packetID; } } void RTCPPacketInformation::AddReportInfo(const WebRtc_UWord8 fraction, const WebRtc_UWord16 rtt, const WebRtc_UWord32 extendedHighSeqNum, const WebRtc_UWord32 j) { reportBlock = true; fractionLost = fraction; roundTripTime = rtt; jitter = j; lastReceivedExtendedHighSeqNum = extendedHighSeqNum; } RTCPReportBlockInformation::RTCPReportBlockInformation(): remoteReceiveBlock(), remoteMaxJitter(0), RTT(0), minRTT(0), maxRTT(0), avgRTT(0), numAverageCalcs(0) { memset(&remoteReceiveBlock,0,sizeof(remoteReceiveBlock)); } RTCPReportBlockInformation::~RTCPReportBlockInformation() { } RTCPReceiveInformation::RTCPReceiveInformation() : lastTimeReceived(0), lastFIRSequenceNumber(-1), lastFIRRequest(0), readyForDelete(false), _tmmbrSetTimeouts(NULL) { } RTCPReceiveInformation::~RTCPReceiveInformation() { if(_tmmbrSetTimeouts) { delete [] _tmmbrSetTimeouts; } } // don't use TmmbrSet.VerifyAndAllocate this version keeps the data void RTCPReceiveInformation::VerifyAndAllocateTMMBRSet(const WebRtc_UWord32 minimumSize) { if(minimumSize > TmmbrSet.sizeOfSet) { // make sure that our buffers are big enough WebRtc_UWord32* ptrTmmbrSet = new WebRtc_UWord32[minimumSize]; WebRtc_UWord32* ptrTmmbrPacketOHSet = new WebRtc_UWord32[minimumSize]; WebRtc_UWord32* ptrTmmbrSsrcSet = new WebRtc_UWord32[minimumSize]; WebRtc_UWord32* tmmbrSetTimeouts = new WebRtc_UWord32[minimumSize]; if(TmmbrSet.lengthOfSet > 0) { // copy old values memcpy(ptrTmmbrSet, TmmbrSet.ptrTmmbrSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet); memcpy(ptrTmmbrPacketOHSet, TmmbrSet.ptrPacketOHSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet); memcpy(ptrTmmbrSsrcSet, TmmbrSet.ptrSsrcSet, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet); memcpy(tmmbrSetTimeouts, _tmmbrSetTimeouts, sizeof(WebRtc_UWord32) * TmmbrSet.lengthOfSet); } if(TmmbrSet.ptrTmmbrSet) { delete [] TmmbrSet.ptrTmmbrSet; delete [] TmmbrSet.ptrPacketOHSet; delete [] TmmbrSet.ptrSsrcSet; } if(_tmmbrSetTimeouts) { delete [] _tmmbrSetTimeouts; } TmmbrSet.ptrTmmbrSet = ptrTmmbrSet; TmmbrSet.ptrPacketOHSet = ptrTmmbrPacketOHSet; TmmbrSet.ptrSsrcSet = ptrTmmbrSsrcSet; TmmbrSet.sizeOfSet = minimumSize; _tmmbrSetTimeouts = tmmbrSetTimeouts; } } void RTCPReceiveInformation::InsertTMMBRItem(const WebRtc_UWord32 senderSSRC, const RTCPUtility::RTCPPacketRTPFBTMMBRItem& TMMBRItem) { // serach to see if we have it in our list for(WebRtc_UWord32 i = 0; i < TmmbrSet.lengthOfSet; i++) { if(TmmbrSet.ptrSsrcSet[i] == senderSSRC) { // we already have this SSRC in our list // update it TmmbrSet.ptrPacketOHSet[i] = TMMBRItem.MeasuredOverhead; TmmbrSet.ptrTmmbrSet[i] = TMMBRItem.MaxTotalMediaBitRate; _tmmbrSetTimeouts[i] = ModuleRTPUtility::GetTimeInMS(); return; } } VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet+1); const WebRtc_UWord32 idx = TmmbrSet.lengthOfSet; TmmbrSet.ptrPacketOHSet[idx] = TMMBRItem.MeasuredOverhead; TmmbrSet.ptrTmmbrSet[idx] = TMMBRItem.MaxTotalMediaBitRate; TmmbrSet.ptrSsrcSet[idx] = senderSSRC; _tmmbrSetTimeouts[idx] = ModuleRTPUtility::GetTimeInMS(); TmmbrSet.lengthOfSet++; } WebRtc_Word32 RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx, const WebRtc_UWord32 targetIdx, TMMBRSet* candidateSet) { if(sourceIdx >= TmmbrSet.lengthOfSet) { return -1; } if(targetIdx >= candidateSet->sizeOfSet) { return -1; } WebRtc_UWord32 timeNow = ModuleRTPUtility::GetTimeInMS(); // use audio define since we don't know what interval the remote peer is using if(timeNow - _tmmbrSetTimeouts[sourceIdx] > 5*RTCP_INTERVAL_AUDIO_MS) { // value timed out const WebRtc_UWord32 move = TmmbrSet.lengthOfSet - (sourceIdx + 1); if(move > 0) { memmove(&(TmmbrSet.ptrTmmbrSet[sourceIdx]), &(TmmbrSet.ptrTmmbrSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32)); memmove(&(TmmbrSet.ptrPacketOHSet[sourceIdx]),&(TmmbrSet.ptrPacketOHSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32)); memmove(&(TmmbrSet.ptrSsrcSet[sourceIdx]),&(TmmbrSet.ptrSsrcSet[sourceIdx+1]), move* sizeof(WebRtc_UWord32)); memmove(&(_tmmbrSetTimeouts[sourceIdx]),&(_tmmbrSetTimeouts[sourceIdx+1]), move* sizeof(WebRtc_UWord32)); } TmmbrSet.lengthOfSet--; return -1; } candidateSet->ptrTmmbrSet[targetIdx] = TmmbrSet.ptrTmmbrSet[sourceIdx]; candidateSet->ptrPacketOHSet[targetIdx] = TmmbrSet.ptrPacketOHSet[sourceIdx]; candidateSet->ptrSsrcSet[targetIdx] = TmmbrSet.ptrSsrcSet[sourceIdx]; return 0; } void RTCPReceiveInformation::VerifyAndAllocateBoundingSet(const WebRtc_UWord32 minimumSize) { TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize); } } // namespace webrtc