blob: de319ca4b032df12e289a4e261fe71237d4473bf [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"
danilchap1b1863a2016-09-20 01:39:54 -070021#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
22#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
24#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
25#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
26#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
27#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
28#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
29#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
30#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
31#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
32#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
33#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
34#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
35#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
36#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010039#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070040#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010041#include "webrtc/system_wrappers/include/ntp_time.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000042
niklase@google.com470e71d2011-07-07 08:21:25 +000043namespace webrtc {
danilchap1b1863a2016-09-20 01:39:54 -070044namespace {
45
46using rtcp::CommonHeader;
47using rtcp::ReportBlock;
danilchap6a6f0892015-12-10 12:39:08 -080048using RTCPHelp::RTCPPacketInformation;
49using RTCPHelp::RTCPReceiveInformation;
50using RTCPHelp::RTCPReportBlockInformation;
danilchap6a6f0892015-12-10 12:39:08 -080051using RTCPUtility::RTCPCnameInformation;
52using RTCPUtility::RTCPPacketReportBlockItem;
53using RTCPUtility::RTCPPacketTypes;
niklase@google.com470e71d2011-07-07 08:21:25 +000054
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000055// The number of RTCP time intervals needed to trigger a timeout.
56const int kRrTimeoutIntervals = 3;
57
Erik Språng6b8d3552015-09-24 15:06:57 +020058const int64_t kMaxWarningLogIntervalMs = 10000;
59
danilchap1b1863a2016-09-20 01:39:54 -070060} // namespace
61
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000062RTCPReceiver::RTCPReceiver(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000063 Clock* clock,
Peter Boströmfe7a80c2015-04-23 17:53:17 +020064 bool receiver_only,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000065 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000066 RtcpBandwidthObserver* rtcp_bandwidth_observer,
67 RtcpIntraFrameObserver* rtcp_intra_frame_observer,
Erik Språng6b8d3552015-09-24 15:06:57 +020068 TransportFeedbackObserver* transport_feedback_observer,
danilchap59cb2bd2016-08-29 11:08:47 -070069 ModuleRtpRtcp* owner)
danilchap13deaad2016-05-24 13:25:27 -070070 : _clock(clock),
Peter Boströmfe7a80c2015-04-23 17:53:17 +020071 receiver_only_(receiver_only),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000072 _rtpRtcp(*owner),
mflodman@webrtc.org96abda02015-02-25 13:50:10 +000073 _cbRtcpBandwidthObserver(rtcp_bandwidth_observer),
74 _cbRtcpIntraFrameObserver(rtcp_intra_frame_observer),
Erik Språng6b8d3552015-09-24 15:06:57 +020075 _cbTransportFeedbackObserver(transport_feedback_observer),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000076 main_ssrc_(0),
77 _remoteSSRC(0),
78 _remoteSenderInfo(),
79 _lastReceivedSRNTPsecs(0),
80 _lastReceivedSRNTPfrac(0),
81 _lastReceivedXRNTPsecs(0),
82 _lastReceivedXRNTPfrac(0),
Danil Chapovalovc1e55c72016-03-09 15:14:35 +010083 xr_rrtr_status_(false),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000084 xr_rr_rtt_ms_(0),
85 _receivedInfoMap(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000086 _lastReceivedRrMs(0),
87 _lastIncreasedSequenceNumberMs(0),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000088 stats_callback_(NULL),
Erik Språng6b8d3552015-09-24 15:06:57 +020089 packet_type_counter_observer_(packet_type_counter_observer),
90 num_skipped_packets_(0),
91 last_skipped_packets_warning_(clock->TimeInMilliseconds()) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +000092 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +000093}
94
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000095RTCPReceiver::~RTCPReceiver() {
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +000096 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
97 for (; it != _receivedReportBlockMap.end(); ++it) {
98 ReportBlockInfoMap* info_map = &(it->second);
99 while (!info_map->empty()) {
100 ReportBlockInfoMap::iterator it_info = info_map->begin();
101 delete it_info->second;
102 info_map->erase(it_info);
103 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000104 }
105 while (!_receivedInfoMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000106 std::map<uint32_t, RTCPReceiveInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000107 _receivedInfoMap.begin();
108 delete first->second;
109 _receivedInfoMap.erase(first);
110 }
111 while (!_receivedCnameMap.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000112 std::map<uint32_t, RTCPCnameInformation*>::iterator first =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000113 _receivedCnameMap.begin();
114 delete first->second;
115 _receivedCnameMap.erase(first);
116 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000117}
118
danilchap59cb2bd2016-08-29 11:08:47 -0700119bool RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) {
danilchap1b1863a2016-09-20 01:39:54 -0700120 if (packet_size == 0) {
121 LOG(LS_WARNING) << "Incoming empty RTCP packet";
danilchap59cb2bd2016-08-29 11:08:47 -0700122 return false;
123 }
danilchap59cb2bd2016-08-29 11:08:47 -0700124
danilchap1b1863a2016-09-20 01:39:54 -0700125 RTCPHelp::RTCPPacketInformation packet_information;
126 if (!ParseCompoundPacket(packet, packet + packet_size, &packet_information))
127 return false;
128 TriggerCallbacksFromRTCPPacket(packet_information);
129 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000130}
131
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000132int64_t RTCPReceiver::LastReceivedReceiverReport() const {
danilchap7c9426c2016-04-14 03:05:31 -0700133 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000134 int64_t last_received_rr = -1;
135 for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
136 it != _receivedInfoMap.end(); ++it) {
danilchap2b616392016-08-18 06:17:42 -0700137 if (it->second->last_time_received_ms > last_received_rr) {
138 last_received_rr = it->second->last_time_received_ms;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000139 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000140 }
141 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000142}
143
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000144void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
danilchap7c9426c2016-04-14 03:05:31 -0700145 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000146
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000147 // new SSRC reset old reports
148 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
149 _lastReceivedSRNTPsecs = 0;
150 _lastReceivedSRNTPfrac = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000152 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000155uint32_t RTCPReceiver::RemoteSSRC() const {
danilchap7c9426c2016-04-14 03:05:31 -0700156 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000157 return _remoteSSRC;
158}
159
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000160void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
161 const std::set<uint32_t>& registered_ssrcs) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000162 uint32_t old_ssrc = 0;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000163 {
danilchap7c9426c2016-04-14 03:05:31 -0700164 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000165 old_ssrc = main_ssrc_;
166 main_ssrc_ = main_ssrc;
167 registered_ssrcs_ = registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000168 }
169 {
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000170 if (_cbRtcpIntraFrameObserver && old_ssrc != main_ssrc) {
171 _cbRtcpIntraFrameObserver->OnLocalSsrcChanged(old_ssrc, main_ssrc);
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000172 }
173 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000174}
175
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000176int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000177 int64_t* RTT,
178 int64_t* avgRTT,
179 int64_t* minRTT,
180 int64_t* maxRTT) const {
danilchap7c9426c2016-04-14 03:05:31 -0700181 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000182
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000183 RTCPReportBlockInformation* reportBlock =
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000184 GetReportBlockInformation(remoteSSRC, main_ssrc_);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000185
186 if (reportBlock == NULL) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000187 return -1;
188 }
189 if (RTT) {
190 *RTT = reportBlock->RTT;
191 }
192 if (avgRTT) {
193 *avgRTT = reportBlock->avgRTT;
194 }
195 if (minRTT) {
196 *minRTT = reportBlock->minRTT;
197 }
198 if (maxRTT) {
199 *maxRTT = reportBlock->maxRTT;
200 }
201 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100204void RTCPReceiver::SetRtcpXrRrtrStatus(bool enable) {
danilchap7c9426c2016-04-14 03:05:31 -0700205 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100206 xr_rrtr_status_ = enable;
207}
208
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000209bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000210 assert(rtt_ms);
danilchap7c9426c2016-04-14 03:05:31 -0700211 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000212 if (xr_rr_rtt_ms_ == 0) {
213 return false;
214 }
215 *rtt_ms = xr_rr_rtt_ms_;
216 xr_rr_rtt_ms_ = 0;
217 return true;
218}
219
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000220// TODO(pbos): Make this fail when we haven't received NTP.
221bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
222 uint32_t* ReceivedNTPfrac,
223 uint32_t* RTCPArrivalTimeSecs,
224 uint32_t* RTCPArrivalTimeFrac,
danilchapda161d72016-08-19 07:29:46 -0700225 uint32_t* rtcp_timestamp) const {
226 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
227 if (ReceivedNTPsecs) {
228 *ReceivedNTPsecs =
229 _remoteSenderInfo.NTPseconds; // NTP from incoming SendReport
230 }
231 if (ReceivedNTPfrac) {
232 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
233 }
234 if (RTCPArrivalTimeFrac) {
235 *RTCPArrivalTimeFrac = _lastReceivedSRNTPfrac; // local NTP time when we
236 // received a RTCP packet
237 // with a send block
238 }
239 if (RTCPArrivalTimeSecs) {
240 *RTCPArrivalTimeSecs = _lastReceivedSRNTPsecs;
241 }
242 if (rtcp_timestamp) {
243 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
244 }
245 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246}
247
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000248bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
249 RtcpReceiveTimeInfo* info) const {
250 assert(info);
danilchap7c9426c2016-04-14 03:05:31 -0700251 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000252 if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
253 return false;
254 }
255
256 info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
257 info->lastRR = _remoteXRReceiveTimeInfo.lastRR;
258
259 // Get the delay since last received report (RFC 3611).
danilchapda161d72016-08-19 07:29:46 -0700260 uint32_t receive_time =
261 RTCPUtility::MidNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000262
263 uint32_t ntp_sec = 0;
264 uint32_t ntp_frac = 0;
265 _clock->CurrentNtp(ntp_sec, ntp_frac);
266 uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);
267
268 info->delaySinceLastRR = now - receive_time;
269 return true;
270}
271
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000272int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
273 assert(senderInfo);
danilchap7c9426c2016-04-14 03:05:31 -0700274 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000275 if (_lastReceivedSRNTPsecs == 0) {
276 return -1;
277 }
278 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
279 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
282// statistics
283// we can get multiple receive reports when we receive the report from a CE
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000284int32_t RTCPReceiver::StatisticsReceived(
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000285 std::vector<RTCPReportBlock>* receiveBlocks) const {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000286 assert(receiveBlocks);
danilchap7c9426c2016-04-14 03:05:31 -0700287 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000288 ReportBlockMap::const_iterator it = _receivedReportBlockMap.begin();
289 for (; it != _receivedReportBlockMap.end(); ++it) {
290 const ReportBlockInfoMap* info_map = &(it->second);
291 ReportBlockInfoMap::const_iterator it_info = info_map->begin();
292 for (; it_info != info_map->end(); ++it_info) {
293 receiveBlocks->push_back(it_info->second->remoteReceiveBlock);
294 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000295 }
296 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000297}
298
danilchap1b1863a2016-09-20 01:39:54 -0700299bool RTCPReceiver::ParseCompoundPacket(
300 const uint8_t* packet_begin,
301 const uint8_t* packet_end,
302 RTCPPacketInformation* packet_information) {
danilchapda161d72016-08-19 07:29:46 -0700303 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000304
danilchap1b1863a2016-09-20 01:39:54 -0700305 CommonHeader rtcp_block;
306 for (const uint8_t* next_block = packet_begin; next_block != packet_end;
307 next_block = rtcp_block.NextPacket()) {
308 ptrdiff_t remaining_blocks_size = packet_end - next_block;
309 RTC_DCHECK_GT(remaining_blocks_size, 0);
310 if (!rtcp_block.Parse(next_block, remaining_blocks_size)) {
311 if (next_block == packet_begin) {
312 // Failed to parse 1st header, nothing was extracted from this packet.
313 LOG(LS_WARNING) << "Incoming invalid RTCP packet";
314 return false;
315 }
316 ++num_skipped_packets_;
317 break;
318 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000319
danilchap1b1863a2016-09-20 01:39:54 -0700320 if (packet_type_counter_.first_packet_time_ms == -1)
321 packet_type_counter_.first_packet_time_ms = _clock->TimeInMilliseconds();
danilchapda161d72016-08-19 07:29:46 -0700322
danilchap1b1863a2016-09-20 01:39:54 -0700323 switch (rtcp_block.type()) {
324 case rtcp::SenderReport::kPacketType:
325 HandleSenderReport(rtcp_block, *packet_information);
Danil Chapovalov91511f12016-09-15 16:24:02 +0200326 break;
danilchap1b1863a2016-09-20 01:39:54 -0700327 case rtcp::ReceiverReport::kPacketType:
328 HandleReceiverReport(rtcp_block, *packet_information);
danilchapda161d72016-08-19 07:29:46 -0700329 break;
danilchap1b1863a2016-09-20 01:39:54 -0700330 case rtcp::Sdes::kPacketType:
331 HandleSDES(rtcp_block, *packet_information);
danilchapda161d72016-08-19 07:29:46 -0700332 break;
danilchap1b1863a2016-09-20 01:39:54 -0700333 case rtcp::ExtendedReports::kPacketType:
334 HandleXr(rtcp_block, *packet_information);
danilchapda161d72016-08-19 07:29:46 -0700335 break;
danilchap1b1863a2016-09-20 01:39:54 -0700336 case rtcp::Bye::kPacketType:
337 HandleBYE(rtcp_block);
danilchapda161d72016-08-19 07:29:46 -0700338 break;
danilchap1b1863a2016-09-20 01:39:54 -0700339 case rtcp::Rtpfb::kPacketType:
340 switch (rtcp_block.fmt()) {
341 case rtcp::Nack::kFeedbackMessageType:
342 HandleNACK(rtcp_block, *packet_information);
343 break;
344 case rtcp::Tmmbr::kFeedbackMessageType:
345 HandleTMMBR(rtcp_block, *packet_information);
346 break;
347 case rtcp::Tmmbn::kFeedbackMessageType:
348 HandleTMMBN(rtcp_block, *packet_information);
349 break;
350 case rtcp::RapidResyncRequest::kFeedbackMessageType:
351 HandleSR_REQ(rtcp_block, *packet_information);
352 break;
353 case rtcp::TransportFeedback::kFeedbackMessageType:
354 HandleTransportFeedback(rtcp_block, packet_information);
355 break;
356 default:
357 ++num_skipped_packets_;
358 break;
359 }
danilchapda161d72016-08-19 07:29:46 -0700360 break;
danilchap1b1863a2016-09-20 01:39:54 -0700361 case rtcp::Psfb::kPacketType:
362 switch (rtcp_block.fmt()) {
363 case rtcp::Pli::kFeedbackMessageType:
364 HandlePLI(rtcp_block, *packet_information);
365 break;
366 case rtcp::Sli::kFeedbackMessageType:
367 HandleSLI(rtcp_block, *packet_information);
368 break;
369 case rtcp::Rpsi::kFeedbackMessageType:
370 HandleRPSI(rtcp_block, *packet_information);
371 break;
372 case rtcp::Fir::kFeedbackMessageType:
373 HandleFIR(rtcp_block, *packet_information);
374 break;
375 case rtcp::Remb::kFeedbackMessageType:
376 HandlePsfbApp(rtcp_block, *packet_information);
377 break;
378 default:
379 ++num_skipped_packets_;
380 break;
381 }
danilchapda161d72016-08-19 07:29:46 -0700382 break;
383 default:
danilchap1b1863a2016-09-20 01:39:54 -0700384 ++num_skipped_packets_;
danilchapda161d72016-08-19 07:29:46 -0700385 break;
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000386 }
danilchapda161d72016-08-19 07:29:46 -0700387 }
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000388
danilchapda161d72016-08-19 07:29:46 -0700389 if (packet_type_counter_observer_ != NULL) {
390 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
391 main_ssrc_, packet_type_counter_);
392 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000393
danilchapda161d72016-08-19 07:29:46 -0700394 int64_t now = _clock->TimeInMilliseconds();
395 if (now - last_skipped_packets_warning_ >= kMaxWarningLogIntervalMs &&
396 num_skipped_packets_ > 0) {
397 last_skipped_packets_warning_ = now;
398 LOG(LS_WARNING) << num_skipped_packets_
399 << " RTCP blocks were skipped due to being malformed or of "
400 "unrecognized/unsupported type, during the past "
401 << (kMaxWarningLogIntervalMs / 1000) << " second period.";
402 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200403
danilchap1b1863a2016-09-20 01:39:54 -0700404 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000405}
406
Danil Chapovalov91511f12016-09-15 16:24:02 +0200407void RTCPReceiver::HandleSenderReport(
danilchap1b1863a2016-09-20 01:39:54 -0700408 const CommonHeader& rtcp_block,
danilchapda161d72016-08-19 07:29:46 -0700409 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700410 rtcp::SenderReport sender_report;
411 if (!sender_report.Parse(rtcp_block)) {
412 ++num_skipped_packets_;
413 return;
414 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
danilchap1b1863a2016-09-20 01:39:54 -0700416 const uint32_t remoteSSRC = sender_report.sender_ssrc();
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
danilchapda161d72016-08-19 07:29:46 -0700418 rtcpPacketInformation.remoteSSRC = remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
danilchapda161d72016-08-19 07:29:46 -0700420 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
danilchap1b1863a2016-09-20 01:39:54 -0700421 if (!ptrReceiveInfo)
danilchapda161d72016-08-19 07:29:46 -0700422 return;
danilchapda161d72016-08-19 07:29:46 -0700423
Danil Chapovalov91511f12016-09-15 16:24:02 +0200424 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
425 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
danilchapda161d72016-08-19 07:29:46 -0700426
Danil Chapovalov91511f12016-09-15 16:24:02 +0200427 // Have I received RTP packets from this party?
428 if (_remoteSSRC == remoteSSRC) {
429 // Only signal that we have received a SR when we accept one.
430 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSr;
danilchapda161d72016-08-19 07:29:46 -0700431
danilchap1b1863a2016-09-20 01:39:54 -0700432 rtcpPacketInformation.ntp_secs = sender_report.ntp().seconds();
433 rtcpPacketInformation.ntp_frac = sender_report.ntp().fractions();
434 rtcpPacketInformation.rtp_timestamp = sender_report.rtp_timestamp();
danilchapda161d72016-08-19 07:29:46 -0700435
Danil Chapovalov91511f12016-09-15 16:24:02 +0200436 // Save the NTP time of this report.
danilchap1b1863a2016-09-20 01:39:54 -0700437 _remoteSenderInfo.NTPseconds = sender_report.ntp().seconds();
438 _remoteSenderInfo.NTPfraction = sender_report.ntp().fractions();
439 _remoteSenderInfo.RTPtimeStamp = sender_report.rtp_timestamp();
440 _remoteSenderInfo.sendPacketCount = sender_report.sender_packet_count();
441 _remoteSenderInfo.sendOctetCount = sender_report.sender_octet_count();
danilchapda161d72016-08-19 07:29:46 -0700442
Danil Chapovalov91511f12016-09-15 16:24:02 +0200443 _clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
danilchapda161d72016-08-19 07:29:46 -0700444 } else {
Danil Chapovalov91511f12016-09-15 16:24:02 +0200445 // We will only store the send report from one source, but
446 // we will store all the receive blocks.
danilchapda161d72016-08-19 07:29:46 -0700447 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
448 }
449 // Update that this remote is alive.
450 ptrReceiveInfo->last_time_received_ms = _clock->TimeInMilliseconds();
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000451
danilchap1b1863a2016-09-20 01:39:54 -0700452 for (const rtcp::ReportBlock report_block : sender_report.report_blocks())
453 HandleReportBlock(report_block, rtcpPacketInformation, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454}
455
Danil Chapovalov91511f12016-09-15 16:24:02 +0200456void RTCPReceiver::HandleReceiverReport(
danilchap1b1863a2016-09-20 01:39:54 -0700457 const CommonHeader& rtcp_block,
Danil Chapovalov91511f12016-09-15 16:24:02 +0200458 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700459 rtcp::ReceiverReport receiver_report;
460 if (!receiver_report.Parse(rtcp_block)) {
461 ++num_skipped_packets_;
462 return;
463 }
Danil Chapovalov91511f12016-09-15 16:24:02 +0200464
danilchap1b1863a2016-09-20 01:39:54 -0700465 const uint32_t remoteSSRC = receiver_report.sender_ssrc();
Danil Chapovalov91511f12016-09-15 16:24:02 +0200466
467 rtcpPacketInformation.remoteSSRC = remoteSSRC;
468
469 RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
danilchap1b1863a2016-09-20 01:39:54 -0700470 if (!ptrReceiveInfo)
Danil Chapovalov91511f12016-09-15 16:24:02 +0200471 return;
Danil Chapovalov91511f12016-09-15 16:24:02 +0200472
473 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
474 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
475
476 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
477
478 // Update that this remote is alive.
479 ptrReceiveInfo->last_time_received_ms = _clock->TimeInMilliseconds();
480
danilchap1b1863a2016-09-20 01:39:54 -0700481 for (const ReportBlock& report_block : receiver_report.report_blocks())
482 HandleReportBlock(report_block, rtcpPacketInformation, remoteSSRC);
Danil Chapovalov91511f12016-09-15 16:24:02 +0200483}
484
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000485void RTCPReceiver::HandleReportBlock(
danilchap1b1863a2016-09-20 01:39:54 -0700486 const ReportBlock& report_block,
andresp@webrtc.org7fb75ec2013-12-20 20:20:50 +0000487 RTCPPacketInformation& rtcpPacketInformation,
danilchap1b1863a2016-09-20 01:39:54 -0700488 uint32_t remoteSSRC) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000489 // This will be called once per report block in the RTCP packet.
490 // We filter out all report blocks that are not for us.
491 // Each packet has max 31 RR blocks.
492 //
493 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000494
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000495 // |rtcpPacket.ReportBlockItem.SSRC| is the SSRC identifier of the source to
496 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000498 // Filter out all report blocks that are not for us.
danilchap1b1863a2016-09-20 01:39:54 -0700499 if (registered_ssrcs_.count(report_block.source_ssrc()) == 0)
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000500 return;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000501
danilchap1b1863a2016-09-20 01:39:54 -0700502 RTCPReportBlockInformation* reportBlock =
503 CreateOrGetReportBlockInformation(remoteSSRC, report_block.source_ssrc());
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000504 if (reportBlock == NULL) {
danilchapda161d72016-08-19 07:29:46 -0700505 LOG(LS_WARNING) << "Failed to CreateReportBlockInformation(" << remoteSSRC
506 << ")";
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000507 return;
508 }
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000509
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000510 _lastReceivedRrMs = _clock->TimeInMilliseconds();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000511 reportBlock->remoteReceiveBlock.remoteSSRC = remoteSSRC;
danilchap1b1863a2016-09-20 01:39:54 -0700512 reportBlock->remoteReceiveBlock.sourceSSRC = report_block.source_ssrc();
513 reportBlock->remoteReceiveBlock.fractionLost = report_block.fraction_lost();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000514 reportBlock->remoteReceiveBlock.cumulativeLost =
danilchap1b1863a2016-09-20 01:39:54 -0700515 report_block.cumulative_lost();
516 if (report_block.extended_high_seq_num() >
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000517 reportBlock->remoteReceiveBlock.extendedHighSeqNum) {
518 // We have successfully delivered new RTP packets to the remote side after
519 // the last RR was sent from the remote side.
520 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000521 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000522 reportBlock->remoteReceiveBlock.extendedHighSeqNum =
danilchap1b1863a2016-09-20 01:39:54 -0700523 report_block.extended_high_seq_num();
524 reportBlock->remoteReceiveBlock.jitter = report_block.jitter();
525 reportBlock->remoteReceiveBlock.delaySinceLastSR =
526 report_block.delay_since_last_sr();
527 reportBlock->remoteReceiveBlock.lastSR = report_block.last_sr();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528
danilchap1b1863a2016-09-20 01:39:54 -0700529 if (report_block.jitter() > reportBlock->remoteMaxJitter)
530 reportBlock->remoteMaxJitter = report_block.jitter();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000531
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100532 int64_t rtt = 0;
danilchap1b1863a2016-09-20 01:39:54 -0700533 uint32_t send_time = report_block.last_sr();
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100534 // RFC3550, section 6.4.1, LSR field discription states:
535 // If no SR has been received yet, the field is set to zero.
536 // Receiver rtp_rtcp module is not expected to calculate rtt using
537 // Sender Reports even if it accidentally can.
538 if (!receiver_only_ && send_time != 0) {
danilchap1b1863a2016-09-20 01:39:54 -0700539 uint32_t delay = report_block.delay_since_last_sr();
Danil Chapovalova094fd12016-02-22 18:59:36 +0100540 // Local NTP time.
541 uint32_t receive_time = CompactNtp(NtpTime(*_clock));
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000542
Danil Chapovalova094fd12016-02-22 18:59:36 +0100543 // RTT in 1/(2^16) seconds.
544 uint32_t rtt_ntp = receive_time - delay - send_time;
545 // Convert to 1/1000 seconds (milliseconds).
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100546 rtt = CompactNtpRttToMs(rtt_ntp);
Danil Chapovalova094fd12016-02-22 18:59:36 +0100547 if (rtt > reportBlock->maxRTT) {
548 // Store max RTT.
549 reportBlock->maxRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000551 if (reportBlock->minRTT == 0) {
Danil Chapovalova094fd12016-02-22 18:59:36 +0100552 // First RTT.
553 reportBlock->minRTT = rtt;
554 } else if (rtt < reportBlock->minRTT) {
555 // Store min RTT.
556 reportBlock->minRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000557 }
Danil Chapovalova094fd12016-02-22 18:59:36 +0100558 // Store last RTT.
559 reportBlock->RTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000560
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000561 // store average RTT
562 if (reportBlock->numAverageCalcs != 0) {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000563 float ac = static_cast<float>(reportBlock->numAverageCalcs);
564 float newAverage =
Danil Chapovalova094fd12016-02-22 18:59:36 +0100565 ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * rtt);
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000566 reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000567 } else {
Danil Chapovalova094fd12016-02-22 18:59:36 +0100568 // First RTT.
569 reportBlock->avgRTT = rtt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000570 }
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000571 reportBlock->numAverageCalcs++;
572 }
573
danilchap1b1863a2016-09-20 01:39:54 -0700574 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT",
575 report_block.source_ssrc(), rtt);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000576
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000577 rtcpPacketInformation.AddReportInfo(*reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000578}
579
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000580RTCPReportBlockInformation* RTCPReceiver::CreateOrGetReportBlockInformation(
581 uint32_t remote_ssrc,
582 uint32_t source_ssrc) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000583 RTCPReportBlockInformation* info =
584 GetReportBlockInformation(remote_ssrc, source_ssrc);
585 if (info == NULL) {
586 info = new RTCPReportBlockInformation;
587 _receivedReportBlockMap[source_ssrc][remote_ssrc] = info;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000589 return info;
niklase@google.com470e71d2011-07-07 08:21:25 +0000590}
591
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000592RTCPReportBlockInformation* RTCPReceiver::GetReportBlockInformation(
593 uint32_t remote_ssrc,
594 uint32_t source_ssrc) const {
595 ReportBlockMap::const_iterator it = _receivedReportBlockMap.find(source_ssrc);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 if (it == _receivedReportBlockMap.end()) {
597 return NULL;
598 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000599 const ReportBlockInfoMap* info_map = &(it->second);
600 ReportBlockInfoMap::const_iterator it_info = info_map->find(remote_ssrc);
601 if (it_info == info_map->end()) {
602 return NULL;
603 }
604 return it_info->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000605}
606
danilchapda161d72016-08-19 07:29:46 -0700607RTCPCnameInformation* RTCPReceiver::CreateCnameInformation(
608 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700609 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000610
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000611 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612 _receivedCnameMap.find(remoteSSRC);
613
614 if (it != _receivedCnameMap.end()) {
615 return it->second;
616 }
617 RTCPCnameInformation* cnameInfo = new RTCPCnameInformation;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000618 memset(cnameInfo->name, 0, RTCP_CNAME_SIZE);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 _receivedCnameMap[remoteSSRC] = cnameInfo;
620 return cnameInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000621}
622
danilchapda161d72016-08-19 07:29:46 -0700623RTCPCnameInformation* RTCPReceiver::GetCnameInformation(
624 uint32_t remoteSSRC) const {
danilchap7c9426c2016-04-14 03:05:31 -0700625 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000626
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000627 std::map<uint32_t, RTCPCnameInformation*>::const_iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000628 _receivedCnameMap.find(remoteSSRC);
629
630 if (it == _receivedCnameMap.end()) {
631 return NULL;
632 }
633 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634}
635
danilchapda161d72016-08-19 07:29:46 -0700636RTCPReceiveInformation* RTCPReceiver::CreateReceiveInformation(
637 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700638 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000640 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641 _receivedInfoMap.find(remoteSSRC);
642
643 if (it != _receivedInfoMap.end()) {
644 return it->second;
645 }
646 RTCPReceiveInformation* receiveInfo = new RTCPReceiveInformation;
647 _receivedInfoMap[remoteSSRC] = receiveInfo;
648 return receiveInfo;
niklase@google.com470e71d2011-07-07 08:21:25 +0000649}
650
danilchapda161d72016-08-19 07:29:46 -0700651RTCPReceiveInformation* RTCPReceiver::GetReceiveInformation(
652 uint32_t remoteSSRC) {
danilchap7c9426c2016-04-14 03:05:31 -0700653 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000654
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000655 std::map<uint32_t, RTCPReceiveInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000656 _receivedInfoMap.find(remoteSSRC);
657 if (it == _receivedInfoMap.end()) {
658 return NULL;
659 }
660 return it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000661}
662
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000663bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700664 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000665 if (_lastReceivedRrMs == 0)
666 return false;
667
668 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000669 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000670 // Reset the timer to only trigger one log.
671 _lastReceivedRrMs = 0;
672 return true;
673 }
674 return false;
675}
676
677bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700678 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000679 if (_lastIncreasedSequenceNumberMs == 0)
680 return false;
681
682 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
danilchapda161d72016-08-19 07:29:46 -0700683 if (_clock->TimeInMilliseconds() >
684 _lastIncreasedSequenceNumberMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000685 // Reset the timer to only trigger one log.
686 _lastIncreasedSequenceNumberMs = 0;
687 return true;
688 }
689 return false;
690}
691
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000692bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
danilchap7c9426c2016-04-14 03:05:31 -0700693 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000694
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000695 bool updateBoundingSet = false;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000696 int64_t timeNow = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000697
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000698 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 _receivedInfoMap.begin();
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000701 while (receiveInfoIt != _receivedInfoMap.end()) {
702 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
703 if (receiveInfo == NULL) {
704 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000705 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000706 // time since last received rtcp packet
707 // when we dont have a lastTimeReceived and the object is marked
708 // readyForDelete it's removed from the map
danilchap2b616392016-08-18 06:17:42 -0700709 if (receiveInfo->last_time_received_ms > 0) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000710 /// use audio define since we don't know what interval the remote peer is
711 // using
danilchap2b616392016-08-18 06:17:42 -0700712 if ((timeNow - receiveInfo->last_time_received_ms) >
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000713 5 * RTCP_INTERVAL_AUDIO_MS) {
714 // no rtcp packet for the last five regular intervals, reset limitations
danilchap2b616392016-08-18 06:17:42 -0700715 receiveInfo->ClearTmmbr();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000716 // prevent that we call this over and over again
danilchap2b616392016-08-18 06:17:42 -0700717 receiveInfo->last_time_received_ms = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000718 // send new TMMBN to all channels using the default codec
719 updateBoundingSet = true;
720 }
721 receiveInfoIt++;
danilchap2b616392016-08-18 06:17:42 -0700722 } else if (receiveInfo->ready_for_delete) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000723 // store our current receiveInfoItem
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000724 std::map<uint32_t, RTCPReceiveInformation*>::iterator
danilchapda161d72016-08-19 07:29:46 -0700725 receiveInfoItemToBeErased = receiveInfoIt;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000726 receiveInfoIt++;
727 delete receiveInfoItemToBeErased->second;
728 _receivedInfoMap.erase(receiveInfoItemToBeErased);
729 } else {
730 receiveInfoIt++;
731 }
732 }
733 return updateBoundingSet;
niklase@google.com470e71d2011-07-07 08:21:25 +0000734}
735
danilchap2b616392016-08-18 06:17:42 -0700736std::vector<rtcp::TmmbItem> RTCPReceiver::BoundingSet(bool* tmmbr_owner) {
danilchap7c9426c2016-04-14 03:05:31 -0700737 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000738
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000740 _receivedInfoMap.find(_remoteSSRC);
741
742 if (receiveInfoIt == _receivedInfoMap.end()) {
danilchap2b616392016-08-18 06:17:42 -0700743 return std::vector<rtcp::TmmbItem>();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000744 }
745 RTCPReceiveInformation* receiveInfo = receiveInfoIt->second;
danilchap2b616392016-08-18 06:17:42 -0700746 RTC_DCHECK(receiveInfo);
747
748 *tmmbr_owner = TMMBRHelp::IsOwner(receiveInfo->tmmbn, main_ssrc_);
749 return receiveInfo->tmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000750}
751
danilchap1b1863a2016-09-20 01:39:54 -0700752void RTCPReceiver::HandleSDES(const CommonHeader& rtcp_block,
Erik Språnga38233a2015-07-24 09:58:18 +0200753 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700754 rtcp::Sdes sdes;
755 if (!sdes.Parse(rtcp_block)) {
756 ++num_skipped_packets_;
757 return;
758 }
759
760 for (const rtcp::Sdes::Chunk& chunk : sdes.chunks()) {
761 RTCPCnameInformation* cnameInfo = CreateCnameInformation(chunk.ssrc);
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200762 RTC_DCHECK(cnameInfo);
763
764 cnameInfo->name[RTCP_CNAME_SIZE - 1] = 0;
danilchap1b1863a2016-09-20 01:39:54 -0700765 strncpy(cnameInfo->name, chunk.cname.c_str(), RTCP_CNAME_SIZE - 1);
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200766 {
767 rtc::CritScope lock(&_criticalSectionFeedbacks);
danilchap1b1863a2016-09-20 01:39:54 -0700768 if (stats_callback_)
769 stats_callback_->CNameChanged(chunk.cname.c_str(), chunk.ssrc);
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200770 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000771 }
Erik Språnga38233a2015-07-24 09:58:18 +0200772 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000773}
774
danilchap1b1863a2016-09-20 01:39:54 -0700775void RTCPReceiver::HandleNACK(const CommonHeader& rtcp_block,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000776 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700777 rtcp::Nack nack;
778 if (!nack.Parse(rtcp_block)) {
779 ++num_skipped_packets_;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000780 return;
781 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000782
danilchap1b1863a2016-09-20 01:39:54 -0700783 if (receiver_only_ || main_ssrc_ != nack.media_ssrc()) // Not to us.
784 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200785
danilchap1b1863a2016-09-20 01:39:54 -0700786 rtcpPacketInformation.nackSequenceNumbers = nack.packet_ids();
787 for (uint16_t packet_id : nack.packet_ids())
788 nack_stats_.ReportRequest(packet_id);
789
790 if (!nack.packet_ids().empty()) {
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200791 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpNack;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000792 ++packet_type_counter_.nack_packets;
793 packet_type_counter_.nack_requests = nack_stats_.requests();
794 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
795 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000796}
797
danilchap1b1863a2016-09-20 01:39:54 -0700798void RTCPReceiver::HandleBYE(const CommonHeader& rtcp_block) {
799 rtcp::Bye bye;
800 if (!bye.Parse(rtcp_block)) {
801 ++num_skipped_packets_;
802 return;
803 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000804
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000805 // clear our lists
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000806 ReportBlockMap::iterator it = _receivedReportBlockMap.begin();
807 for (; it != _receivedReportBlockMap.end(); ++it) {
808 ReportBlockInfoMap* info_map = &(it->second);
danilchap1b1863a2016-09-20 01:39:54 -0700809 ReportBlockInfoMap::iterator it_info = info_map->find(bye.sender_ssrc());
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000810 if (it_info != info_map->end()) {
811 delete it_info->second;
812 info_map->erase(it_info);
813 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000814 }
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000815
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000816 // we can't delete it due to TMMBR
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000817 std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt =
danilchap1b1863a2016-09-20 01:39:54 -0700818 _receivedInfoMap.find(bye.sender_ssrc());
niklase@google.com470e71d2011-07-07 08:21:25 +0000819
danilchap1b1863a2016-09-20 01:39:54 -0700820 if (receiveInfoIt != _receivedInfoMap.end())
danilchap2b616392016-08-18 06:17:42 -0700821 receiveInfoIt->second->ready_for_delete = true;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000822
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000823 std::map<uint32_t, RTCPCnameInformation*>::iterator cnameInfoIt =
danilchap1b1863a2016-09-20 01:39:54 -0700824 _receivedCnameMap.find(bye.sender_ssrc());
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000825
826 if (cnameInfoIt != _receivedCnameMap.end()) {
827 delete cnameInfoIt->second;
828 _receivedCnameMap.erase(cnameInfoIt);
829 }
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000830 xr_rr_rtt_ms_ = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831}
832
danilchap1b1863a2016-09-20 01:39:54 -0700833void RTCPReceiver::HandleXr(const CommonHeader& rtcp_block,
834 RTCPPacketInformation& rtcpPacketInformation) {
835 rtcp::ExtendedReports xr;
836 if (!xr.Parse(rtcp_block)) {
837 ++num_skipped_packets_;
838 return;
839 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000840
danilchap1b1863a2016-09-20 01:39:54 -0700841 rtcpPacketInformation.xr_originator_ssrc = xr.sender_ssrc();
842 for (const rtcp::Rrtr& rrtr : xr.rrtrs())
843 HandleXrReceiveReferenceTime(rrtr, rtcpPacketInformation);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000844
danilchap1b1863a2016-09-20 01:39:54 -0700845 for (const rtcp::Dlrr& dlrr : xr.dlrrs()) {
846 for (const rtcp::ReceiveTimeInfo& time_info : dlrr.sub_blocks())
847 HandleXrDlrrReportBlock(time_info, rtcpPacketInformation);
848 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000849}
850
851void RTCPReceiver::HandleXrReceiveReferenceTime(
danilchap1b1863a2016-09-20 01:39:54 -0700852 const rtcp::Rrtr& rrtr,
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000853 RTCPPacketInformation& rtcpPacketInformation) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000854 _remoteXRReceiveTimeInfo.sourceSSRC =
855 rtcpPacketInformation.xr_originator_ssrc;
856
danilchap1b1863a2016-09-20 01:39:54 -0700857 _remoteXRReceiveTimeInfo.lastRR = CompactNtp(rrtr.ntp());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000858
859 _clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);
860
861 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000862}
863
864void RTCPReceiver::HandleXrDlrrReportBlock(
danilchap1b1863a2016-09-20 01:39:54 -0700865 const rtcp::ReceiveTimeInfo& rti,
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000866 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700867 if (registered_ssrcs_.count(rti.ssrc) == 0) // Not to us.
868 return;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000869
danilchap1b1863a2016-09-20 01:39:54 -0700870 rtcpPacketInformation.xr_dlrr_item = true;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200871
danilchap1b1863a2016-09-20 01:39:54 -0700872 // Caller should explicitly enable rtt calculation using extended reports.
873 if (!xr_rrtr_status_)
874 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200875
danilchap1b1863a2016-09-20 01:39:54 -0700876 // The send_time and delay_rr fields are in units of 1/2^16 sec.
877 uint32_t send_time = rti.last_rr;
878 // RFC3611, section 4.5, LRR field discription states:
879 // If no such block has been received, the field is set to zero.
880 if (send_time == 0)
881 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200882
danilchap1b1863a2016-09-20 01:39:54 -0700883 uint32_t delay_rr = rti.delay_since_last_rr;
884 uint32_t now = CompactNtp(NtpTime(*_clock));
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200885
danilchap1b1863a2016-09-20 01:39:54 -0700886 uint32_t rtt_ntp = now - delay_rr - send_time;
887 xr_rr_rtt_ms_ = CompactNtpRttToMs(rtt_ntp);
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200888
danilchap1b1863a2016-09-20 01:39:54 -0700889 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000890}
891
danilchap1b1863a2016-09-20 01:39:54 -0700892void RTCPReceiver::HandlePLI(const CommonHeader& rtcp_block,
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000893 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700894 rtcp::Pli pli;
895 if (!pli.Parse(rtcp_block)) {
896 ++num_skipped_packets_;
897 return;
898 }
899
900 if (main_ssrc_ == pli.media_ssrc()) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000901 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000902
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000903 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000904 // Received a signal that we need to send a new key frame.
905 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpPli;
906 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000907}
908
danilchap1b1863a2016-09-20 01:39:54 -0700909void RTCPReceiver::HandleTMMBR(const CommonHeader& rtcp_block,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000910 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700911 rtcp::Tmmbr tmmbr;
912 if (!tmmbr.Parse(rtcp_block)) {
913 ++num_skipped_packets_;
914 return;
915 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
danilchap1b1863a2016-09-20 01:39:54 -0700917 uint32_t senderSSRC = tmmbr.sender_ssrc();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000918 RTCPReceiveInformation* ptrReceiveInfo = GetReceiveInformation(senderSSRC);
danilchap1b1863a2016-09-20 01:39:54 -0700919 if (!ptrReceiveInfo) // This remote SSRC must be saved before.
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000920 return;
danilchap1b1863a2016-09-20 01:39:54 -0700921
922 if (tmmbr.media_ssrc()) {
923 // media_ssrc() SHOULD be 0 if same as SenderSSRC.
924 // In relay mode this is a valid number.
925 senderSSRC = tmmbr.media_ssrc();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000926 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000927
danilchap1b1863a2016-09-20 01:39:54 -0700928 for (const rtcp::TmmbItem& request : tmmbr.requests()) {
929 if (main_ssrc_ == request.ssrc() && request.bitrate_bps()) {
930 ptrReceiveInfo->InsertTmmbrItem(senderSSRC, request,
931 _clock->TimeInMilliseconds());
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200932 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbr;
933 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000934 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000935}
936
danilchap1b1863a2016-09-20 01:39:54 -0700937void RTCPReceiver::HandleTMMBN(const CommonHeader& rtcp_block,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000938 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700939 rtcp::Tmmbn tmmbn;
940 if (!tmmbn.Parse(rtcp_block)) {
941 ++num_skipped_packets_;
942 return;
943 }
944
danilchapda161d72016-08-19 07:29:46 -0700945 RTCPReceiveInformation* ptrReceiveInfo =
danilchap1b1863a2016-09-20 01:39:54 -0700946 GetReceiveInformation(tmmbn.sender_ssrc());
947 if (!ptrReceiveInfo) // This remote SSRC must be saved before.
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000948 return;
danilchap1b1863a2016-09-20 01:39:54 -0700949
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000950 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpTmmbn;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000951
danilchap1b1863a2016-09-20 01:39:54 -0700952 for (const auto& item : tmmbn.items())
953 ptrReceiveInfo->tmmbn.push_back(item);
954}
955
956void RTCPReceiver::HandleSR_REQ(const CommonHeader& rtcp_block,
957 RTCPPacketInformation& rtcpPacketInformation) {
958 rtcp::RapidResyncRequest sr_req;
959 if (!sr_req.Parse(rtcp_block)) {
960 ++num_skipped_packets_;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000961 return;
962 }
963
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000964 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965}
966
danilchap1b1863a2016-09-20 01:39:54 -0700967void RTCPReceiver::HandleSLI(const CommonHeader& rtcp_block,
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000968 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700969 rtcp::Sli sli;
970 if (!sli.Parse(rtcp_block)) {
971 ++num_skipped_packets_;
972 return;
973 }
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200974
danilchap1b1863a2016-09-20 01:39:54 -0700975 for (const rtcp::Sli::Macroblocks& item : sli.macroblocks()) {
976 // In theory there could be multiple slices lost.
977 // Received signal that we need to refresh a slice.
978 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpSli;
979 rtcpPacketInformation.sliPictureId = item.picture_id();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000980 }
981}
982
danilchapda161d72016-08-19 07:29:46 -0700983void RTCPReceiver::HandleRPSI(
danilchap1b1863a2016-09-20 01:39:54 -0700984 const CommonHeader& rtcp_block,
danilchapda161d72016-08-19 07:29:46 -0700985 RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700986 rtcp::Rpsi rpsi;
987 if (!rpsi.Parse(rtcp_block)) {
988 ++num_skipped_packets_;
989 return;
danilchapda161d72016-08-19 07:29:46 -0700990 }
danilchap1b1863a2016-09-20 01:39:54 -0700991
992 // Received signal that we have a confirmed reference picture.
993 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRpsi;
994 rtcpPacketInformation.rpsiPictureId = rpsi.picture_id();
niklase@google.com470e71d2011-07-07 08:21:25 +0000995}
996
danilchap1b1863a2016-09-20 01:39:54 -0700997void RTCPReceiver::HandlePsfbApp(const CommonHeader& rtcp_block,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000998 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -0700999 rtcp::Remb remb;
1000 if (remb.Parse(rtcp_block)) {
1001 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb;
1002 rtcpPacketInformation.receiverEstimatedMaxBitrate = remb.bitrate_bps();
1003 return;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001004 }
danilchap1b1863a2016-09-20 01:39:54 -07001005
1006 ++num_skipped_packets_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001007}
1008
danilchap1b1863a2016-09-20 01:39:54 -07001009void RTCPReceiver::HandleFIR(const CommonHeader& rtcp_block,
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001010 RTCPPacketInformation& rtcpPacketInformation) {
danilchap1b1863a2016-09-20 01:39:54 -07001011 rtcp::Fir fir;
1012 if (!fir.Parse(rtcp_block)) {
1013 ++num_skipped_packets_;
1014 return;
1015 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001016
danilchap1b1863a2016-09-20 01:39:54 -07001017 RTCPReceiveInformation* ptrReceiveInfo =
1018 GetReceiveInformation(fir.sender_ssrc());
1019
1020 for (const rtcp::Fir::Request& fir_request : fir.requests()) {
Danil Chapovalov530b3f52016-09-15 18:41:02 +02001021 // Is it our sender that is requested to generate a new keyframe
danilchap1b1863a2016-09-20 01:39:54 -07001022 if (main_ssrc_ != fir_request.ssrc)
1023 continue;
Danil Chapovalov530b3f52016-09-15 18:41:02 +02001024
1025 ++packet_type_counter_.fir_packets;
1026
1027 // rtcpPacket.FIR.MediaSSRC SHOULD be 0 but we ignore to check it
1028 // we don't know who this originate from
1029 if (ptrReceiveInfo) {
1030 // check if we have reported this FIRSequenceNumber before
danilchap1b1863a2016-09-20 01:39:54 -07001031 if (fir_request.seq_nr != ptrReceiveInfo->last_fir_sequence_number) {
Danil Chapovalov530b3f52016-09-15 18:41:02 +02001032 int64_t now = _clock->TimeInMilliseconds();
1033 // sanity; don't go crazy with the callbacks
1034 if ((now - ptrReceiveInfo->last_fir_request_ms) >
1035 RTCP_MIN_FRAME_LENGTH_MS) {
1036 ptrReceiveInfo->last_fir_request_ms = now;
danilchap1b1863a2016-09-20 01:39:54 -07001037 ptrReceiveInfo->last_fir_sequence_number = fir_request.seq_nr;
Danil Chapovalov530b3f52016-09-15 18:41:02 +02001038 // received signal that we need to send a new key frame
1039 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1040 }
1041 }
1042 } else {
1043 // received signal that we need to send a new key frame
1044 rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpFir;
1045 }
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +00001046 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001047}
1048
Erik Språng6b8d3552015-09-24 15:06:57 +02001049void RTCPReceiver::HandleTransportFeedback(
danilchap1b1863a2016-09-20 01:39:54 -07001050 const CommonHeader& rtcp_block,
Erik Språng6b8d3552015-09-24 15:06:57 +02001051 RTCPHelp::RTCPPacketInformation* rtcp_packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -07001052 std::unique_ptr<rtcp::TransportFeedback> transport_feedback(
1053 new rtcp::TransportFeedback());
1054 if (!transport_feedback->Parse(rtcp_block)) {
1055 ++num_skipped_packets_;
1056 return;
1057 }
Erik Språng6b8d3552015-09-24 15:06:57 +02001058
danilchap1b1863a2016-09-20 01:39:54 -07001059 rtcp_packet_information->rtcpPacketTypeFlags |= kRtcpTransportFeedback;
1060 rtcp_packet_information->transport_feedback_ = std::move(transport_feedback);
Erik Språng6b8d3552015-09-24 15:06:57 +02001061}
danilchap287e5482016-08-16 15:15:39 -07001062
danilchap853ecb22016-08-22 08:26:15 -07001063void RTCPReceiver::UpdateTmmbr() {
1064 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -07001065 std::vector<rtcp::TmmbItem> bounding =
danilchap853ecb22016-08-22 08:26:15 -07001066 TMMBRHelp::FindBoundingSet(TmmbrReceived());
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001067
danilchap853ecb22016-08-22 08:26:15 -07001068 if (!bounding.empty() && _cbRtcpBandwidthObserver) {
1069 // We have a new bandwidth estimate on this channel.
danilchap2f69ce92016-08-16 03:21:38 -07001070 uint64_t bitrate_bps = TMMBRHelp::CalcMinBitrateBps(bounding);
1071 if (bitrate_bps <= std::numeric_limits<uint32_t>::max())
1072 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate_bps);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +00001073 }
danilchap853ecb22016-08-22 08:26:15 -07001074
1075 // Set bounding set: inform remote clients about the new bandwidth.
1076 _rtpRtcp.SetTmmbn(std::move(bounding));
niklase@google.com470e71d2011-07-07 08:21:25 +00001077}
1078
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001079void RTCPReceiver::RegisterRtcpStatisticsCallback(
1080 RtcpStatisticsCallback* callback) {
danilchap7c9426c2016-04-14 03:05:31 -07001081 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001082 stats_callback_ = callback;
1083}
1084
1085RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
danilchap7c9426c2016-04-14 03:05:31 -07001086 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001087 return stats_callback_;
1088}
1089
niklase@google.com470e71d2011-07-07 08:21:25 +00001090// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001091void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001092 RTCPPacketInformation& rtcpPacketInformation) {
1093 // Process TMMBR and REMB first to avoid multiple callbacks
1094 // to OnNetworkChanged.
1095 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001096 // Might trigger a OnReceivedBandwidthEstimateUpdate.
danilchap853ecb22016-08-22 08:26:15 -07001097 UpdateTmmbr();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001098 }
sprang7dc39f32015-10-13 09:17:48 -07001099 uint32_t local_ssrc;
1100 std::set<uint32_t> registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001101 {
1102 // We don't want to hold this critsect when triggering the callbacks below.
danilchap7c9426c2016-04-14 03:05:31 -07001103 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +00001104 local_ssrc = main_ssrc_;
sprang7dc39f32015-10-13 09:17:48 -07001105 registered_ssrcs = registered_ssrcs_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001106 }
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001107 if (!receiver_only_ &&
Erik Språng6b8d3552015-09-24 15:06:57 +02001108 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSrReq)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001109 _rtpRtcp.OnRequestSendReport();
1110 }
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001111 if (!receiver_only_ &&
Erik Språng6b8d3552015-09-24 15:06:57 +02001112 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpNack)) {
stefan@webrtc.orgbecf9c82013-02-01 15:09:57 +00001113 if (rtcpPacketInformation.nackSequenceNumbers.size() > 0) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001114 LOG(LS_VERBOSE) << "Incoming NACK length: "
danilchapda161d72016-08-19 07:29:46 -07001115 << rtcpPacketInformation.nackSequenceNumbers.size();
Danil Chapovalov2800d742016-08-26 18:48:46 +02001116 _rtpRtcp.OnReceivedNack(rtcpPacketInformation.nackSequenceNumbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +00001117 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001118 }
1119 {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001120 // We need feedback that we have received a report block(s) so that we
1121 // can generate a new packet in a conference relay scenario, one received
1122 // report can generate several RTCP packets, based on number relayed/mixed
1123 // a send report block should go out to all receivers.
1124 if (_cbRtcpIntraFrameObserver) {
henrikg91d6ede2015-09-17 00:24:34 -07001125 RTC_DCHECK(!receiver_only_);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001126 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) ||
1127 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpFir)) {
1128 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001129 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001130 << rtcpPacketInformation.remoteSSRC;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001131 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001132 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001133 << rtcpPacketInformation.remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +00001134 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001135 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001136 }
1137 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) {
1138 _cbRtcpIntraFrameObserver->OnReceivedSLI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001139 local_ssrc, rtcpPacketInformation.sliPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001140 }
1141 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) {
1142 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +00001143 local_ssrc, rtcpPacketInformation.rpsiPictureId);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001144 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001145 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001146 if (_cbRtcpBandwidthObserver) {
henrikg91d6ede2015-09-17 00:24:34 -07001147 RTC_DCHECK(!receiver_only_);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001148 if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +00001149 LOG(LS_VERBOSE) << "Incoming REMB: "
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +00001150 << rtcpPacketInformation.receiverEstimatedMaxBitrate;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001151 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
1152 rtcpPacketInformation.receiverEstimatedMaxBitrate);
1153 }
Erik Språng242e22b2015-05-11 10:17:43 +02001154 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) ||
1155 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr)) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001156 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001157 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
danilchapda161d72016-08-19 07:29:46 -07001158 rtcpPacketInformation.report_blocks, rtcpPacketInformation.rtt,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001159 now);
1160 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001161 }
isheriff6b4b5f32016-06-08 00:24:21 -07001162 if ((rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) ||
1163 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRr)) {
1164 _rtpRtcp.OnReceivedRtcpReportBlocks(rtcpPacketInformation.report_blocks);
1165 }
1166
Erik Språng6b8d3552015-09-24 15:06:57 +02001167 if (_cbTransportFeedbackObserver &&
1168 (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpTransportFeedback)) {
1169 uint32_t media_source_ssrc =
1170 rtcpPacketInformation.transport_feedback_->GetMediaSourceSsrc();
sprang7dc39f32015-10-13 09:17:48 -07001171 if (media_source_ssrc == local_ssrc ||
1172 registered_ssrcs.find(media_source_ssrc) != registered_ssrcs.end()) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001173 _cbTransportFeedbackObserver->OnTransportFeedback(
1174 *rtcpPacketInformation.transport_feedback_.get());
1175 }
1176 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001177 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001178
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001179 if (!receiver_only_) {
danilchap7c9426c2016-04-14 03:05:31 -07001180 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001181 if (stats_callback_) {
1182 for (ReportBlockList::const_iterator it =
danilchapda161d72016-08-19 07:29:46 -07001183 rtcpPacketInformation.report_blocks.begin();
1184 it != rtcpPacketInformation.report_blocks.end(); ++it) {
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001185 RtcpStatistics stats;
1186 stats.cumulative_lost = it->cumulativeLost;
1187 stats.extended_max_sequence_number = it->extendedHighSeqNum;
1188 stats.fraction_lost = it->fractionLost;
1189 stats.jitter = it->jitter;
1190
stefan@webrtc.org58e2d262014-08-14 15:10:49 +00001191 stats_callback_->StatisticsUpdated(stats, it->sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001192 }
1193 }
1194 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001195}
1196
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001197int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001198 char cName[RTCP_CNAME_SIZE]) const {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001199 assert(cName);
1200
danilchap7c9426c2016-04-14 03:05:31 -07001201 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001202 RTCPCnameInformation* cnameInfo = GetCnameInformation(remoteSSRC);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001203 if (cnameInfo == NULL) {
1204 return -1;
1205 }
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001206 cName[RTCP_CNAME_SIZE - 1] = 0;
1207 strncpy(cName, cnameInfo->name, RTCP_CNAME_SIZE - 1);
1208 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001209}
1210
danilchap853ecb22016-08-22 08:26:15 -07001211std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() const {
danilchap7c9426c2016-04-14 03:05:31 -07001212 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap287e5482016-08-16 15:15:39 -07001213 std::vector<rtcp::TmmbItem> candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
danilchap287e5482016-08-16 15:15:39 -07001215 int64_t now_ms = _clock->TimeInMilliseconds();
1216
1217 for (const auto& kv : _receivedInfoMap) {
1218 RTCPReceiveInformation* receive_info = kv.second;
1219 RTC_DCHECK(receive_info);
danilchap2b616392016-08-18 06:17:42 -07001220 receive_info->GetTmmbrSet(now_ms, &candidates);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001221 }
danilchap287e5482016-08-16 15:15:39 -07001222 return candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001223}
1224
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001225} // namespace webrtc