| /* |
| * Copyright (c) 2012 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 "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h" |
| |
| #include <assert.h> // assert |
| #include <string.h> // memset |
| |
| #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
| |
| namespace webrtc { |
| namespace RTCPHelp { |
| |
| RTCPPacketInformation::RTCPPacketInformation() |
| : rtcpPacketTypeFlags(0), |
| remoteSSRC(0), |
| nackSequenceNumbers(), |
| applicationSubType(0), |
| applicationName(0), |
| applicationData(), |
| applicationLength(0), |
| rtt(0), |
| interArrivalJitter(0), |
| sliPictureId(0), |
| rpsiPictureId(0), |
| receiverEstimatedMaxBitrate(0), |
| ntp_secs(0), |
| ntp_frac(0), |
| rtp_timestamp(0), |
| xr_originator_ssrc(0), |
| xr_dlrr_item(false), |
| VoIPMetric(nullptr) {} |
| |
| RTCPPacketInformation::~RTCPPacketInformation() |
| { |
| delete [] applicationData; |
| } |
| |
| void |
| RTCPPacketInformation::AddVoIPMetric(const RTCPVoIPMetric* metric) |
| { |
| VoIPMetric.reset(new RTCPVoIPMetric()); |
| memcpy(VoIPMetric.get(), metric, sizeof(RTCPVoIPMetric)); |
| } |
| |
| void RTCPPacketInformation::AddApplicationData(const uint8_t* data, |
| const uint16_t size) { |
| uint8_t* oldData = applicationData; |
| uint16_t oldLength = applicationLength; |
| |
| // Don't copy more than kRtcpAppCode_DATA_SIZE bytes. |
| uint16_t copySize = size; |
| if (size > kRtcpAppCode_DATA_SIZE) { |
| copySize = kRtcpAppCode_DATA_SIZE; |
| } |
| |
| applicationLength += copySize; |
| applicationData = new uint8_t[applicationLength]; |
| |
| if (oldData) |
| { |
| memcpy(applicationData, oldData, oldLength); |
| memcpy(applicationData+oldLength, data, copySize); |
| delete [] oldData; |
| } else |
| { |
| memcpy(applicationData, data, copySize); |
| } |
| } |
| |
| void |
| RTCPPacketInformation::ResetNACKPacketIdArray() |
| { |
| nackSequenceNumbers.clear(); |
| } |
| |
| void |
| RTCPPacketInformation::AddNACKPacket(const uint16_t packetID) |
| { |
| if (nackSequenceNumbers.size() >= kSendSideNackListSizeSanity) { |
| return; |
| } |
| nackSequenceNumbers.push_back(packetID); |
| } |
| |
| void |
| RTCPPacketInformation::AddReportInfo( |
| const RTCPReportBlockInformation& report_block_info) |
| { |
| this->rtt = report_block_info.RTT; |
| report_blocks.push_back(report_block_info.remoteReceiveBlock); |
| } |
| |
| 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) { |
| } |
| |
| RTCPReceiveInformation::~RTCPReceiveInformation() { |
| } |
| |
| // Increase size of TMMBRSet if needed, and also take care of |
| // the _tmmbrSetTimeouts vector. |
| void RTCPReceiveInformation::VerifyAndAllocateTMMBRSet( |
| const uint32_t minimumSize) { |
| if (minimumSize > TmmbrSet.sizeOfSet()) { |
| TmmbrSet.VerifyAndAllocateSetKeepingData(minimumSize); |
| // make sure that our buffers are big enough |
| _tmmbrSetTimeouts.reserve(minimumSize); |
| } |
| } |
| |
| void RTCPReceiveInformation::InsertTMMBRItem( |
| const uint32_t senderSSRC, |
| const RTCPUtility::RTCPPacketRTPFBTMMBRItem& TMMBRItem, |
| const int64_t currentTimeMS) { |
| // serach to see if we have it in our list |
| for (uint32_t i = 0; i < TmmbrSet.lengthOfSet(); i++) { |
| if (TmmbrSet.Ssrc(i) == senderSSRC) { |
| // we already have this SSRC in our list update it |
| TmmbrSet.SetEntry(i, |
| TMMBRItem.MaxTotalMediaBitRate, |
| TMMBRItem.MeasuredOverhead, |
| senderSSRC); |
| _tmmbrSetTimeouts[i] = currentTimeMS; |
| return; |
| } |
| } |
| VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet() + 1); |
| TmmbrSet.AddEntry(TMMBRItem.MaxTotalMediaBitRate, |
| TMMBRItem.MeasuredOverhead, |
| senderSSRC); |
| _tmmbrSetTimeouts.push_back(currentTimeMS); |
| } |
| |
| int32_t RTCPReceiveInformation::GetTMMBRSet( |
| const uint32_t sourceIdx, |
| const uint32_t targetIdx, |
| TMMBRSet* candidateSet, |
| const int64_t currentTimeMS) { |
| if (sourceIdx >= TmmbrSet.lengthOfSet()) { |
| return -1; |
| } |
| if (targetIdx >= candidateSet->sizeOfSet()) { |
| return -1; |
| } |
| // use audio define since we don't know what interval the remote peer is using |
| if (currentTimeMS - _tmmbrSetTimeouts[sourceIdx] > |
| 5 * RTCP_INTERVAL_AUDIO_MS) { |
| // value timed out |
| TmmbrSet.RemoveEntry(sourceIdx); |
| _tmmbrSetTimeouts.erase(_tmmbrSetTimeouts.begin() + sourceIdx); |
| return -1; |
| } |
| candidateSet->SetEntry(targetIdx, |
| TmmbrSet.Tmmbr(sourceIdx), |
| TmmbrSet.PacketOH(sourceIdx), |
| TmmbrSet.Ssrc(sourceIdx)); |
| return 0; |
| } |
| |
| void RTCPReceiveInformation::VerifyAndAllocateBoundingSet( |
| const uint32_t minimumSize) { |
| TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize); |
| } |
| } // namespace RTCPHelp |
| } // namespace webrtc |