249 lines
7.5 KiB
C++
249 lines
7.5 KiB
C++
/*
|
|
* 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),
|
|
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
|