1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h"
12 
13 #include <assert.h>  // assert
14 #include <string.h>  // memset
15 
16 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
17 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
18 
19 namespace webrtc {
20 namespace RTCPHelp {
21 
RTCPPacketInformation()22 RTCPPacketInformation::RTCPPacketInformation()
23     : rtcpPacketTypeFlags(0),
24       remoteSSRC(0),
25       nackSequenceNumbers(),
26       applicationSubType(0),
27       applicationName(0),
28       applicationData(),
29       applicationLength(0),
30       rtt(0),
31       interArrivalJitter(0),
32       sliPictureId(0),
33       rpsiPictureId(0),
34       receiverEstimatedMaxBitrate(0),
35       ntp_secs(0),
36       ntp_frac(0),
37       rtp_timestamp(0),
38       xr_originator_ssrc(0),
39       xr_dlrr_item(false),
40       VoIPMetric(nullptr) {}
41 
~RTCPPacketInformation()42 RTCPPacketInformation::~RTCPPacketInformation()
43 {
44     delete [] applicationData;
45     delete VoIPMetric;
46 }
47 
48 void
AddVoIPMetric(const RTCPVoIPMetric * metric)49 RTCPPacketInformation::AddVoIPMetric(const RTCPVoIPMetric* metric)
50 {
51     VoIPMetric = new RTCPVoIPMetric();
52     memcpy(VoIPMetric, metric, sizeof(RTCPVoIPMetric));
53 }
54 
AddApplicationData(const uint8_t * data,const uint16_t size)55 void RTCPPacketInformation::AddApplicationData(const uint8_t* data,
56                                                const uint16_t size) {
57     uint8_t* oldData = applicationData;
58     uint16_t oldLength = applicationLength;
59 
60     // Don't copy more than kRtcpAppCode_DATA_SIZE bytes.
61     uint16_t copySize = size;
62     if (size > kRtcpAppCode_DATA_SIZE) {
63         copySize = kRtcpAppCode_DATA_SIZE;
64     }
65 
66     applicationLength += copySize;
67     applicationData = new uint8_t[applicationLength];
68 
69     if (oldData)
70     {
71         memcpy(applicationData, oldData, oldLength);
72         memcpy(applicationData+oldLength, data, copySize);
73         delete [] oldData;
74     } else
75     {
76         memcpy(applicationData, data, copySize);
77     }
78 }
79 
80 void
ResetNACKPacketIdArray()81 RTCPPacketInformation::ResetNACKPacketIdArray()
82 {
83   nackSequenceNumbers.clear();
84 }
85 
86 void
AddNACKPacket(const uint16_t packetID)87 RTCPPacketInformation::AddNACKPacket(const uint16_t packetID)
88 {
89   if (nackSequenceNumbers.size() >= kSendSideNackListSizeSanity) {
90     return;
91   }
92   nackSequenceNumbers.push_back(packetID);
93 }
94 
95 void
AddReportInfo(const RTCPReportBlockInformation & report_block_info)96 RTCPPacketInformation::AddReportInfo(
97     const RTCPReportBlockInformation& report_block_info)
98 {
99   this->rtt = report_block_info.RTT;
100   report_blocks.push_back(report_block_info.remoteReceiveBlock);
101 }
102 
RTCPReportBlockInformation()103 RTCPReportBlockInformation::RTCPReportBlockInformation():
104     remoteReceiveBlock(),
105     remoteMaxJitter(0),
106     RTT(0),
107     minRTT(0),
108     maxRTT(0),
109     avgRTT(0),
110     numAverageCalcs(0)
111 {
112     memset(&remoteReceiveBlock,0,sizeof(remoteReceiveBlock));
113 }
114 
~RTCPReportBlockInformation()115 RTCPReportBlockInformation::~RTCPReportBlockInformation()
116 {
117 }
118 
RTCPReceiveInformation()119 RTCPReceiveInformation::RTCPReceiveInformation()
120     : lastTimeReceived(0),
121       lastFIRSequenceNumber(-1),
122       lastFIRRequest(0),
123       readyForDelete(false) {
124 }
125 
~RTCPReceiveInformation()126 RTCPReceiveInformation::~RTCPReceiveInformation() {
127 }
128 
129 // Increase size of TMMBRSet if needed, and also take care of
130 // the _tmmbrSetTimeouts vector.
VerifyAndAllocateTMMBRSet(const uint32_t minimumSize)131 void RTCPReceiveInformation::VerifyAndAllocateTMMBRSet(
132     const uint32_t minimumSize) {
133   if (minimumSize > TmmbrSet.sizeOfSet()) {
134     TmmbrSet.VerifyAndAllocateSetKeepingData(minimumSize);
135     // make sure that our buffers are big enough
136     _tmmbrSetTimeouts.reserve(minimumSize);
137   }
138 }
139 
InsertTMMBRItem(const uint32_t senderSSRC,const RTCPUtility::RTCPPacketRTPFBTMMBRItem & TMMBRItem,const int64_t currentTimeMS)140 void RTCPReceiveInformation::InsertTMMBRItem(
141     const uint32_t senderSSRC,
142     const RTCPUtility::RTCPPacketRTPFBTMMBRItem& TMMBRItem,
143     const int64_t currentTimeMS) {
144   // serach to see if we have it in our list
145   for (uint32_t i = 0; i < TmmbrSet.lengthOfSet(); i++)  {
146     if (TmmbrSet.Ssrc(i) == senderSSRC) {
147       // we already have this SSRC in our list update it
148       TmmbrSet.SetEntry(i,
149                         TMMBRItem.MaxTotalMediaBitRate,
150                         TMMBRItem.MeasuredOverhead,
151                         senderSSRC);
152       _tmmbrSetTimeouts[i] = currentTimeMS;
153       return;
154     }
155   }
156   VerifyAndAllocateTMMBRSet(TmmbrSet.lengthOfSet() + 1);
157   TmmbrSet.AddEntry(TMMBRItem.MaxTotalMediaBitRate,
158                     TMMBRItem.MeasuredOverhead,
159                     senderSSRC);
160   _tmmbrSetTimeouts.push_back(currentTimeMS);
161 }
162 
GetTMMBRSet(const uint32_t sourceIdx,const uint32_t targetIdx,TMMBRSet * candidateSet,const int64_t currentTimeMS)163 int32_t RTCPReceiveInformation::GetTMMBRSet(
164     const uint32_t sourceIdx,
165     const uint32_t targetIdx,
166     TMMBRSet* candidateSet,
167     const int64_t currentTimeMS) {
168   if (sourceIdx >= TmmbrSet.lengthOfSet()) {
169     return -1;
170   }
171   if (targetIdx >= candidateSet->sizeOfSet()) {
172     return -1;
173   }
174   // use audio define since we don't know what interval the remote peer is using
175   if (currentTimeMS - _tmmbrSetTimeouts[sourceIdx] >
176       5 * RTCP_INTERVAL_AUDIO_MS) {
177     // value timed out
178     TmmbrSet.RemoveEntry(sourceIdx);
179     _tmmbrSetTimeouts.erase(_tmmbrSetTimeouts.begin() + sourceIdx);
180     return -1;
181   }
182   candidateSet->SetEntry(targetIdx,
183                          TmmbrSet.Tmmbr(sourceIdx),
184                          TmmbrSet.PacketOH(sourceIdx),
185                          TmmbrSet.Ssrc(sourceIdx));
186   return 0;
187 }
188 
VerifyAndAllocateBoundingSet(const uint32_t minimumSize)189 void RTCPReceiveInformation::VerifyAndAllocateBoundingSet(
190     const uint32_t minimumSize) {
191   TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize);
192 }
193 }  // namespace RTCPHelp
194 }  // namespace webrtc
195