blob: 71cf86f3ec872cbfc9380cfcf6b1fb128a583d9e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Peter Boströmfe7a80c2015-04-23 17:53:17 +020013#include <assert.h>
14#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000015
danilchap2f69ce92016-08-16 03:21:38 -070016#include <limits>
17
Peter Boströmfe7a80c2015-04-23 17:53:17 +020018#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020021#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070022#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010023#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070024#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010025#include "webrtc/system_wrappers/include/ntp_time.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000026
niklase@google.com470e71d2011-07-07 08:21:25 +000027namespace webrtc {
danilchap6a6f0892015-12-10 12:39:08 -080028using RTCPHelp::RTCPPacketInformation;
29using RTCPHelp::RTCPReceiveInformation;
30using RTCPHelp::RTCPReportBlockInformation;
31using RTCPUtility::kBtVoipMetric;
32using RTCPUtility::RTCPCnameInformation;
33using RTCPUtility::RTCPPacketReportBlockItem;
34using RTCPUtility::RTCPPacketTypes;
niklase@google.com470e71d2011-07-07 08:21:25 +000035
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000036// The number of RTCP time intervals needed to trigger a timeout.
37const int kRrTimeoutIntervals = 3;
38
Erik Språng6b8d3552015-09-24 15:06:57 +020039const int64_t kMaxWarningLogIntervalMs = 10000;
40
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000041RTCPReceiver::RTCPReceiver(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000042 Clock* clock,
Peter Boströmfe7a80c2015-04-23 17:53:17 +020043 bool receiver_only,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000044 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000045 RtcpBandwidthObserver* rtcp_bandwidth_observer,
46 RtcpIntraFrameObserver* rtcp_intra_frame_observer,
Erik Språng6b8d3552015-09-24 15:06:57 +020047 TransportFeedbackObserver* transport_feedback_observer,
danilchap59cb2bd2016-08-29 11:08:47 -070048 ModuleRtpRtcp* owner)
danilchap13deaad2016-05-24 13:25:27 -070049 : _clock(clock),
Peter Boströmfe7a80c2015-04-23 17:53:17 +020050 receiver_only_(receiver_only),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000051 _lastReceived(0),
52 _rtpRtcp(*owner),
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000053 _cbRtcpBandwidthObserver(rtcp_bandwidth_observer),
54 _cbRtcpIntraFrameObserver(rtcp_intra_frame_observer),
Erik Språng6b8d3552015-09-24 15:06:57 +020055 _cbTransportFeedbackObserver(transport_feedback_observer),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000056 main_ssrc_(0),
57 _remoteSSRC(0),
58 _remoteSenderInfo(),
59 _lastReceivedSRNTPsecs(0),
60 _lastReceivedSRNTPfrac(0),
61 _lastReceivedXRNTPsecs(0),
62 _lastReceivedXRNTPfrac(0),
Danil Chapovalovc1e55c72016-03-09 15:14:35 +010063 xr_rrtr_status_(false),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000064 xr_rr_rtt_ms_(0),
65 _receivedInfoMap(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000066 _lastReceivedRrMs(0),
67 _lastIncreasedSequenceNumberMs(0),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000068 stats_callback_(NULL),
Erik Språng6b8d3552015-09-24 15:06:57 +020069 packet_type_counter_observer_(packet_type_counter_observer),
70 num_skipped_packets_(0),
71 last_skipped_packets_warning_(clock->TimeInMilliseconds()) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000072 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000073}
74
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000075RTCPReceiver::~RTCPReceiver() {
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000076 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
77 for (; it != _receivedReportBlockMap.end(); ++it) {
78 ReportBlockInfoMap* info_map = &(it->second);
79 while (!info_map->empty()) {
80 ReportBlockInfoMap::iterator it_info = info_map->begin();
81 delete it_info->second;
82 info_map->erase(it_info);
83 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000084 }
85 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000086 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000087 _receivedInfoMap.begin();
88 delete first->second;
89 _receivedInfoMap.erase(first);
90 }
91 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +000092 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000093 _receivedCnameMap.begin();
94 delete first->second;
95 _receivedCnameMap.erase(first);
96 }
niklase@google.com470e71d2011-07-07 08:21:25 +000097}
98
danilchap59cb2bd2016-08-29 11:08:47 -070099bool RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) {
100 // Allow receive of non-compound RTCP packets.
101 RTCPUtility::RTCPParserV2 rtcp_parser(packet, packet_size, true);
102
103 if (!rtcp_parser.IsValid()) {
104 LOG(LS_WARNING) << "Incoming invalid RTCP packet";
105 return false;
106 }
107 RTCPHelp::RTCPPacketInformation rtcp_packet_information;
108 IncomingRTCPPacket(rtcp_packet_information, &rtcp_parser);
109 TriggerCallbacksFromRTCPPacket(rtcp_packet_information);
110 return true;
111}
112
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000113int64_t RTCPReceiver::LastReceived() {
danilchap7c9426c2016-04-14 03:05:31 -0700114 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000115 return _lastReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +0000116}
117
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000118int64_t RTCPReceiver::LastReceivedReceiverReport() const {
danilchap7c9426c2016-04-14 03:05:31 -0700119 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000120 int64_t last_received_rr = -1;
121 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
122 it != _receivedInfoMap.end(); ++it) {
danilchap2b616392016-08-18 06:17:42 -0700123 if (it->second->last_time_received_ms > last_received_rr) {
124 last_received_rr = it->second->last_time_received_ms;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000125 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000126 }
127 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000128}
129
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000130void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
danilchap7c9426c2016-04-14 03:05:31 -0700131 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000132
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000133 // new SSRC reset old reports
134 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
135 _lastReceivedSRNTPsecs = 0;
136 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000137
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000138 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139}
140
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000141uint32_t RTCPReceiver::RemoteSSRC() const {
danilchap7c9426c2016-04-14 03:05:31 -0700142 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000143 return _remoteSSRC;
144}
145
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000146void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
147 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000148 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000149 {
danilchap7c9426c2016-04-14 03:05:31 -0700150 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000151 old_ssrc = main_ssrc_;
152 main_ssrc_ = main_ssrc;
153 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000154 }
155 {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000156 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
157 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000158 }
159 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000160}
161
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000162int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000163 int64_t* RTT,
164 int64_t* avgRTT,
165 int64_t* minRTT,
166 int64_t* maxRTT) const {
danilchap7c9426c2016-04-14 03:05:31 -0700167 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000169 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000170 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000171
172 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000173 return -1;
174 }
175 if (RTT) {
176 *RTT = reportBlock->RTT;
177 }
178 if (avgRTT) {
179 *avgRTT = reportBlock->avgRTT;
180 }
181 if (minRTT) {
182 *minRTT = reportBlock->minRTT;
183 }
184 if (maxRTT) {
185 *maxRTT = reportBlock->maxRTT;
186 }
187 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100190void RTCPReceiver::SetRtcpXrRrtrStatus(bool enable) {
danilchap7c9426c2016-04-14 03:05:31 -0700191 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100192 xr_rrtr_status_ = enable;
193}
194
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000195bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000196 assert(rtt_ms);
danilchap7c9426c2016-04-14 03:05:31 -0700197 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000198 if (xr_rr_rtt_ms_ == 0) {
199 return false;
200 }
201 *rtt_ms = xr_rr_rtt_ms_;
202 xr_rr_rtt_ms_ = 0;
203 return true;
204}
205
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000206// TODO(pbos): Make this fail when we haven't received NTP.
207bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
208 uint32_t* ReceivedNTPfrac,
209 uint32_t* RTCPArrivalTimeSecs,
210 uint32_t* RTCPArrivalTimeFrac,
danilchapda161d72016-08-19 07:29:46 -0700211 uint32_t* rtcp_timestamp) const {
212 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
213 if (ReceivedNTPsecs) {
214 *ReceivedNTPsecs =
215 _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
216 }
217 if (ReceivedNTPfrac) {
218 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
219 }
220 if (RTCPArrivalTimeFrac) {
221 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we
222 // received a RTCP packet
223 // with a send block
224 }
225 if (RTCPArrivalTimeSecs) {
226 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
227 }
228 if (rtcp_timestamp) {
229 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
230 }
231 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000232}
233
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000234bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
235 RtcpReceiveTimeInfo* info) const {
236 assert(info);
danilchap7c9426c2016-04-14 03:05:31 -0700237 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000238 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
239 return false;
240 }
241
242 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
243 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
244
245 // Get the delay since last received report (RFC 3611).
danilchapda161d72016-08-19 07:29:46 -0700246 uint32_t receive_time =
247 RTCPUtility::MidNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000248
249 uint32_t ntp_sec = 0;
250 uint32_t ntp_frac = 0;
251 _clock->CurrentNtp(ntp_sec, ntp_frac);
252 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
253
254 info->delaySinceLastRR = now - receive_time;
255 return true;
256}
257
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000258int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
259 assert(senderInfo);
danilchap7c9426c2016-04-14 03:05:31 -0700260 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000261 if (_lastReceivedSRNTPsecs == 0) {
262 return -1;
263 }
264 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
265 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
268// statistics
269// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000270int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000271 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000272 assert(receiveBlocks);
danilchap7c9426c2016-04-14 03:05:31 -0700273 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000274 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
275 for (; it != _receivedReportBlockMap.end(); ++it) {
276 const ReportBlockInfoMap* info_map = &(it->second);
277 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
278 for (; it_info != info_map->end(); ++it_info) {
279 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
280 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000281 }
282 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
danilchapda161d72016-08-19 07:29:46 -0700285int32_t RTCPReceiver::IncomingRTCPPacket(
286 RTCPPacketInformation& rtcpPacketInformation,
287 RTCPUtility::RTCPParserV2* rtcpParser) {
288 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000289
danilchapda161d72016-08-19 07:29:46 -0700290 _lastReceived = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000291
danilchapda161d72016-08-19 07:29:46 -0700292 if (packet_type_counter_.first_packet_time_ms == -1) {
293 packet_type_counter_.first_packet_time_ms = _lastReceived;
294 }
295
296 RTCPUtility::RTCPPacketTypes pktType = rtcpParser->Begin();
297 while (pktType != RTCPPacketTypes::kInvalid) {
298 // Each "case" is responsible for iterate the parser to the
299 // next top level packet.
300 switch (pktType) {
301 case RTCPPacketTypes::kSr:
302 case RTCPPacketTypes::kRr:
303 HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
304 break;
305 case RTCPPacketTypes::kSdes:
306 HandleSDES(*rtcpParser, rtcpPacketInformation);
307 break;
308 case RTCPPacketTypes::kXrHeader:
309 HandleXrHeader(*rtcpParser, rtcpPacketInformation);
310 break;
311 case RTCPPacketTypes::kXrReceiverReferenceTime:
312 HandleXrReceiveReferenceTime(*rtcpParser, rtcpPacketInformation);
313 break;
314 case RTCPPacketTypes::kXrDlrrReportBlock:
315 HandleXrDlrrReportBlock(*rtcpParser, rtcpPacketInformation);
316 break;
danilchapda161d72016-08-19 07:29:46 -0700317 case RTCPPacketTypes::kBye:
318 HandleBYE(*rtcpParser);
319 break;
320 case RTCPPacketTypes::kRtpfbNack:
321 HandleNACK(*rtcpParser, rtcpPacketInformation);
322 break;
323 case RTCPPacketTypes::kRtpfbTmmbr:
324 HandleTMMBR(*rtcpParser, rtcpPacketInformation);
325 break;
326 case RTCPPacketTypes::kRtpfbTmmbn:
327 HandleTMMBN(*rtcpParser, rtcpPacketInformation);
328 break;
329 case RTCPPacketTypes::kRtpfbSrReq:
330 HandleSR_REQ(*rtcpParser, rtcpPacketInformation);
331 break;
332 case RTCPPacketTypes::kPsfbPli:
333 HandlePLI(*rtcpParser, rtcpPacketInformation);
334 break;
335 case RTCPPacketTypes::kPsfbSli:
336 HandleSLI(*rtcpParser, rtcpPacketInformation);
337 break;
338 case RTCPPacketTypes::kPsfbRpsi:
339 HandleRPSI(*rtcpParser, rtcpPacketInformation);
340 break;
danilchapda161d72016-08-19 07:29:46 -0700341 case RTCPPacketTypes::kPsfbFir:
342 HandleFIR(*rtcpParser, rtcpPacketInformation);
343 break;
344 case RTCPPacketTypes::kPsfbApp:
345 HandlePsfbApp(*rtcpParser, rtcpPacketInformation);
346 break;
danilchapda161d72016-08-19 07:29:46 -0700347 case RTCPPacketTypes::kTransportFeedback:
348 HandleTransportFeedback(rtcpParser, &rtcpPacketInformation);
349 break;
350 default:
351 rtcpParser->Iterate();
352 break;
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000353 }
danilchapda161d72016-08-19 07:29:46 -0700354 pktType = rtcpParser->PacketType();
355 }
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000356
danilchapda161d72016-08-19 07:29:46 -0700357 if (packet_type_counter_observer_ != NULL) {
358 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
359 main_ssrc_, packet_type_counter_);
360 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000361
danilchapda161d72016-08-19 07:29:46 -0700362 num_skipped_packets_ += rtcpParser->NumSkippedBlocks();
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000363
danilchapda161d72016-08-19 07:29:46 -0700364 int64_t now = _clock->TimeInMilliseconds();
365 if (now - last_skipped_packets_warning_ >= kMaxWarningLogIntervalMs &&
366 num_skipped_packets_ > 0) {
367 last_skipped_packets_warning_ = now;
368 LOG(LS_WARNING) << num_skipped_packets_
369 << " RTCP blocks were skipped due to being malformed or of "
370 "unrecognized/unsupported type, during the past "
371 << (kMaxWarningLogIntervalMs / 1000) << " second period.";
372 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200373
danilchapda161d72016-08-19 07:29:46 -0700374 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000375}
376
danilchapda161d72016-08-19 07:29:46 -0700377void RTCPReceiver::HandleSenderReceiverReport(
378 RTCPUtility::RTCPParserV2& rtcpParser,
379 RTCPPacketInformation& rtcpPacketInformation) {
380 RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
381 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchapda161d72016-08-19 07:29:46 -0700383 assert((rtcpPacketType == RTCPPacketTypes::kRr) ||
384 (rtcpPacketType == RTCPPacketTypes::kSr));
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchapda161d72016-08-19 07:29:46 -0700386 // SR.SenderSSRC
387 // The synchronization source identifier for the originator of this SR packet
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchapda161d72016-08-19 07:29:46 -0700389 // rtcpPacket.RR.SenderSSRC
390 // The source of the packet sender, same as of SR? or is this a CE?
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchapda161d72016-08-19 07:29:46 -0700392 const uint32_t remoteSSRC = (rtcpPacketType == RTCPPacketTypes::kRr)
393 ? rtcpPacket.RR.SenderSSRC
394 : rtcpPacket.SR.SenderSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchapda161d72016-08-19 07:29:46 -0700396 rtcpPacketInformation.remoteSSRC = remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchapda161d72016-08-19 07:29:46 -0700398 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
399 if (!ptrReceiveInfo) {
400 rtcpParser.Iterate();
401 return;
402 }
403
404 if (rtcpPacketType == RTCPPacketTypes::kSr) {
405 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
406 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
407
408 if (_remoteSSRC ==
409 remoteSSRC) // have I received RTP packets from this party
niklase@google.com470e71d2011-07-07 08:21:25 +0000410 {
danilchapda161d72016-08-19 07:29:46 -0700411 // only signal that we have received a SR when we accept one
412 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
413
414 rtcpPacketInformation.ntp_secs = rtcpPacket.SR.NTPMostSignificant;
415 rtcpPacketInformation.ntp_frac = rtcpPacket.SR.NTPLeastSignificant;
416 rtcpPacketInformation.rtp_timestamp = rtcpPacket.SR.RTPTimestamp;
417
418 // We will only store the send report from one source, but
419 // we will store all the receive block
420
421 // Save the NTP time of this report
422 _remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
423 _remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
424 _remoteSenderInfo.RTPtimeStamp = rtcpPacket.SR.RTPTimestamp;
425 _remoteSenderInfo.sendPacketCount = rtcpPacket.SR.SenderPacketCount;
426 _remoteSenderInfo.sendOctetCount = rtcpPacket.SR.SenderOctetCount;
427
428 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
429 } else {
430 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000431 }
danilchapda161d72016-08-19 07:29:46 -0700432 } else {
433 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
434 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
danilchapda161d72016-08-19 07:29:46 -0700436 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
437 }
438 // Update that this remote is alive.
439 ptrReceiveInfo->last_time_received_ms = _clock->TimeInMilliseconds();
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000440
danilchapda161d72016-08-19 07:29:46 -0700441 rtcpPacketType = rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
danilchapda161d72016-08-19 07:29:46 -0700443 while (rtcpPacketType == RTCPPacketTypes::kReportBlockItem) {
444 HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000445 rtcpPacketType = rtcpParser.Iterate();
danilchapda161d72016-08-19 07:29:46 -0700446 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000447}
448
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000449void RTCPReceiver::HandleReportBlock(
450 const RTCPUtility::RTCPPacket& rtcpPacket,
451 RTCPPacketInformation& rtcpPacketInformation,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000452 uint32_t remoteSSRC)
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000453 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000454 // This will be called once per report block in the RTCP packet.
455 // We filter out all report blocks that are not for us.
456 // Each packet has max 31 RR blocks.
457 //
458 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000460 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
461 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000463 // Filter out all report blocks that are not for us.
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000464 if (registered_ssrcs_.find(rtcpPacket.ReportBlockItem.SSRC) ==
465 registered_ssrcs_.end()) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000466 // This block is not for us ignore it.
467 return;
468 }
469
danilchapda161d72016-08-19 07:29:46 -0700470 RTCPReportBlockInformation* reportBlock = CreateOrGetReportBlockInformation(
471 remoteSSRC, rtcpPacket.ReportBlockItem.SSRC);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000472 if (reportBlock == NULL) {
danilchapda161d72016-08-19 07:29:46 -0700473 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation(" << remoteSSRC
474 << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000475 return;
476 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000477
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000478 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000479 const RTCPPacketReportBlockItem& rb = rtcpPacket.ReportBlockItem;
480 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
481 reportBlock->remoteReceiveBlock.sourceSSRC = rb.SSRC;
482 reportBlock->remoteReceiveBlock.fractionLost = rb.FractionLost;
483 reportBlock->remoteReceiveBlock.cumulativeLost =
484 rb.CumulativeNumOfPacketsLost;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000485 if (rb.ExtendedHighestSequenceNumber >
486 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
487 // We have successfully delivered new RTP packets to the remote side after
488 // the last RR was sent from the remote side.
489 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000490 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000491 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
492 rb.ExtendedHighestSequenceNumber;
493 reportBlock->remoteReceiveBlock.jitter = rb.Jitter;
494 reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
495 reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
496
497 if (rtcpPacket.ReportBlockItem.Jitter > reportBlock->remoteMaxJitter) {
498 reportBlock->remoteMaxJitter = rtcpPacket.ReportBlockItem.Jitter;
499 }
500
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100501 int64_t rtt = 0;
Danil Chapovalova094fd12016-02-22 18:59:36 +0100502 uint32_t send_time = rtcpPacket.ReportBlockItem.LastSR;
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100503 // RFC3550, section 6.4.1, LSR field discription states:
504 // If no SR has been received yet, the field is set to zero.
505 // Receiver rtp_rtcp module is not expected to calculate rtt using
506 // Sender Reports even if it accidentally can.
507 if (!receiver_only_ && send_time != 0) {
Danil Chapovalova094fd12016-02-22 18:59:36 +0100508 uint32_t delay = rtcpPacket.ReportBlockItem.DelayLastSR;
509 // Local NTP time.
510 uint32_t receive_time = CompactNtp(NtpTime(*_clock));
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000511
Danil Chapovalova094fd12016-02-22 18:59:36 +0100512 // RTT in 1/(2^16) seconds.
513 uint32_t rtt_ntp = receive_time - delay - send_time;
514 // Convert to 1/1000 seconds (milliseconds).
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100515 rtt = CompactNtpRttToMs(rtt_ntp);
Danil Chapovalova094fd12016-02-22 18:59:36 +0100516 if (rtt > reportBlock->maxRTT) {
517 // Store max RTT.
518 reportBlock->maxRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000519 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000520 if (reportBlock->minRTT == 0) {
Danil Chapovalova094fd12016-02-22 18:59:36 +0100521 // First RTT.
522 reportBlock->minRTT = rtt;
523 } else if (rtt < reportBlock->minRTT) {
524 // Store min RTT.
525 reportBlock->minRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 }
Danil Chapovalova094fd12016-02-22 18:59:36 +0100527 // Store last RTT.
528 reportBlock->RTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000530 // store average RTT
531 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000532 float ac = static_cast<float>(reportBlock->numAverageCalcs);
533 float newAverage =
Danil Chapovalova094fd12016-02-22 18:59:36 +0100534 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * rtt);
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000535 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000536 } else {
Danil Chapovalova094fd12016-02-22 18:59:36 +0100537 // First RTT.
538 reportBlock->avgRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000540 reportBlock->numAverageCalcs++;
541 }
542
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000543 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT", rb.SSRC,
Danil Chapovalova094fd12016-02-22 18:59:36 +0100544 rtt);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000545
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000546 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000547}
548
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000549RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
550 uint32_t remote_ssrc,
551 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000552 RTCPReportBlockInformation* info =
553 GetReportBlockInformation(remote_ssrc, source_ssrc);
554 if (info == NULL) {
555 info = new RTCPReportBlockInformation;
556 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000557 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000558 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559}
560
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000561RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
562 uint32_t remote_ssrc,
563 uint32_t source_ssrc) const {
564 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000565 if (it == _receivedReportBlockMap.end()) {
566 return NULL;
567 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000568 const ReportBlockInfoMap* info_map = &(it->second);
569 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
570 if (it_info == info_map->end()) {
571 return NULL;
572 }
573 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000574}
575
danilchapda161d72016-08-19 07:29:46 -0700576RTCPCnameInformation* RTCPReceiver::CreateCnameInformation(
577 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700578 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000579
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000581 _receivedCnameMap.find(remoteSSRC);
582
583 if (it != _receivedCnameMap.end()) {
584 return it->second;
585 }
586 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000587 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 _receivedCnameMap[remoteSSRC] = cnameInfo;
589 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000590}
591
danilchapda161d72016-08-19 07:29:46 -0700592RTCPCnameInformation* RTCPReceiver::GetCnameInformation(
593 uint32_t remoteSSRC) const {
danilchap7c9426c2016-04-14 03:05:31 -0700594 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000596 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000597 _receivedCnameMap.find(remoteSSRC);
598
599 if (it == _receivedCnameMap.end()) {
600 return NULL;
601 }
602 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000603}
604
danilchapda161d72016-08-19 07:29:46 -0700605RTCPReceiveInformation* RTCPReceiver::CreateReceiveInformation(
606 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700607 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000608
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000609 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000610 _receivedInfoMap.find(remoteSSRC);
611
612 if (it != _receivedInfoMap.end()) {
613 return it->second;
614 }
615 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
616 _receivedInfoMap[remoteSSRC] = receiveInfo;
617 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618}
619
danilchapda161d72016-08-19 07:29:46 -0700620RTCPReceiveInformation* RTCPReceiver::GetReceiveInformation(
621 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700622 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000624 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000625 _receivedInfoMap.find(remoteSSRC);
626 if (it == _receivedInfoMap.end()) {
627 return NULL;
628 }
629 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000630}
631
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000632bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700633 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000634 if (_lastReceivedRrMs == 0)
635 return false;
636
637 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000638 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000639 // Reset the timer to only trigger one log.
640 _lastReceivedRrMs = 0;
641 return true;
642 }
643 return false;
644}
645
646bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700647 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000648 if (_lastIncreasedSequenceNumberMs == 0)
649 return false;
650
651 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
danilchapda161d72016-08-19 07:29:46 -0700652 if (_clock->TimeInMilliseconds() >
653 _lastIncreasedSequenceNumberMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000654 // Reset the timer to only trigger one log.
655 _lastIncreasedSequenceNumberMs = 0;
656 return true;
657 }
658 return false;
659}
660
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000661bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
danilchap7c9426c2016-04-14 03:05:31 -0700662 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000663
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000665 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000666
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000667 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000668 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000669
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000670 while (receiveInfoIt != _receivedInfoMap.end()) {
671 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
672 if (receiveInfo == NULL) {
673 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000674 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000675 // time since last received rtcp packet
676 // when we dont have a lastTimeReceived and the object is marked
677 // readyForDelete it's removed from the map
danilchap2b616392016-08-18 06:17:42 -0700678 if (receiveInfo->last_time_received_ms > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000679 /// use audio define since we don't know what interval the remote peer is
680 // using
danilchap2b616392016-08-18 06:17:42 -0700681 if ((timeNow - receiveInfo->last_time_received_ms) >
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000682 5 * RTCP_INTERVAL_AUDIO_MS) {
683 // no rtcp packet for the last five regular intervals, reset limitations
danilchap2b616392016-08-18 06:17:42 -0700684 receiveInfo->ClearTmmbr();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000685 // prevent that we call this over and over again
danilchap2b616392016-08-18 06:17:42 -0700686 receiveInfo->last_time_received_ms = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 // send new TMMBN to all channels using the default codec
688 updateBoundingSet = true;
689 }
690 receiveInfoIt++;
danilchap2b616392016-08-18 06:17:42 -0700691 } else if (receiveInfo->ready_for_delete) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000693 std::map<uint32_t, RTCPReceiveInformation*>::iterator
danilchapda161d72016-08-19 07:29:46 -0700694 receiveInfoItemToBeErased = receiveInfoIt;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 receiveInfoIt++;
696 delete receiveInfoItemToBeErased->second;
697 _receivedInfoMap.erase(receiveInfoItemToBeErased);
698 } else {
699 receiveInfoIt++;
700 }
701 }
702 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000703}
704
danilchap2b616392016-08-18 06:17:42 -0700705std::vector<rtcp::TmmbItem> RTCPReceiver::BoundingSet(bool* tmmbr_owner) {
danilchap7c9426c2016-04-14 03:05:31 -0700706 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000707
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000708 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000709 _receivedInfoMap.find(_remoteSSRC);
710
711 if (receiveInfoIt == _receivedInfoMap.end()) {
danilchap2b616392016-08-18 06:17:42 -0700712 return std::vector<rtcp::TmmbItem>();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 }
714 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
danilchap2b616392016-08-18 06:17:42 -0700715 RTC_DCHECK(receiveInfo);
716
717 *tmmbr_owner = TMMBRHelp::IsOwner(receiveInfo->tmmbn, main_ssrc_);
718 return receiveInfo->tmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000719}
720
Erik Språnga38233a2015-07-24 09:58:18 +0200721void RTCPReceiver::HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser,
722 RTCPPacketInformation& rtcpPacketInformation) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000723 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +0200724 while (pktType == RTCPPacketTypes::kSdesChunk) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000725 HandleSDESChunk(rtcpParser);
726 pktType = rtcpParser.Iterate();
727 }
Erik Språnga38233a2015-07-24 09:58:18 +0200728 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000729}
730
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000731void RTCPReceiver::HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) {
732 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
733 RTCPCnameInformation* cnameInfo =
734 CreateCnameInformation(rtcpPacket.CName.SenderSSRC);
735 assert(cnameInfo);
niklase@google.com470e71d2011-07-07 08:21:25 +0000736
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000737 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
738 strncpy(cnameInfo->name, rtcpPacket.CName.CName, RTCP_CNAME_SIZE - 1);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000739 {
danilchap7c9426c2016-04-14 03:05:31 -0700740 rtc::CritScope lock(&_criticalSectionFeedbacks);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000741 if (stats_callback_ != NULL) {
742 stats_callback_->CNameChanged(rtcpPacket.CName.CName,
743 rtcpPacket.CName.SenderSSRC);
744 }
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +0000745 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000746}
747
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000748void RTCPReceiver::HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser,
749 RTCPPacketInformation& rtcpPacketInformation) {
750 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
Peter Boströmfe7a80c2015-04-23 17:53:17 +0200751 if (receiver_only_ || main_ssrc_ != rtcpPacket.NACK.MediaSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000752 // Not to us.
753 rtcpParser.Iterate();
754 return;
755 }
756 rtcpPacketInformation.ResetNACKPacketIdArray();
niklase@google.com470e71d2011-07-07 08:21:25 +0000757
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000758 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +0200759 while (pktType == RTCPPacketTypes::kRtpfbNackItem) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000760 HandleNACKItem(rtcpPacket, rtcpPacketInformation);
761 pktType = rtcpParser.Iterate();
762 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000763
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000764 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack) {
765 ++packet_type_counter_.nack_packets;
766 packet_type_counter_.nack_requests = nack_stats_.requests();
767 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
768 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000769}
770
danilchapda161d72016-08-19 07:29:46 -0700771void RTCPReceiver::HandleNACKItem(
772 const RTCPUtility::RTCPPacket& rtcpPacket,
773 RTCPPacketInformation& rtcpPacketInformation) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000774 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID);
775 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID);
niklase@google.com470e71d2011-07-07 08:21:25 +0000776
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000777 uint16_t bitMask = rtcpPacket.NACKItem.BitMask;
778 if (bitMask) {
danilchapda161d72016-08-19 07:29:46 -0700779 for (int i = 1; i <= 16; ++i) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000780 if (bitMask & 0x01) {
781 rtcpPacketInformation.AddNACKPacket(rtcpPacket.NACKItem.PacketID + i);
782 nack_stats_.ReportRequest(rtcpPacket.NACKItem.PacketID + i);
783 }
danilchapda161d72016-08-19 07:29:46 -0700784 bitMask = bitMask >> 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000785 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000786 }
787 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
niklase@google.com470e71d2011-07-07 08:21:25 +0000788}
789
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000790void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
791 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000792
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000793 // clear our lists
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000794 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
795 for (; it != _receivedReportBlockMap.end(); ++it) {
796 ReportBlockInfoMap* info_map = &(it->second);
danilchapda161d72016-08-19 07:29:46 -0700797 ReportBlockInfoMap::iterator it_info =
798 info_map->find(rtcpPacket.BYE.SenderSSRC);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000799 if (it_info != info_map->end()) {
800 delete it_info->second;
801 info_map->erase(it_info);
802 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000803 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000804
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000805 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000807 _receivedInfoMap.find(rtcpPacket.BYE.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000808
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000809 if (receiveInfoIt != _receivedInfoMap.end()) {
danilchap2b616392016-08-18 06:17:42 -0700810 receiveInfoIt->second->ready_for_delete = true;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000811 }
812
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000813 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000814 _receivedCnameMap.find(rtcpPacket.BYE.SenderSSRC);
815
816 if (cnameInfoIt != _receivedCnameMap.end()) {
817 delete cnameInfoIt->second;
818 _receivedCnameMap.erase(cnameInfoIt);
819 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000820 xr_rr_rtt_ms_ = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000821 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000822}
823
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000824void RTCPReceiver::HandleXrHeader(
825 RTCPUtility::RTCPParserV2& parser,
826 RTCPPacketInformation& rtcpPacketInformation) {
827 const RTCPUtility::RTCPPacket& packet = parser.Packet();
828
829 rtcpPacketInformation.xr_originator_ssrc = packet.XR.OriginatorSSRC;
830
831 parser.Iterate();
832}
833
834void RTCPReceiver::HandleXrReceiveReferenceTime(
835 RTCPUtility::RTCPParserV2& parser,
836 RTCPPacketInformation& rtcpPacketInformation) {
837 const RTCPUtility::RTCPPacket& packet = parser.Packet();
838
839 _remoteXRReceiveTimeInfo.sourceSSRC =
840 rtcpPacketInformation.xr_originator_ssrc;
841
842 _remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
843 packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
844 packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
845
846 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
847
848 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
849
850 parser.Iterate();
851}
852
853void RTCPReceiver::HandleXrDlrrReportBlock(
854 RTCPUtility::RTCPParserV2& parser,
855 RTCPPacketInformation& rtcpPacketInformation) {
856 const RTCPUtility::RTCPPacket& packet = parser.Packet();
857 // Iterate through sub-block(s), if any.
858 RTCPUtility::RTCPPacketTypes packet_type = parser.Iterate();
859
Erik Språng242e22b2015-05-11 10:17:43 +0200860 while (packet_type == RTCPPacketTypes::kXrDlrrReportBlockItem) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000861 HandleXrDlrrReportBlockItem(packet, rtcpPacketInformation);
862 packet_type = parser.Iterate();
863 }
864}
865
866void RTCPReceiver::HandleXrDlrrReportBlockItem(
867 const RTCPUtility::RTCPPacket& packet,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000868 RTCPPacketInformation& rtcpPacketInformation)
869 EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000870 if (registered_ssrcs_.find(packet.XRDLRRReportBlockItem.SSRC) ==
871 registered_ssrcs_.end()) {
872 // Not to us.
873 return;
874 }
875
876 rtcpPacketInformation.xr_dlrr_item = true;
877
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100878 // Caller should explicitly enable rtt calculation using extended reports.
879 if (!xr_rrtr_status_)
880 return;
881
Danil Chapovalova094fd12016-02-22 18:59:36 +0100882 // The send_time and delay_rr fields are in units of 1/2^16 sec.
883 uint32_t send_time = packet.XRDLRRReportBlockItem.LastRR;
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100884 // RFC3611, section 4.5, LRR field discription states:
Danil Chapovalova094fd12016-02-22 18:59:36 +0100885 // If no such block has been received, the field is set to zero.
886 if (send_time == 0)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000887 return;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000888
Danil Chapovalova094fd12016-02-22 18:59:36 +0100889 uint32_t delay_rr = packet.XRDLRRReportBlockItem.DelayLastRR;
890 uint32_t now = CompactNtp(NtpTime(*_clock));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000891
Danil Chapovalova094fd12016-02-22 18:59:36 +0100892 uint32_t rtt_ntp = now - delay_rr - send_time;
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100893 xr_rr_rtt_ms_ = CompactNtpRttToMs(rtt_ntp);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000894
895 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
896}
897
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000898void RTCPReceiver::HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser,
899 RTCPPacketInformation& rtcpPacketInformation) {
900 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000901 if (main_ssrc_ == rtcpPacket.PLI.MediaSSRC) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000902 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000903
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000904 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000905 // Received a signal that we need to send a new key frame.
906 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
907 }
908 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000909}
910
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000911void RTCPReceiver::HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser,
912 RTCPPacketInformation& rtcpPacketInformation) {
913 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000914
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000915 uint32_t senderSSRC = rtcpPacket.TMMBR.SenderSSRC;
916 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
917 if (ptrReceiveInfo == NULL) {
918 // This remote SSRC must be saved before.
919 rtcpParser.Iterate();
920 return;
921 }
922 if (rtcpPacket.TMMBR.MediaSSRC) {
923 // rtcpPacket.TMMBR.MediaSSRC SHOULD be 0 if same as SenderSSRC
924 // in relay mode this is a valid number
925 senderSSRC = rtcpPacket.TMMBR.MediaSSRC;
926 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000927
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000928 // Use packet length to calc max number of TMMBR blocks
929 // each TMMBR block is 8 bytes
930 ptrdiff_t maxNumOfTMMBRBlocks = rtcpParser.LengthLeft() / 8;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000932 // sanity, we can't have more than what's in one packet
933 if (maxNumOfTMMBRBlocks > 200) {
934 assert(false);
935 rtcpParser.Iterate();
936 return;
937 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000938
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000939 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +0200940 while (pktType == RTCPPacketTypes::kRtpfbTmmbrItem) {
danilchapda161d72016-08-19 07:29:46 -0700941 HandleTMMBRItem(*ptrReceiveInfo, rtcpPacket, rtcpPacketInformation,
942 senderSSRC);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000943 pktType = rtcpParser.Iterate();
944 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000945}
946
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000947void RTCPReceiver::HandleTMMBRItem(RTCPReceiveInformation& receiveInfo,
948 const RTCPUtility::RTCPPacket& rtcpPacket,
949 RTCPPacketInformation& rtcpPacketInformation,
950 uint32_t senderSSRC) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000951 if (main_ssrc_ == rtcpPacket.TMMBRItem.SSRC &&
952 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate > 0) {
danilchap2b616392016-08-18 06:17:42 -0700953 receiveInfo.InsertTmmbrItem(
954 senderSSRC,
955 rtcp::TmmbItem(rtcpPacket.TMMBRItem.SSRC,
956 rtcpPacket.TMMBRItem.MaxTotalMediaBitRate * 1000,
957 rtcpPacket.TMMBRItem.MeasuredOverhead),
958 _clock->TimeInMilliseconds());
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000959 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
960 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000961}
962
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000963void RTCPReceiver::HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser,
964 RTCPPacketInformation& rtcpPacketInformation) {
965 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
danilchapda161d72016-08-19 07:29:46 -0700966 RTCPReceiveInformation* ptrReceiveInfo =
967 GetReceiveInformation(rtcpPacket.TMMBN.SenderSSRC);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000968 if (ptrReceiveInfo == NULL) {
969 // This remote SSRC must be saved before.
niklase@google.com470e71d2011-07-07 08:21:25 +0000970 rtcpParser.Iterate();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000971 return;
972 }
973 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
974 // Use packet length to calc max number of TMMBN blocks
975 // each TMMBN block is 8 bytes
976 ptrdiff_t maxNumOfTMMBNBlocks = rtcpParser.LengthLeft() / 8;
977
978 // sanity, we cant have more than what's in one packet
979 if (maxNumOfTMMBNBlocks > 200) {
980 assert(false);
981 rtcpParser.Iterate();
982 return;
983 }
984
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000985 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +0200986 while (pktType == RTCPPacketTypes::kRtpfbTmmbnItem) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000987 HandleTMMBNItem(*ptrReceiveInfo, rtcpPacket);
988 pktType = rtcpParser.Iterate();
989 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000990}
991
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000992void RTCPReceiver::HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser,
993 RTCPPacketInformation& rtcpPacketInformation) {
994 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
995 rtcpParser.Iterate();
niklase@google.com470e71d2011-07-07 08:21:25 +0000996}
997
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000998void RTCPReceiver::HandleTMMBNItem(RTCPReceiveInformation& receiveInfo,
999 const RTCPUtility::RTCPPacket& rtcpPacket) {
danilchap2b616392016-08-18 06:17:42 -07001000 receiveInfo.tmmbn.emplace_back(
1001 rtcpPacket.TMMBNItem.SSRC,
1002 rtcpPacket.TMMBNItem.MaxTotalMediaBitRate * 1000,
1003 rtcpPacket.TMMBNItem.MeasuredOverhead);
niklase@google.com470e71d2011-07-07 08:21:25 +00001004}
1005
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001006void RTCPReceiver::HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser,
1007 RTCPPacketInformation& rtcpPacketInformation) {
1008 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1009 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +02001010 while (pktType == RTCPPacketTypes::kPsfbSliItem) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001011 HandleSLIItem(rtcpPacket, rtcpPacketInformation);
1012 pktType = rtcpParser.Iterate();
1013 }
1014}
1015
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001016void RTCPReceiver::HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket,
1017 RTCPPacketInformation& rtcpPacketInformation) {
1018 // in theory there could be multiple slices lost
danilchapda161d72016-08-19 07:29:46 -07001019 rtcpPacketInformation.rtcpPacketTypeFlags |=
1020 kRtcpSli; // received signal that we need to refresh a slice
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001021 rtcpPacketInformation.sliPictureId = rtcpPacket.SLIItem.PictureId;
niklase@google.com470e71d2011-07-07 08:21:25 +00001022}
1023
danilchapda161d72016-08-19 07:29:46 -07001024void RTCPReceiver::HandleRPSI(
1025 RTCPUtility::RTCPParserV2& rtcpParser,
1026 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) {
1027 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1028 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
1029 if (pktType == RTCPPacketTypes::kPsfbRpsiItem) {
1030 if (rtcpPacket.RPSI.NumberOfValidBits % 8 != 0) {
1031 // to us unknown
1032 // continue
1033 rtcpParser.Iterate();
1034 return;
niklase@google.com470e71d2011-07-07 08:21:25 +00001035 }
danilchapda161d72016-08-19 07:29:46 -07001036 // Received signal that we have a confirmed reference picture.
1037 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi;
1038 rtcpPacketInformation.rpsiPictureId = 0;
1039
1040 // convert NativeBitString to rpsiPictureId
1041 uint8_t numberOfBytes = rtcpPacket.RPSI.NumberOfValidBits / 8;
1042 for (uint8_t n = 0; n < (numberOfBytes - 1); n++) {
1043 rtcpPacketInformation.rpsiPictureId +=
1044 (rtcpPacket.RPSI.NativeBitString[n] & 0x7f);
1045 rtcpPacketInformation.rpsiPictureId <<= 7; // prepare next
1046 }
1047 rtcpPacketInformation.rpsiPictureId +=
1048 (rtcpPacket.RPSI.NativeBitString[numberOfBytes - 1] & 0x7f);
1049 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001050}
1051
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001052void RTCPReceiver::HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser,
1053 RTCPPacketInformation& rtcpPacketInformation) {
1054 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +02001055 if (pktType == RTCPPacketTypes::kPsfbRemb) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001056 pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +02001057 if (pktType == RTCPPacketTypes::kPsfbRembItem) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001058 HandleREMBItem(rtcpParser, rtcpPacketInformation);
1059 rtcpParser.Iterate();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001060 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001061 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001062}
1063
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001064void RTCPReceiver::HandleREMBItem(
1065 RTCPUtility::RTCPParserV2& rtcpParser,
1066 RTCPPacketInformation& rtcpPacketInformation) {
1067 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1068 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1069 rtcpPacketInformation.receiverEstimatedMaxBitrate =
1070 rtcpPacket.REMBItem.BitRate;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001071}
1072
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001073void RTCPReceiver::HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser,
1074 RTCPPacketInformation& rtcpPacketInformation) {
1075 const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
1076 RTCPReceiveInformation* ptrReceiveInfo =
1077 GetReceiveInformation(rtcpPacket.FIR.SenderSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001078
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001079 RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Iterate();
Erik Språng242e22b2015-05-11 10:17:43 +02001080 while (pktType == RTCPPacketTypes::kPsfbFirItem) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001081 HandleFIRItem(ptrReceiveInfo, rtcpPacket, rtcpPacketInformation);
1082 pktType = rtcpParser.Iterate();
1083 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001084}
1085
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001086void RTCPReceiver::HandleFIRItem(RTCPReceiveInformation* receiveInfo,
1087 const RTCPUtility::RTCPPacket& rtcpPacket,
1088 RTCPPacketInformation& rtcpPacketInformation) {
1089 // Is it our sender that is requested to generate a new keyframe
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001090 if (main_ssrc_ != rtcpPacket.FIRItem.SSRC) {
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001091 return;
1092 }
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001093
1094 ++packet_type_counter_.fir_packets;
1095
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001096 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1097 // we don't know who this originate from
1098 if (receiveInfo) {
1099 // check if we have reported this FIRSequenceNumber before
1100 if (rtcpPacket.FIRItem.CommandSequenceNumber !=
danilchap2b616392016-08-18 06:17:42 -07001101 receiveInfo->last_fir_sequence_number) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001102 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001103 // sanity; don't go crazy with the callbacks
danilchap2b616392016-08-18 06:17:42 -07001104 if ((now - receiveInfo->last_fir_request_ms) > RTCP_MIN_FRAME_LENGTH_MS) {
1105 receiveInfo->last_fir_request_ms = now;
1106 receiveInfo->last_fir_sequence_number =
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001107 rtcpPacket.FIRItem.CommandSequenceNumber;
1108 // received signal that we need to send a new key frame
1109 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1110 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001112 } else {
1113 // received signal that we need to send a new key frame
1114 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1115 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001116}
1117
Erik Språng6b8d3552015-09-24 15:06:57 +02001118void RTCPReceiver::HandleTransportFeedback(
1119 RTCPUtility::RTCPParserV2* rtcp_parser,
1120 RTCPHelp::RTCPPacketInformation* rtcp_packet_information) {
1121 rtcp::RtcpPacket* packet = rtcp_parser->ReleaseRtcpPacket();
1122 RTC_DCHECK(packet != nullptr);
1123 rtcp_packet_information->rtcpPacketTypeFlags |= kRtcpTransportFeedback;
1124 rtcp_packet_information->transport_feedback_.reset(
1125 static_cast<rtcp::TransportFeedback*>(packet));
1126
1127 rtcp_parser->Iterate();
1128}
danilchap287e5482016-08-16 15:15:39 -07001129
danilchap853ecb22016-08-22 08:26:15 -07001130void RTCPReceiver::UpdateTmmbr() {
1131 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -07001132 std::vector<rtcp::TmmbItem> bounding =
danilchap853ecb22016-08-22 08:26:15 -07001133 TMMBRHelp::FindBoundingSet(TmmbrReceived());
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001134
danilchap853ecb22016-08-22 08:26:15 -07001135 if (!bounding.empty() && _cbRtcpBandwidthObserver) {
1136 // We have a new bandwidth estimate on this channel.
danilchap2f69ce92016-08-16 03:21:38 -07001137 uint64_t bitrate_bps = TMMBRHelp::CalcMinBitrateBps(bounding);
1138 if (bitrate_bps <= std::numeric_limits<uint32_t>::max())
1139 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate_bps);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001140 }
danilchap853ecb22016-08-22 08:26:15 -07001141
1142 // Set bounding set: inform remote clients about the new bandwidth.
1143 _rtpRtcp.SetTmmbn(std::move(bounding));
niklase@google.com470e71d2011-07-07 08:21:25 +00001144}
1145
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001146void RTCPReceiver::RegisterRtcpStatisticsCallback(
1147 RtcpStatisticsCallback* callback) {
danilchap7c9426c2016-04-14 03:05:31 -07001148 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001149 stats_callback_ = callback;
1150}
1151
1152RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
danilchap7c9426c2016-04-14 03:05:31 -07001153 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001154 return stats_callback_;
1155}
1156
niklase@google.com470e71d2011-07-07 08:21:25 +00001157// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001158void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001159 RTCPPacketInformation& rtcpPacketInformation) {
1160 // Process TMMBR and REMB first to avoid multiple callbacks
1161 // to OnNetworkChanged.
1162 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001163 // Might trigger a OnReceivedBandwidthEstimateUpdate.
danilchap853ecb22016-08-22 08:26:15 -07001164 UpdateTmmbr();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001165 }
sprang7dc39f32015-10-13 09:17:48 -07001166 uint32_t local_ssrc;
1167 std::set<uint32_t> registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001168 {
1169 // We don't want to hold this critsect when triggering the callbacks below.
danilchap7c9426c2016-04-14 03:05:31 -07001170 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001171 local_ssrc = main_ssrc_;
sprang7dc39f32015-10-13 09:17:48 -07001172 registered_ssrcs = registered_ssrcs_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001173 }
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001174 if (!receiver_only_ &&
Erik Språng6b8d3552015-09-24 15:06:57 +02001175 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001176 _rtpRtcp.OnRequestSendReport();
1177 }
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001178 if (!receiver_only_ &&
Erik Språng6b8d3552015-09-24 15:06:57 +02001179 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack)) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001180 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001181 LOG(LS_VERBOSE) << "Incoming NACK length: "
danilchapda161d72016-08-19 07:29:46 -07001182 << rtcpPacketInformation.nackSequenceNumbers.size();
Danil Chapovalov2800d742016-08-26 18:48:46 +02001183 _rtpRtcp.OnReceivedNack(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001184 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001185 }
1186 {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001187 // We need feedback that we have received a report block(s) so that we
1188 // can generate a new packet in a conference relay scenario, one received
1189 // report can generate several RTCP packets, based on number relayed/mixed
1190 // a send report block should go out to all receivers.
1191 if (_cbRtcpIntraFrameObserver) {
henrikg91d6ede2015-09-17 00:24:34 -07001192 RTC_DCHECK(!receiver_only_);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001193 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1194 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1195 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001196 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001197 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001198 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001199 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001200 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001202 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001203 }
1204 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1205 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001206 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001207 }
1208 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1209 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001210 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001211 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001213 if (_cbRtcpBandwidthObserver) {
henrikg91d6ede2015-09-17 00:24:34 -07001214 RTC_DCHECK(!receiver_only_);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001215 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001216 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001217 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001218 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1219 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1220 }
Erik Språng242e22b2015-05-11 10:17:43 +02001221 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) ||
1222 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr)) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001223 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001224 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
danilchapda161d72016-08-19 07:29:46 -07001225 rtcpPacketInformation.report_blocks, rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001226 now);
1227 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001228 }
isheriff6b4b5f32016-06-08 00:24:21 -07001229 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) ||
1230 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr)) {
1231 _rtpRtcp.OnReceivedRtcpReportBlocks(rtcpPacketInformation.report_blocks);
1232 }
1233
Erik Språng6b8d3552015-09-24 15:06:57 +02001234 if (_cbTransportFeedbackObserver &&
1235 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTransportFeedback)) {
1236 uint32_t media_source_ssrc =
1237 rtcpPacketInformation.transport_feedback_->GetMediaSourceSsrc();
sprang7dc39f32015-10-13 09:17:48 -07001238 if (media_source_ssrc == local_ssrc ||
1239 registered_ssrcs.find(media_source_ssrc) != registered_ssrcs.end()) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001240 _cbTransportFeedbackObserver->OnTransportFeedback(
1241 *rtcpPacketInformation.transport_feedback_.get());
1242 }
1243 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001244 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001245
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001246 if (!receiver_only_) {
danilchap7c9426c2016-04-14 03:05:31 -07001247 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001248 if (stats_callback_) {
1249 for (ReportBlockList::const_iterator it =
danilchapda161d72016-08-19 07:29:46 -07001250 rtcpPacketInformation.report_blocks.begin();
1251 it != rtcpPacketInformation.report_blocks.end(); ++it) {
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001252 RtcpStatistics stats;
1253 stats.cumulative_lost = it->cumulativeLost;
1254 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1255 stats.fraction_lost = it->fractionLost;
1256 stats.jitter = it->jitter;
1257
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001258 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001259 }
1260 }
1261 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001262}
1263
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001264int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001265 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001266 assert(cName);
1267
danilchap7c9426c2016-04-14 03:05:31 -07001268 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001269 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001270 if (cnameInfo == NULL) {
1271 return -1;
1272 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001273 cName[RTCP_CNAME_SIZE - 1] = 0;
1274 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1275 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001276}
1277
danilchap853ecb22016-08-22 08:26:15 -07001278std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() const {
danilchap7c9426c2016-04-14 03:05:31 -07001279 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap287e5482016-08-16 15:15:39 -07001280 std::vector<rtcp::TmmbItem> candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001281
danilchap287e5482016-08-16 15:15:39 -07001282 int64_t now_ms = _clock->TimeInMilliseconds();
1283
1284 for (const auto& kv : _receivedInfoMap) {
1285 RTCPReceiveInformation* receive_info = kv.second;
1286 RTC_DCHECK(receive_info);
danilchap2b616392016-08-18 06:17:42 -07001287 receive_info->GetTmmbrSet(now_ms, &candidates);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001288 }
danilchap287e5482016-08-16 15:15:39 -07001289 return candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001290}
1291
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001292} // namespace webrtc