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/rtp_utility.h"
17
18namespace webrtc {
19using namespace RTCPHelp;
20
21RTCPPacketInformation::RTCPPacketInformation()
22    : rtcpPacketTypeFlags(0),
23      remoteSSRC(0),
24      nackSequenceNumbers(),
25      applicationSubType(0),
26      applicationName(0),
27      applicationData(),
28      applicationLength(0),
29      rtt(0),
30      interArrivalJitter(0),
31      sliPictureId(0),
32      rpsiPictureId(0),
33      receiverEstimatedMaxBitrate(0),
34      ntp_secs(0),
35      ntp_frac(0),
36      rtp_timestamp(0),
37      xr_originator_ssrc(0),
38      xr_dlrr_item(false),
39      VoIPMetric(NULL) {
40}
41
42RTCPPacketInformation::~RTCPPacketInformation()
43{
44    delete [] applicationData;
45    delete VoIPMetric;
46}
47
48void
49RTCPPacketInformation::AddVoIPMetric(const RTCPVoIPMetric* metric)
50{
51    VoIPMetric = new RTCPVoIPMetric();
52    memcpy(VoIPMetric, metric, sizeof(RTCPVoIPMetric));
53}
54
55void 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
80void
81RTCPPacketInformation::ResetNACKPacketIdArray()
82{
83  nackSequenceNumbers.clear();
84}
85
86void
87RTCPPacketInformation::AddNACKPacket(const uint16_t packetID)
88{
89  if (nackSequenceNumbers.size() >= kSendSideNackListSizeSanity) {
90    return;
91  }
92  nackSequenceNumbers.push_back(packetID);
93}
94
95void
96RTCPPacketInformation::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
103RTCPReportBlockInformation::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
115RTCPReportBlockInformation::~RTCPReportBlockInformation()
116{
117}
118
119RTCPReceiveInformation::RTCPReceiveInformation()
120    : lastTimeReceived(0),
121      lastFIRSequenceNumber(-1),
122      lastFIRRequest(0),
123      readyForDelete(false) {
124}
125
126RTCPReceiveInformation::~RTCPReceiveInformation() {
127}
128
129// Increase size of TMMBRSet if needed, and also take care of
130// the _tmmbrSetTimeouts vector.
131void 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
140void 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
163int32_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
189void RTCPReceiveInformation::VerifyAndAllocateBoundingSet(
190    const uint32_t minimumSize) {
191  TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize);
192}
193}  // namespace webrtc
194