blob: 0058acabb6e575f7501abb240bbc7ff5fe1944b7 [file] [log] [blame]
/*
* 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 <string.h> //memset
#include <cassert> //assert
namespace webrtc {
using namespace RTCPHelp;
RTCPPacketInformation::RTCPPacketInformation()
: rtcpPacketTypeFlags(0),
remoteSSRC(0),
nackSequenceNumbers(0),
nackSequenceNumbersLength(0),
applicationSubType(0),
applicationName(0),
applicationData(),
applicationLength(0),
reportBlock(false),
fractionLost(0),
roundTripTime(0),
lastReceivedExtendedHighSeqNum(0),
jitter(0),
interArrivalJitter(0),
sliPictureId(0),
rpsiPictureId(0),
receiverEstimatedMaxBitrate(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;
// Don't copy more than kRtcpAppCode_DATA_SIZE bytes.
WebRtc_UWord16 copySize = size;
if (size > kRtcpAppCode_DATA_SIZE) {
copySize = kRtcpAppCode_DATA_SIZE;
}
applicationLength += copySize;
applicationData = new WebRtc_UWord8[applicationLength];
if(oldData)
{
memcpy(applicationData, oldData, oldLength);
memcpy(applicationData+oldLength, data, copySize);
delete [] oldData;
} else
{
memcpy(applicationData, data, copySize);
}
}
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,
const WebRtc_UWord32 currentTimeMS)
{
// 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] = currentTimeMS;
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] = currentTimeMS;
TmmbrSet.lengthOfSet++;
}
WebRtc_Word32
RTCPReceiveInformation::GetTMMBRSet(const WebRtc_UWord32 sourceIdx,
const WebRtc_UWord32 targetIdx,
TMMBRSet* candidateSet,
const WebRtc_UWord32 currentTimeMS)
{
if(sourceIdx >= TmmbrSet.lengthOfSet)
{
return -1;
}
if(targetIdx >= candidateSet->sizeOfSet)
{
return -1;
}
WebRtc_UWord32 timeNow = currentTimeMS;
// 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