blob: 5c80e236db64dc417b03fbe77b301d890ad9cc0b [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>
danilchap7851bda2016-09-29 15:28:07 -070017#include <map>
danilchap92ea6012016-09-23 10:36:03 -070018#include <memory>
19#include <utility>
danilchap7851bda2016-09-29 15:28:07 -070020#include <vector>
danilchap2f69ce92016-08-16 03:21:38 -070021
Peter Boströmfe7a80c2015-04-23 17:53:17 +020022#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010023#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070024#include "webrtc/base/trace_event.h"
danilchap1b1863a2016-09-20 01:39:54 -070025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
26#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/common_header.h"
27#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
28#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
29#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
30#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
31#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
32#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
33#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
34#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
35#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
36#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
37#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
38#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
39#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
40#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
Erik Språng6b8d3552015-09-24 15:06:57 +020041#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010042#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070043#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
Danil Chapovalova094fd12016-02-22 18:59:36 +010044#include "webrtc/system_wrappers/include/ntp_time.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000045
niklase@google.com470e71d2011-07-07 08:21:25 +000046namespace webrtc {
danilchap1b1863a2016-09-20 01:39:54 -070047namespace {
48
49using rtcp::CommonHeader;
50using rtcp::ReportBlock;
niklase@google.com470e71d2011-07-07 08:21:25 +000051
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +000052// The number of RTCP time intervals needed to trigger a timeout.
53const int kRrTimeoutIntervals = 3;
54
Erik Språng6b8d3552015-09-24 15:06:57 +020055const int64_t kMaxWarningLogIntervalMs = 10000;
56
danilchap1b1863a2016-09-20 01:39:54 -070057} // namespace
58
danilchap92ea6012016-09-23 10:36:03 -070059struct RTCPReceiver::PacketInformation {
60 uint32_t packet_type_flags = 0; // RTCPPacketTypeFlags bit field.
61
62 uint32_t remote_ssrc = 0;
63 std::vector<uint16_t> nack_sequence_numbers;
64 ReportBlockList report_blocks;
65 int64_t rtt_ms = 0;
66 uint8_t sli_picture_id = 0;
67 uint64_t rpsi_picture_id = 0;
68 uint32_t receiver_estimated_max_bitrate_bps = 0;
69 std::unique_ptr<rtcp::TransportFeedback> transport_feedback;
70};
71
danilchap7851bda2016-09-29 15:28:07 -070072struct RTCPReceiver::ReceiveInformation {
73 struct TimedTmmbrItem {
74 rtcp::TmmbItem tmmbr_item;
75 int64_t last_updated_ms;
76 };
77
78 int64_t last_time_received_ms = 0;
79
80 int64_t last_fir_request_ms = 0;
81 int32_t last_fir_sequence_number = -1;
82
83 bool ready_for_delete = false;
84
85 std::vector<rtcp::TmmbItem> tmmbn;
86 std::map<uint32_t, TimedTmmbrItem> tmmbr;
87};
88
danilchap28b03eb2016-10-05 06:59:44 -070089struct RTCPReceiver::ReportBlockWithRtt {
90 RTCPReportBlock report_block;
91
92 int64_t last_rtt_ms = 0;
93 int64_t min_rtt_ms = 0;
94 int64_t max_rtt_ms = 0;
95 int64_t sum_rtt_ms = 0;
96 size_t num_rtts = 0;
97};
98
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000099RTCPReceiver::RTCPReceiver(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000100 Clock* clock,
Peter Boströmfe7a80c2015-04-23 17:53:17 +0200101 bool receiver_only,
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000102 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
mflodman@webrtc.org96abda02015-02-25 13:50:10 +0000103 RtcpBandwidthObserver* rtcp_bandwidth_observer,
104 RtcpIntraFrameObserver* rtcp_intra_frame_observer,
Erik Språng6b8d3552015-09-24 15:06:57 +0200105 TransportFeedbackObserver* transport_feedback_observer,
danilchap59cb2bd2016-08-29 11:08:47 -0700106 ModuleRtpRtcp* owner)
danilchap13deaad2016-05-24 13:25:27 -0700107 : _clock(clock),
Peter Boströmfe7a80c2015-04-23 17:53:17 +0200108 receiver_only_(receiver_only),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000109 _rtpRtcp(*owner),
mflodman@webrtc.org96abda02015-02-25 13:50:10 +0000110 _cbRtcpBandwidthObserver(rtcp_bandwidth_observer),
111 _cbRtcpIntraFrameObserver(rtcp_intra_frame_observer),
Erik Språng6b8d3552015-09-24 15:06:57 +0200112 _cbTransportFeedbackObserver(transport_feedback_observer),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000113 main_ssrc_(0),
114 _remoteSSRC(0),
115 _remoteSenderInfo(),
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100116 xr_rrtr_status_(false),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000117 xr_rr_rtt_ms_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000118 _lastReceivedRrMs(0),
119 _lastIncreasedSequenceNumberMs(0),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000120 stats_callback_(NULL),
Erik Språng6b8d3552015-09-24 15:06:57 +0200121 packet_type_counter_observer_(packet_type_counter_observer),
122 num_skipped_packets_(0),
123 last_skipped_packets_warning_(clock->TimeInMilliseconds()) {
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000124 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
niklase@google.com470e71d2011-07-07 08:21:25 +0000125}
126
danilchap28b03eb2016-10-05 06:59:44 -0700127RTCPReceiver::~RTCPReceiver() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000128
danilchap59cb2bd2016-08-29 11:08:47 -0700129bool RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) {
danilchap1b1863a2016-09-20 01:39:54 -0700130 if (packet_size == 0) {
131 LOG(LS_WARNING) << "Incoming empty RTCP packet";
danilchap59cb2bd2016-08-29 11:08:47 -0700132 return false;
133 }
danilchap59cb2bd2016-08-29 11:08:47 -0700134
danilchap92ea6012016-09-23 10:36:03 -0700135 PacketInformation packet_information;
danilchap1b1863a2016-09-20 01:39:54 -0700136 if (!ParseCompoundPacket(packet, packet + packet_size, &packet_information))
137 return false;
138 TriggerCallbacksFromRTCPPacket(packet_information);
139 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140}
141
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000142int64_t RTCPReceiver::LastReceivedReceiverReport() const {
danilchap7c9426c2016-04-14 03:05:31 -0700143 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000144 int64_t last_received_rr = -1;
danilchap7851bda2016-09-29 15:28:07 -0700145 for (const auto& kv : received_infos_)
146 if (kv.second.last_time_received_ms > last_received_rr)
147 last_received_rr = kv.second.last_time_received_ms;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000148 return last_received_rr;
stefan@webrtc.orgb5865072013-02-01 14:33:42 +0000149}
150
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000151void RTCPReceiver::SetRemoteSSRC(uint32_t ssrc) {
danilchap7c9426c2016-04-14 03:05:31 -0700152 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000154 // new SSRC reset old reports
155 memset(&_remoteSenderInfo, 0, sizeof(_remoteSenderInfo));
danilchap0b4b7272016-10-06 09:24:45 -0700156 last_received_sr_ntp_.Reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000158 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000159}
160
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000161uint32_t RTCPReceiver::RemoteSSRC() const {
danilchap7c9426c2016-04-14 03:05:31 -0700162 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000163 return _remoteSSRC;
164}
165
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000166void RTCPReceiver::SetSsrcs(uint32_t main_ssrc,
167 const std::set<uint32_t>& registered_ssrcs) {
mflodman15d83572016-10-06 08:35:11 -0700168 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
169 main_ssrc_ = main_ssrc;
170 registered_ssrcs_ = registered_ssrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171}
172
danilchap28b03eb2016-10-05 06:59:44 -0700173int32_t RTCPReceiver::RTT(uint32_t remote_ssrc,
174 int64_t* last_rtt_ms,
175 int64_t* avg_rtt_ms,
176 int64_t* min_rtt_ms,
177 int64_t* max_rtt_ms) const {
danilchap7c9426c2016-04-14 03:05:31 -0700178 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000179
danilchap28b03eb2016-10-05 06:59:44 -0700180 auto it = received_report_blocks_.find(main_ssrc_);
181 if (it == received_report_blocks_.end())
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000182 return -1;
danilchap28b03eb2016-10-05 06:59:44 -0700183
184 auto it_info = it->second.find(remote_ssrc);
185 if (it_info == it->second.end())
186 return -1;
187
188 const ReportBlockWithRtt* report_block = &it_info->second;
189
190 if (report_block->num_rtts == 0)
191 return -1;
192
193 if (last_rtt_ms)
194 *last_rtt_ms = report_block->last_rtt_ms;
195
196 if (avg_rtt_ms)
197 *avg_rtt_ms = report_block->sum_rtt_ms / report_block->num_rtts;
198
199 if (min_rtt_ms)
200 *min_rtt_ms = report_block->min_rtt_ms;
201
202 if (max_rtt_ms)
203 *max_rtt_ms = report_block->max_rtt_ms;
204
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000205 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000206}
207
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100208void RTCPReceiver::SetRtcpXrRrtrStatus(bool enable) {
danilchap7c9426c2016-04-14 03:05:31 -0700209 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100210 xr_rrtr_status_ = enable;
211}
212
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000213bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000214 assert(rtt_ms);
danilchap7c9426c2016-04-14 03:05:31 -0700215 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000216 if (xr_rr_rtt_ms_ == 0) {
217 return false;
218 }
219 *rtt_ms = xr_rr_rtt_ms_;
220 xr_rr_rtt_ms_ = 0;
221 return true;
222}
223
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000224bool RTCPReceiver::NTP(uint32_t* ReceivedNTPsecs,
225 uint32_t* ReceivedNTPfrac,
226 uint32_t* RTCPArrivalTimeSecs,
227 uint32_t* RTCPArrivalTimeFrac,
danilchapda161d72016-08-19 07:29:46 -0700228 uint32_t* rtcp_timestamp) const {
229 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap0b4b7272016-10-06 09:24:45 -0700230 if (!last_received_sr_ntp_.Valid())
231 return false;
232
233 // NTP from incoming SenderReport.
234 if (ReceivedNTPsecs)
235 *ReceivedNTPsecs = _remoteSenderInfo.NTPseconds;
236 if (ReceivedNTPfrac)
danilchapda161d72016-08-19 07:29:46 -0700237 *ReceivedNTPfrac = _remoteSenderInfo.NTPfraction;
danilchap0b4b7272016-10-06 09:24:45 -0700238
239 // Rtp time from incoming SenderReport.
240 if (rtcp_timestamp)
danilchapda161d72016-08-19 07:29:46 -0700241 *rtcp_timestamp = _remoteSenderInfo.RTPtimeStamp;
danilchap0b4b7272016-10-06 09:24:45 -0700242
243 // Local NTP time when we received a RTCP packet with a send block.
244 if (RTCPArrivalTimeSecs)
245 *RTCPArrivalTimeSecs = last_received_sr_ntp_.seconds();
246 if (RTCPArrivalTimeFrac)
247 *RTCPArrivalTimeFrac = last_received_sr_ntp_.fractions();
248
danilchapda161d72016-08-19 07:29:46 -0700249 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250}
251
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000252bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
danilchap798896a2016-09-28 02:54:25 -0700253 rtcp::ReceiveTimeInfo* info) const {
danilchap0b4b7272016-10-06 09:24:45 -0700254 RTC_DCHECK(info);
danilchap7c9426c2016-04-14 03:05:31 -0700255 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap0b4b7272016-10-06 09:24:45 -0700256 if (!last_received_xr_ntp_.Valid())
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000257 return false;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000258
danilchap798896a2016-09-28 02:54:25 -0700259 info->ssrc = remote_time_info_.ssrc;
260 info->last_rr = remote_time_info_.last_rr;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000261
262 // Get the delay since last received report (RFC 3611).
danilchap0b4b7272016-10-06 09:24:45 -0700263 uint32_t receive_time = CompactNtp(last_received_xr_ntp_);
264 uint32_t now = CompactNtp(NtpTime(*_clock));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000265
danilchap798896a2016-09-28 02:54:25 -0700266 info->delay_since_last_rr = now - receive_time;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000267 return true;
268}
269
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000270int32_t RTCPReceiver::SenderInfoReceived(RTCPSenderInfo* senderInfo) const {
271 assert(senderInfo);
danilchap7c9426c2016-04-14 03:05:31 -0700272 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap0b4b7272016-10-06 09:24:45 -0700273 if (!last_received_sr_ntp_.Valid())
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000274 return -1;
danilchap0b4b7272016-10-06 09:24:45 -0700275
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000276 memcpy(senderInfo, &(_remoteSenderInfo), sizeof(RTCPSenderInfo));
277 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
danilchap28b03eb2016-10-05 06:59:44 -0700280// We can get multiple receive reports when we receive the report from a CE.
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000281int32_t RTCPReceiver::StatisticsReceived(
danilchap28b03eb2016-10-05 06:59:44 -0700282 std::vector<RTCPReportBlock>* receive_blocks) const {
283 RTC_DCHECK(receive_blocks);
danilchap7c9426c2016-04-14 03:05:31 -0700284 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap28b03eb2016-10-05 06:59:44 -0700285 for (const auto& reports_per_receiver : received_report_blocks_)
286 for (const auto& report : reports_per_receiver.second)
287 receive_blocks->push_back(report.second.report_block);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000288 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000289}
290
danilchap92ea6012016-09-23 10:36:03 -0700291bool RTCPReceiver::ParseCompoundPacket(const uint8_t* packet_begin,
292 const uint8_t* packet_end,
293 PacketInformation* packet_information) {
danilchapda161d72016-08-19 07:29:46 -0700294 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
danilchap1b1863a2016-09-20 01:39:54 -0700296 CommonHeader rtcp_block;
297 for (const uint8_t* next_block = packet_begin; next_block != packet_end;
298 next_block = rtcp_block.NextPacket()) {
299 ptrdiff_t remaining_blocks_size = packet_end - next_block;
300 RTC_DCHECK_GT(remaining_blocks_size, 0);
301 if (!rtcp_block.Parse(next_block, remaining_blocks_size)) {
302 if (next_block == packet_begin) {
303 // Failed to parse 1st header, nothing was extracted from this packet.
304 LOG(LS_WARNING) << "Incoming invalid RTCP packet";
305 return false;
306 }
307 ++num_skipped_packets_;
308 break;
309 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000310
danilchap1b1863a2016-09-20 01:39:54 -0700311 if (packet_type_counter_.first_packet_time_ms == -1)
312 packet_type_counter_.first_packet_time_ms = _clock->TimeInMilliseconds();
danilchapda161d72016-08-19 07:29:46 -0700313
danilchap1b1863a2016-09-20 01:39:54 -0700314 switch (rtcp_block.type()) {
315 case rtcp::SenderReport::kPacketType:
danilchap92ea6012016-09-23 10:36:03 -0700316 HandleSenderReport(rtcp_block, packet_information);
Danil Chapovalov91511f12016-09-15 16:24:02 +0200317 break;
danilchap1b1863a2016-09-20 01:39:54 -0700318 case rtcp::ReceiverReport::kPacketType:
danilchap92ea6012016-09-23 10:36:03 -0700319 HandleReceiverReport(rtcp_block, packet_information);
danilchapda161d72016-08-19 07:29:46 -0700320 break;
danilchap1b1863a2016-09-20 01:39:54 -0700321 case rtcp::Sdes::kPacketType:
danilchap92ea6012016-09-23 10:36:03 -0700322 HandleSDES(rtcp_block, packet_information);
danilchapda161d72016-08-19 07:29:46 -0700323 break;
danilchap1b1863a2016-09-20 01:39:54 -0700324 case rtcp::ExtendedReports::kPacketType:
danilchap92ea6012016-09-23 10:36:03 -0700325 HandleXr(rtcp_block, packet_information);
danilchapda161d72016-08-19 07:29:46 -0700326 break;
danilchap1b1863a2016-09-20 01:39:54 -0700327 case rtcp::Bye::kPacketType:
328 HandleBYE(rtcp_block);
danilchapda161d72016-08-19 07:29:46 -0700329 break;
danilchap1b1863a2016-09-20 01:39:54 -0700330 case rtcp::Rtpfb::kPacketType:
331 switch (rtcp_block.fmt()) {
332 case rtcp::Nack::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700333 HandleNACK(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700334 break;
335 case rtcp::Tmmbr::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700336 HandleTMMBR(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700337 break;
338 case rtcp::Tmmbn::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700339 HandleTMMBN(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700340 break;
341 case rtcp::RapidResyncRequest::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700342 HandleSR_REQ(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700343 break;
344 case rtcp::TransportFeedback::kFeedbackMessageType:
345 HandleTransportFeedback(rtcp_block, packet_information);
346 break;
347 default:
348 ++num_skipped_packets_;
349 break;
350 }
danilchapda161d72016-08-19 07:29:46 -0700351 break;
danilchap1b1863a2016-09-20 01:39:54 -0700352 case rtcp::Psfb::kPacketType:
353 switch (rtcp_block.fmt()) {
354 case rtcp::Pli::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700355 HandlePLI(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700356 break;
357 case rtcp::Sli::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700358 HandleSLI(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700359 break;
360 case rtcp::Rpsi::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700361 HandleRPSI(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700362 break;
363 case rtcp::Fir::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700364 HandleFIR(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700365 break;
366 case rtcp::Remb::kFeedbackMessageType:
danilchap92ea6012016-09-23 10:36:03 -0700367 HandlePsfbApp(rtcp_block, packet_information);
danilchap1b1863a2016-09-20 01:39:54 -0700368 break;
369 default:
370 ++num_skipped_packets_;
371 break;
372 }
danilchapda161d72016-08-19 07:29:46 -0700373 break;
374 default:
danilchap1b1863a2016-09-20 01:39:54 -0700375 ++num_skipped_packets_;
danilchapda161d72016-08-19 07:29:46 -0700376 break;
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000377 }
danilchapda161d72016-08-19 07:29:46 -0700378 }
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000379
danilchapda161d72016-08-19 07:29:46 -0700380 if (packet_type_counter_observer_ != NULL) {
381 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
382 main_ssrc_, packet_type_counter_);
383 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000384
danilchapda161d72016-08-19 07:29:46 -0700385 int64_t now = _clock->TimeInMilliseconds();
386 if (now - last_skipped_packets_warning_ >= kMaxWarningLogIntervalMs &&
387 num_skipped_packets_ > 0) {
388 last_skipped_packets_warning_ = now;
389 LOG(LS_WARNING) << num_skipped_packets_
390 << " RTCP blocks were skipped due to being malformed or of "
391 "unrecognized/unsupported type, during the past "
392 << (kMaxWarningLogIntervalMs / 1000) << " second period.";
393 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200394
danilchap1b1863a2016-09-20 01:39:54 -0700395 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000396}
397
danilchap92ea6012016-09-23 10:36:03 -0700398void RTCPReceiver::HandleSenderReport(const CommonHeader& rtcp_block,
399 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700400 rtcp::SenderReport sender_report;
401 if (!sender_report.Parse(rtcp_block)) {
402 ++num_skipped_packets_;
403 return;
404 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap1b1863a2016-09-20 01:39:54 -0700406 const uint32_t remoteSSRC = sender_report.sender_ssrc();
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap92ea6012016-09-23 10:36:03 -0700408 packet_information->remote_ssrc = remoteSSRC;
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
danilchap7851bda2016-09-29 15:28:07 -0700410 CreateReceiveInformation(remoteSSRC);
danilchapda161d72016-08-19 07:29:46 -0700411
Danil Chapovalov91511f12016-09-15 16:24:02 +0200412 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "SR",
413 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
danilchapda161d72016-08-19 07:29:46 -0700414
Danil Chapovalov91511f12016-09-15 16:24:02 +0200415 // Have I received RTP packets from this party?
416 if (_remoteSSRC == remoteSSRC) {
417 // Only signal that we have received a SR when we accept one.
danilchap92ea6012016-09-23 10:36:03 -0700418 packet_information->packet_type_flags |= kRtcpSr;
danilchapda161d72016-08-19 07:29:46 -0700419
Danil Chapovalov91511f12016-09-15 16:24:02 +0200420 // Save the NTP time of this report.
danilchap1b1863a2016-09-20 01:39:54 -0700421 _remoteSenderInfo.NTPseconds = sender_report.ntp().seconds();
422 _remoteSenderInfo.NTPfraction = sender_report.ntp().fractions();
423 _remoteSenderInfo.RTPtimeStamp = sender_report.rtp_timestamp();
424 _remoteSenderInfo.sendPacketCount = sender_report.sender_packet_count();
425 _remoteSenderInfo.sendOctetCount = sender_report.sender_octet_count();
danilchapda161d72016-08-19 07:29:46 -0700426
danilchap0b4b7272016-10-06 09:24:45 -0700427 last_received_sr_ntp_.SetCurrent(*_clock);
danilchapda161d72016-08-19 07:29:46 -0700428 } else {
Danil Chapovalov91511f12016-09-15 16:24:02 +0200429 // We will only store the send report from one source, but
430 // we will store all the receive blocks.
danilchap92ea6012016-09-23 10:36:03 -0700431 packet_information->packet_type_flags |= kRtcpRr;
danilchapda161d72016-08-19 07:29:46 -0700432 }
elham@webrtc.orgb7eda432013-07-15 21:08:27 +0000433
danilchap1b1863a2016-09-20 01:39:54 -0700434 for (const rtcp::ReportBlock report_block : sender_report.report_blocks())
danilchap92ea6012016-09-23 10:36:03 -0700435 HandleReportBlock(report_block, packet_information, remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000436}
437
danilchap92ea6012016-09-23 10:36:03 -0700438void RTCPReceiver::HandleReceiverReport(const CommonHeader& rtcp_block,
439 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700440 rtcp::ReceiverReport receiver_report;
441 if (!receiver_report.Parse(rtcp_block)) {
442 ++num_skipped_packets_;
443 return;
444 }
Danil Chapovalov91511f12016-09-15 16:24:02 +0200445
danilchap1b1863a2016-09-20 01:39:54 -0700446 const uint32_t remoteSSRC = receiver_report.sender_ssrc();
Danil Chapovalov91511f12016-09-15 16:24:02 +0200447
danilchap92ea6012016-09-23 10:36:03 -0700448 packet_information->remote_ssrc = remoteSSRC;
Danil Chapovalov91511f12016-09-15 16:24:02 +0200449
danilchap7851bda2016-09-29 15:28:07 -0700450 CreateReceiveInformation(remoteSSRC);
Danil Chapovalov91511f12016-09-15 16:24:02 +0200451
452 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
453 "remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
454
danilchap92ea6012016-09-23 10:36:03 -0700455 packet_information->packet_type_flags |= kRtcpRr;
Danil Chapovalov91511f12016-09-15 16:24:02 +0200456
danilchap1b1863a2016-09-20 01:39:54 -0700457 for (const ReportBlock& report_block : receiver_report.report_blocks())
danilchap92ea6012016-09-23 10:36:03 -0700458 HandleReportBlock(report_block, packet_information, remoteSSRC);
Danil Chapovalov91511f12016-09-15 16:24:02 +0200459}
460
danilchap92ea6012016-09-23 10:36:03 -0700461void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,
462 PacketInformation* packet_information,
danilchap28b03eb2016-10-05 06:59:44 -0700463 uint32_t remote_ssrc) {
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000464 // This will be called once per report block in the RTCP packet.
465 // We filter out all report blocks that are not for us.
466 // Each packet has max 31 RR blocks.
467 //
468 // We can calc RTT if we send a send report and get a report block back.
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
danilchap28b03eb2016-10-05 06:59:44 -0700470 // |report_block.source_ssrc()| is the SSRC identifier of the source to
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000471 // which the information in this reception report block pertains.
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000473 // Filter out all report blocks that are not for us.
danilchap1b1863a2016-09-20 01:39:54 -0700474 if (registered_ssrcs_.count(report_block.source_ssrc()) == 0)
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000475 return;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000476
danilchap28b03eb2016-10-05 06:59:44 -0700477 ReportBlockWithRtt* report_block_info =
478 &received_report_blocks_[report_block.source_ssrc()][remote_ssrc];
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000479
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000480 _lastReceivedRrMs = _clock->TimeInMilliseconds();
danilchap28b03eb2016-10-05 06:59:44 -0700481 report_block_info->report_block.remoteSSRC = remote_ssrc;
482 report_block_info->report_block.sourceSSRC = report_block.source_ssrc();
483 report_block_info->report_block.fractionLost = report_block.fraction_lost();
484 report_block_info->report_block.cumulativeLost =
danilchap1b1863a2016-09-20 01:39:54 -0700485 report_block.cumulative_lost();
486 if (report_block.extended_high_seq_num() >
danilchap28b03eb2016-10-05 06:59:44 -0700487 report_block_info->report_block.extendedHighSeqNum) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000488 // We have successfully delivered new RTP packets to the remote side after
489 // the last RR was sent from the remote side.
490 _lastIncreasedSequenceNumberMs = _lastReceivedRrMs;
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000491 }
danilchap28b03eb2016-10-05 06:59:44 -0700492 report_block_info->report_block.extendedHighSeqNum =
danilchap1b1863a2016-09-20 01:39:54 -0700493 report_block.extended_high_seq_num();
danilchap28b03eb2016-10-05 06:59:44 -0700494 report_block_info->report_block.jitter = report_block.jitter();
495 report_block_info->report_block.delaySinceLastSR =
danilchap1b1863a2016-09-20 01:39:54 -0700496 report_block.delay_since_last_sr();
danilchap28b03eb2016-10-05 06:59:44 -0700497 report_block_info->report_block.lastSR = report_block.last_sr();
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000498
danilchap28b03eb2016-10-05 06:59:44 -0700499 int64_t rtt_ms = 0;
danilchap1b1863a2016-09-20 01:39:54 -0700500 uint32_t send_time = report_block.last_sr();
Danil Chapovalovc1e55c72016-03-09 15:14:35 +0100501 // RFC3550, section 6.4.1, LSR field discription states:
502 // If no SR has been received yet, the field is set to zero.
503 // Receiver rtp_rtcp module is not expected to calculate rtt using
504 // Sender Reports even if it accidentally can.
505 if (!receiver_only_ && send_time != 0) {
danilchap1b1863a2016-09-20 01:39:54 -0700506 uint32_t delay = report_block.delay_since_last_sr();
Danil Chapovalova094fd12016-02-22 18:59:36 +0100507 // Local NTP time.
508 uint32_t receive_time = CompactNtp(NtpTime(*_clock));
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000509
Danil Chapovalova094fd12016-02-22 18:59:36 +0100510 // RTT in 1/(2^16) seconds.
511 uint32_t rtt_ntp = receive_time - delay - send_time;
512 // Convert to 1/1000 seconds (milliseconds).
danilchap28b03eb2016-10-05 06:59:44 -0700513 rtt_ms = CompactNtpRttToMs(rtt_ntp);
514 if (rtt_ms > report_block_info->max_rtt_ms)
515 report_block_info->max_rtt_ms = rtt_ms;
niklase@google.com470e71d2011-07-07 08:21:25 +0000516
danilchap28b03eb2016-10-05 06:59:44 -0700517 if (report_block_info->num_rtts == 0 ||
518 rtt_ms < report_block_info->min_rtt_ms)
519 report_block_info->min_rtt_ms = rtt_ms;
520
521 report_block_info->last_rtt_ms = rtt_ms;
522 report_block_info->sum_rtt_ms += rtt_ms;
523 ++report_block_info->num_rtts;
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000524 }
525
danilchap1b1863a2016-09-20 01:39:54 -0700526 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR_RTT",
danilchap28b03eb2016-10-05 06:59:44 -0700527 report_block.source_ssrc(), rtt_ms);
perkj@webrtc.orgce5990c2012-01-11 13:00:08 +0000528
danilchap28b03eb2016-10-05 06:59:44 -0700529 packet_information->rtt_ms = rtt_ms;
530 packet_information->report_blocks.push_back(report_block_info->report_block);
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
danilchap7851bda2016-09-29 15:28:07 -0700533void RTCPReceiver::CreateReceiveInformation(uint32_t remote_ssrc) {
534 // Create or find receive information.
535 ReceiveInformation* receive_info = &received_infos_[remote_ssrc];
536 // Update that this remote is alive.
537 receive_info->last_time_received_ms = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +0000538}
539
danilchap7851bda2016-09-29 15:28:07 -0700540RTCPReceiver::ReceiveInformation* RTCPReceiver::GetReceiveInformation(
541 uint32_t remote_ssrc) {
542 auto it = received_infos_.find(remote_ssrc);
543 if (it == received_infos_.end())
544 return nullptr;
545 return &it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546}
547
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000548bool RTCPReceiver::RtcpRrTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700549 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000550 if (_lastReceivedRrMs == 0)
551 return false;
552
553 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000554 if (_clock->TimeInMilliseconds() > _lastReceivedRrMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000555 // Reset the timer to only trigger one log.
556 _lastReceivedRrMs = 0;
557 return true;
558 }
559 return false;
560}
561
562bool RTCPReceiver::RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms) {
danilchap7c9426c2016-04-14 03:05:31 -0700563 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000564 if (_lastIncreasedSequenceNumberMs == 0)
565 return false;
566
567 int64_t time_out_ms = kRrTimeoutIntervals * rtcp_interval_ms;
danilchapda161d72016-08-19 07:29:46 -0700568 if (_clock->TimeInMilliseconds() >
569 _lastIncreasedSequenceNumberMs + time_out_ms) {
mflodman@webrtc.org2f225ca2013-01-09 13:54:43 +0000570 // Reset the timer to only trigger one log.
571 _lastIncreasedSequenceNumberMs = 0;
572 return true;
573 }
574 return false;
575}
576
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000577bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() {
danilchap7c9426c2016-04-14 03:05:31 -0700578 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
niklase@google.com470e71d2011-07-07 08:21:25 +0000579
danilchap7851bda2016-09-29 15:28:07 -0700580 bool update_bounding_set = false;
581 int64_t now_ms = _clock->TimeInMilliseconds();
582 // Use audio define since we don't know what interval the remote peer use.
583 int64_t timeouted_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000584
danilchap7851bda2016-09-29 15:28:07 -0700585 for (auto receive_info_it = received_infos_.begin();
586 receive_info_it != received_infos_.end();) {
587 ReceiveInformation* receive_info = &receive_info_it->second;
588 if (receive_info->last_time_received_ms > 0) {
589 if (receive_info->last_time_received_ms < timeouted_ms) {
590 // No rtcp packet for the last 5 regular intervals, reset limitations.
591 receive_info->tmmbr.clear();
592 // Prevent that we call this over and over again.
593 receive_info->last_time_received_ms = 0;
594 // Send new TMMBN to all channels using the default codec.
595 update_bounding_set = true;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 }
danilchap7851bda2016-09-29 15:28:07 -0700597 ++receive_info_it;
598 } else if (receive_info->ready_for_delete) {
599 // When we dont have a last_time_received_ms and the object is marked
600 // ready_for_delete it's removed from the map.
601 receive_info_it = received_infos_.erase(receive_info_it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 } else {
danilchap7851bda2016-09-29 15:28:07 -0700603 ++receive_info_it;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000604 }
605 }
danilchap7851bda2016-09-29 15:28:07 -0700606 return update_bounding_set;
niklase@google.com470e71d2011-07-07 08:21:25 +0000607}
608
danilchap2b616392016-08-18 06:17:42 -0700609std::vector<rtcp::TmmbItem> RTCPReceiver::BoundingSet(bool* tmmbr_owner) {
danilchap7c9426c2016-04-14 03:05:31 -0700610 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap7851bda2016-09-29 15:28:07 -0700611 ReceiveInformation* receive_info = GetReceiveInformation(_remoteSSRC);
612 if (!receive_info)
danilchap2b616392016-08-18 06:17:42 -0700613 return std::vector<rtcp::TmmbItem>();
danilchap2b616392016-08-18 06:17:42 -0700614
danilchap7851bda2016-09-29 15:28:07 -0700615 *tmmbr_owner = TMMBRHelp::IsOwner(receive_info->tmmbn, main_ssrc_);
616 return receive_info->tmmbn;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617}
618
danilchap1b1863a2016-09-20 01:39:54 -0700619void RTCPReceiver::HandleSDES(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700620 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700621 rtcp::Sdes sdes;
622 if (!sdes.Parse(rtcp_block)) {
623 ++num_skipped_packets_;
624 return;
625 }
626
627 for (const rtcp::Sdes::Chunk& chunk : sdes.chunks()) {
danilchap95321242016-09-27 07:05:32 -0700628 received_cnames_[chunk.ssrc] = chunk.cname;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200629 {
630 rtc::CritScope lock(&_criticalSectionFeedbacks);
danilchap1b1863a2016-09-20 01:39:54 -0700631 if (stats_callback_)
632 stats_callback_->CNameChanged(chunk.cname.c_str(), chunk.ssrc);
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200633 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000634 }
danilchap92ea6012016-09-23 10:36:03 -0700635 packet_information->packet_type_flags |= kRtcpSdes;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636}
637
danilchap1b1863a2016-09-20 01:39:54 -0700638void RTCPReceiver::HandleNACK(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700639 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700640 rtcp::Nack nack;
641 if (!nack.Parse(rtcp_block)) {
642 ++num_skipped_packets_;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000643 return;
644 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000645
danilchap1b1863a2016-09-20 01:39:54 -0700646 if (receiver_only_ || main_ssrc_ != nack.media_ssrc()) // Not to us.
647 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200648
danilchap92ea6012016-09-23 10:36:03 -0700649 packet_information->nack_sequence_numbers = nack.packet_ids();
danilchap1b1863a2016-09-20 01:39:54 -0700650 for (uint16_t packet_id : nack.packet_ids())
651 nack_stats_.ReportRequest(packet_id);
652
653 if (!nack.packet_ids().empty()) {
danilchap92ea6012016-09-23 10:36:03 -0700654 packet_information->packet_type_flags |= kRtcpNack;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000655 ++packet_type_counter_.nack_packets;
656 packet_type_counter_.nack_requests = nack_stats_.requests();
657 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
658 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000659}
660
danilchap1b1863a2016-09-20 01:39:54 -0700661void RTCPReceiver::HandleBYE(const CommonHeader& rtcp_block) {
662 rtcp::Bye bye;
663 if (!bye.Parse(rtcp_block)) {
664 ++num_skipped_packets_;
665 return;
666 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000668 // clear our lists
danilchap28b03eb2016-10-05 06:59:44 -0700669 for (auto& reports_per_receiver : received_report_blocks_)
670 reports_per_receiver.second.erase(bye.sender_ssrc());
asapersson@webrtc.orgcb791412014-12-18 14:30:32 +0000671
danilchap7851bda2016-09-29 15:28:07 -0700672 // We can't delete it due to TMMBR.
673 ReceiveInformation* receive_info = GetReceiveInformation(bye.sender_ssrc());
674 if (receive_info)
675 receive_info->ready_for_delete = true;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000676
danilchap95321242016-09-27 07:05:32 -0700677 received_cnames_.erase(bye.sender_ssrc());
asapersson@webrtc.org7d6bd222013-10-31 12:14:34 +0000678 xr_rr_rtt_ms_ = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000679}
680
danilchap1b1863a2016-09-20 01:39:54 -0700681void RTCPReceiver::HandleXr(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700682 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700683 rtcp::ExtendedReports xr;
684 if (!xr.Parse(rtcp_block)) {
685 ++num_skipped_packets_;
686 return;
687 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000688
danilchap1b1863a2016-09-20 01:39:54 -0700689 for (const rtcp::Rrtr& rrtr : xr.rrtrs())
danilchap92ea6012016-09-23 10:36:03 -0700690 HandleXrReceiveReferenceTime(xr.sender_ssrc(), rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000691
danilchap1b1863a2016-09-20 01:39:54 -0700692 for (const rtcp::Dlrr& dlrr : xr.dlrrs()) {
693 for (const rtcp::ReceiveTimeInfo& time_info : dlrr.sub_blocks())
danilchap92ea6012016-09-23 10:36:03 -0700694 HandleXrDlrrReportBlock(time_info);
danilchap1b1863a2016-09-20 01:39:54 -0700695 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000696}
697
698void RTCPReceiver::HandleXrReceiveReferenceTime(
danilchap92ea6012016-09-23 10:36:03 -0700699 uint32_t sender_ssrc,
700 const rtcp::Rrtr& rrtr) {
danilchap798896a2016-09-28 02:54:25 -0700701 remote_time_info_.ssrc = sender_ssrc;
702 remote_time_info_.last_rr = CompactNtp(rrtr.ntp());
danilchap0b4b7272016-10-06 09:24:45 -0700703 last_received_xr_ntp_.SetCurrent(*_clock);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000704}
705
danilchap92ea6012016-09-23 10:36:03 -0700706void RTCPReceiver::HandleXrDlrrReportBlock(const rtcp::ReceiveTimeInfo& rti) {
danilchap1b1863a2016-09-20 01:39:54 -0700707 if (registered_ssrcs_.count(rti.ssrc) == 0) // Not to us.
708 return;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000709
danilchap1b1863a2016-09-20 01:39:54 -0700710 // Caller should explicitly enable rtt calculation using extended reports.
711 if (!xr_rrtr_status_)
712 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200713
danilchap1b1863a2016-09-20 01:39:54 -0700714 // The send_time and delay_rr fields are in units of 1/2^16 sec.
715 uint32_t send_time = rti.last_rr;
716 // RFC3611, section 4.5, LRR field discription states:
717 // If no such block has been received, the field is set to zero.
718 if (send_time == 0)
719 return;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200720
danilchap1b1863a2016-09-20 01:39:54 -0700721 uint32_t delay_rr = rti.delay_since_last_rr;
722 uint32_t now = CompactNtp(NtpTime(*_clock));
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200723
danilchap1b1863a2016-09-20 01:39:54 -0700724 uint32_t rtt_ntp = now - delay_rr - send_time;
725 xr_rr_rtt_ms_ = CompactNtpRttToMs(rtt_ntp);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000726}
727
danilchap1b1863a2016-09-20 01:39:54 -0700728void RTCPReceiver::HandlePLI(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700729 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700730 rtcp::Pli pli;
731 if (!pli.Parse(rtcp_block)) {
732 ++num_skipped_packets_;
733 return;
734 }
735
736 if (main_ssrc_ == pli.media_ssrc()) {
sprang@webrtc.org0200f702015-02-16 12:06:00 +0000737 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PLI");
justinlin@chromium.org7bfb3a32013-05-13 22:59:00 +0000738
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000739 ++packet_type_counter_.pli_packets;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000740 // Received a signal that we need to send a new key frame.
danilchap92ea6012016-09-23 10:36:03 -0700741 packet_information->packet_type_flags |= kRtcpPli;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000742 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000743}
744
danilchap1b1863a2016-09-20 01:39:54 -0700745void RTCPReceiver::HandleTMMBR(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700746 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700747 rtcp::Tmmbr tmmbr;
748 if (!tmmbr.Parse(rtcp_block)) {
749 ++num_skipped_packets_;
750 return;
751 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000752
danilchap7851bda2016-09-29 15:28:07 -0700753 uint32_t sender_ssrc = tmmbr.sender_ssrc();
754 ReceiveInformation* receive_info = GetReceiveInformation(sender_ssrc);
755 if (!receive_info) // This remote SSRC must be saved before.
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000756 return;
danilchap1b1863a2016-09-20 01:39:54 -0700757
758 if (tmmbr.media_ssrc()) {
759 // media_ssrc() SHOULD be 0 if same as SenderSSRC.
760 // In relay mode this is a valid number.
danilchap7851bda2016-09-29 15:28:07 -0700761 sender_ssrc = tmmbr.media_ssrc();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000762 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
danilchap1b1863a2016-09-20 01:39:54 -0700764 for (const rtcp::TmmbItem& request : tmmbr.requests()) {
765 if (main_ssrc_ == request.ssrc() && request.bitrate_bps()) {
danilchap7851bda2016-09-29 15:28:07 -0700766 auto* entry = &receive_info->tmmbr[sender_ssrc];
767 entry->tmmbr_item = rtcp::TmmbItem(sender_ssrc,
768 request.bitrate_bps(),
769 request.packet_overhead());
770 entry->last_updated_ms = _clock->TimeInMilliseconds();
771
danilchap92ea6012016-09-23 10:36:03 -0700772 packet_information->packet_type_flags |= kRtcpTmmbr;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200773 }
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000774 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000775}
776
danilchap1b1863a2016-09-20 01:39:54 -0700777void RTCPReceiver::HandleTMMBN(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700778 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700779 rtcp::Tmmbn tmmbn;
780 if (!tmmbn.Parse(rtcp_block)) {
781 ++num_skipped_packets_;
782 return;
783 }
784
danilchap7851bda2016-09-29 15:28:07 -0700785 ReceiveInformation* receive_info = GetReceiveInformation(tmmbn.sender_ssrc());
786 if (!receive_info) // This remote SSRC must be saved before.
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000787 return;
danilchap1b1863a2016-09-20 01:39:54 -0700788
danilchap92ea6012016-09-23 10:36:03 -0700789 packet_information->packet_type_flags |= kRtcpTmmbn;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000790
danilchap1b1863a2016-09-20 01:39:54 -0700791 for (const auto& item : tmmbn.items())
danilchap7851bda2016-09-29 15:28:07 -0700792 receive_info->tmmbn.push_back(item);
danilchap1b1863a2016-09-20 01:39:54 -0700793}
794
795void RTCPReceiver::HandleSR_REQ(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700796 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700797 rtcp::RapidResyncRequest sr_req;
798 if (!sr_req.Parse(rtcp_block)) {
799 ++num_skipped_packets_;
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000800 return;
801 }
802
danilchap92ea6012016-09-23 10:36:03 -0700803 packet_information->packet_type_flags |= kRtcpSrReq;
niklase@google.com470e71d2011-07-07 08:21:25 +0000804}
805
danilchap1b1863a2016-09-20 01:39:54 -0700806void RTCPReceiver::HandleSLI(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700807 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700808 rtcp::Sli sli;
809 if (!sli.Parse(rtcp_block)) {
810 ++num_skipped_packets_;
811 return;
812 }
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200813
danilchap1b1863a2016-09-20 01:39:54 -0700814 for (const rtcp::Sli::Macroblocks& item : sli.macroblocks()) {
815 // In theory there could be multiple slices lost.
816 // Received signal that we need to refresh a slice.
danilchap92ea6012016-09-23 10:36:03 -0700817 packet_information->packet_type_flags |= kRtcpSli;
818 packet_information->sli_picture_id = item.picture_id();
asapersson@webrtc.orgdf7b65b2015-01-21 13:07:04 +0000819 }
820}
821
danilchap92ea6012016-09-23 10:36:03 -0700822void RTCPReceiver::HandleRPSI(const CommonHeader& rtcp_block,
823 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700824 rtcp::Rpsi rpsi;
825 if (!rpsi.Parse(rtcp_block)) {
826 ++num_skipped_packets_;
827 return;
danilchapda161d72016-08-19 07:29:46 -0700828 }
danilchap1b1863a2016-09-20 01:39:54 -0700829
830 // Received signal that we have a confirmed reference picture.
danilchap92ea6012016-09-23 10:36:03 -0700831 packet_information->packet_type_flags |= kRtcpRpsi;
832 packet_information->rpsi_picture_id = rpsi.picture_id();
niklase@google.com470e71d2011-07-07 08:21:25 +0000833}
834
danilchap1b1863a2016-09-20 01:39:54 -0700835void RTCPReceiver::HandlePsfbApp(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700836 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700837 rtcp::Remb remb;
838 if (remb.Parse(rtcp_block)) {
danilchap92ea6012016-09-23 10:36:03 -0700839 packet_information->packet_type_flags |= kRtcpRemb;
840 packet_information->receiver_estimated_max_bitrate_bps = remb.bitrate_bps();
danilchap1b1863a2016-09-20 01:39:54 -0700841 return;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000842 }
danilchap1b1863a2016-09-20 01:39:54 -0700843
844 ++num_skipped_packets_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000845}
846
danilchap1b1863a2016-09-20 01:39:54 -0700847void RTCPReceiver::HandleFIR(const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700848 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700849 rtcp::Fir fir;
850 if (!fir.Parse(rtcp_block)) {
851 ++num_skipped_packets_;
852 return;
853 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000854
danilchap7851bda2016-09-29 15:28:07 -0700855 ReceiveInformation* receive_info = GetReceiveInformation(fir.sender_ssrc());
danilchap1b1863a2016-09-20 01:39:54 -0700856
857 for (const rtcp::Fir::Request& fir_request : fir.requests()) {
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200858 // Is it our sender that is requested to generate a new keyframe
danilchap1b1863a2016-09-20 01:39:54 -0700859 if (main_ssrc_ != fir_request.ssrc)
860 continue;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200861
862 ++packet_type_counter_.fir_packets;
863
danilchap7851bda2016-09-29 15:28:07 -0700864 if (receive_info) {
865 // Check if we have reported this FIRSequenceNumber before.
866 if (fir_request.seq_nr == receive_info->last_fir_sequence_number)
867 continue;
868
869 int64_t now_ms = _clock->TimeInMilliseconds();
870 // Sanity: don't go crazy with the callbacks.
871 if (now_ms - receive_info->last_fir_request_ms < RTCP_MIN_FRAME_LENGTH_MS)
872 continue;
873
874 receive_info->last_fir_request_ms = now_ms;
875 receive_info->last_fir_sequence_number = fir_request.seq_nr;
Danil Chapovalov530b3f52016-09-15 18:41:02 +0200876 }
danilchap7851bda2016-09-29 15:28:07 -0700877 // Received signal that we need to send a new key frame.
878 packet_information->packet_type_flags |= kRtcpFir;
pwestin@webrtc.orgb2179c22012-05-21 12:00:49 +0000879 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000880}
881
Erik Språng6b8d3552015-09-24 15:06:57 +0200882void RTCPReceiver::HandleTransportFeedback(
danilchap1b1863a2016-09-20 01:39:54 -0700883 const CommonHeader& rtcp_block,
danilchap92ea6012016-09-23 10:36:03 -0700884 PacketInformation* packet_information) {
danilchap1b1863a2016-09-20 01:39:54 -0700885 std::unique_ptr<rtcp::TransportFeedback> transport_feedback(
886 new rtcp::TransportFeedback());
887 if (!transport_feedback->Parse(rtcp_block)) {
888 ++num_skipped_packets_;
889 return;
890 }
Erik Språng6b8d3552015-09-24 15:06:57 +0200891
danilchap92ea6012016-09-23 10:36:03 -0700892 packet_information->packet_type_flags |= kRtcpTransportFeedback;
893 packet_information->transport_feedback = std::move(transport_feedback);
Erik Språng6b8d3552015-09-24 15:06:57 +0200894}
danilchap287e5482016-08-16 15:15:39 -0700895
danilchap853ecb22016-08-22 08:26:15 -0700896void RTCPReceiver::UpdateTmmbr() {
897 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700898 std::vector<rtcp::TmmbItem> bounding =
danilchap853ecb22016-08-22 08:26:15 -0700899 TMMBRHelp::FindBoundingSet(TmmbrReceived());
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000900
danilchap853ecb22016-08-22 08:26:15 -0700901 if (!bounding.empty() && _cbRtcpBandwidthObserver) {
902 // We have a new bandwidth estimate on this channel.
danilchap2f69ce92016-08-16 03:21:38 -0700903 uint64_t bitrate_bps = TMMBRHelp::CalcMinBitrateBps(bounding);
904 if (bitrate_bps <= std::numeric_limits<uint32_t>::max())
905 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(bitrate_bps);
pwestin@webrtc.orgcac78782012-04-05 08:30:10 +0000906 }
danilchap853ecb22016-08-22 08:26:15 -0700907
908 // Set bounding set: inform remote clients about the new bandwidth.
909 _rtpRtcp.SetTmmbn(std::move(bounding));
niklase@google.com470e71d2011-07-07 08:21:25 +0000910}
911
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +0000912void RTCPReceiver::RegisterRtcpStatisticsCallback(
913 RtcpStatisticsCallback* callback) {
danilchap7c9426c2016-04-14 03:05:31 -0700914 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +0000915 stats_callback_ = callback;
916}
917
918RtcpStatisticsCallback* RTCPReceiver::GetRtcpStatisticsCallback() {
danilchap7c9426c2016-04-14 03:05:31 -0700919 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +0000920 return stats_callback_;
921}
922
niklase@google.com470e71d2011-07-07 08:21:25 +0000923// Holding no Critical section
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +0000924void RTCPReceiver::TriggerCallbacksFromRTCPPacket(
danilchap92ea6012016-09-23 10:36:03 -0700925 const PacketInformation& packet_information) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000926 // Process TMMBR and REMB first to avoid multiple callbacks
927 // to OnNetworkChanged.
danilchap92ea6012016-09-23 10:36:03 -0700928 if (packet_information.packet_type_flags & kRtcpTmmbr) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000929 // Might trigger a OnReceivedBandwidthEstimateUpdate.
danilchap853ecb22016-08-22 08:26:15 -0700930 UpdateTmmbr();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000931 }
sprang7dc39f32015-10-13 09:17:48 -0700932 uint32_t local_ssrc;
933 std::set<uint32_t> registered_ssrcs;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000934 {
935 // We don't want to hold this critsect when triggering the callbacks below.
danilchap7c9426c2016-04-14 03:05:31 -0700936 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
stefan@webrtc.org28a331e2013-09-17 07:49:56 +0000937 local_ssrc = main_ssrc_;
sprang7dc39f32015-10-13 09:17:48 -0700938 registered_ssrcs = registered_ssrcs_;
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000939 }
danilchap92ea6012016-09-23 10:36:03 -0700940 if (!receiver_only_ && (packet_information.packet_type_flags & kRtcpSrReq)) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000941 _rtpRtcp.OnRequestSendReport();
942 }
danilchap92ea6012016-09-23 10:36:03 -0700943 if (!receiver_only_ && (packet_information.packet_type_flags & kRtcpNack)) {
944 if (!packet_information.nack_sequence_numbers.empty()) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +0000945 LOG(LS_VERBOSE) << "Incoming NACK length: "
danilchap92ea6012016-09-23 10:36:03 -0700946 << packet_information.nack_sequence_numbers.size();
947 _rtpRtcp.OnReceivedNack(packet_information.nack_sequence_numbers);
pwestin@webrtc.org3aa25de2012-01-05 08:40:56 +0000948 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000949 }
950 {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000951 // We need feedback that we have received a report block(s) so that we
952 // can generate a new packet in a conference relay scenario, one received
953 // report can generate several RTCP packets, based on number relayed/mixed
954 // a send report block should go out to all receivers.
955 if (_cbRtcpIntraFrameObserver) {
henrikg91d6ede2015-09-17 00:24:34 -0700956 RTC_DCHECK(!receiver_only_);
danilchap92ea6012016-09-23 10:36:03 -0700957 if ((packet_information.packet_type_flags & kRtcpPli) ||
958 (packet_information.packet_type_flags & kRtcpFir)) {
959 if (packet_information.packet_type_flags & kRtcpPli) {
andresp@webrtc.org4436b442014-06-04 09:05:30 +0000960 LOG(LS_VERBOSE) << "Incoming PLI from SSRC "
danilchap92ea6012016-09-23 10:36:03 -0700961 << packet_information.remote_ssrc;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000962 } else {
andresp@webrtc.org4436b442014-06-04 09:05:30 +0000963 LOG(LS_VERBOSE) << "Incoming FIR from SSRC "
danilchap92ea6012016-09-23 10:36:03 -0700964 << packet_information.remote_ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965 }
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000966 _cbRtcpIntraFrameObserver->OnReceivedIntraFrameRequest(local_ssrc);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000967 }
danilchap92ea6012016-09-23 10:36:03 -0700968 if (packet_information.packet_type_flags & kRtcpSli) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000969 _cbRtcpIntraFrameObserver->OnReceivedSLI(
danilchap92ea6012016-09-23 10:36:03 -0700970 local_ssrc, packet_information.sli_picture_id);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000971 }
danilchap92ea6012016-09-23 10:36:03 -0700972 if (packet_information.packet_type_flags & kRtcpRpsi) {
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000973 _cbRtcpIntraFrameObserver->OnReceivedRPSI(
danilchap92ea6012016-09-23 10:36:03 -0700974 local_ssrc, packet_information.rpsi_picture_id);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000975 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000976 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000977 if (_cbRtcpBandwidthObserver) {
henrikg91d6ede2015-09-17 00:24:34 -0700978 RTC_DCHECK(!receiver_only_);
danilchap92ea6012016-09-23 10:36:03 -0700979 if (packet_information.packet_type_flags & kRtcpRemb) {
980 LOG(LS_VERBOSE)
981 << "Incoming REMB: "
982 << packet_information.receiver_estimated_max_bitrate_bps;
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000983 _cbRtcpBandwidthObserver->OnReceivedEstimatedBitrate(
danilchap92ea6012016-09-23 10:36:03 -0700984 packet_information.receiver_estimated_max_bitrate_bps);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000985 }
danilchap92ea6012016-09-23 10:36:03 -0700986 if ((packet_information.packet_type_flags & kRtcpSr) ||
987 (packet_information.packet_type_flags & kRtcpRr)) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000988 int64_t now = _clock->TimeInMilliseconds();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000989 _cbRtcpBandwidthObserver->OnReceivedRtcpReceiverReport(
danilchap92ea6012016-09-23 10:36:03 -0700990 packet_information.report_blocks, packet_information.rtt_ms, now);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000991 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000992 }
danilchap92ea6012016-09-23 10:36:03 -0700993 if ((packet_information.packet_type_flags & kRtcpSr) ||
994 (packet_information.packet_type_flags & kRtcpRr)) {
995 _rtpRtcp.OnReceivedRtcpReportBlocks(packet_information.report_blocks);
isheriff6b4b5f32016-06-08 00:24:21 -0700996 }
997
Erik Språng6b8d3552015-09-24 15:06:57 +0200998 if (_cbTransportFeedbackObserver &&
danilchap92ea6012016-09-23 10:36:03 -0700999 (packet_information.packet_type_flags & kRtcpTransportFeedback)) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001000 uint32_t media_source_ssrc =
danilchap92ea6012016-09-23 10:36:03 -07001001 packet_information.transport_feedback->media_ssrc();
sprang7dc39f32015-10-13 09:17:48 -07001002 if (media_source_ssrc == local_ssrc ||
1003 registered_ssrcs.find(media_source_ssrc) != registered_ssrcs.end()) {
Erik Språng6b8d3552015-09-24 15:06:57 +02001004 _cbTransportFeedbackObserver->OnTransportFeedback(
danilchap92ea6012016-09-23 10:36:03 -07001005 *packet_information.transport_feedback);
Erik Språng6b8d3552015-09-24 15:06:57 +02001006 }
1007 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001008 }
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001009
Peter Boströmfe7a80c2015-04-23 17:53:17 +02001010 if (!receiver_only_) {
danilchap7c9426c2016-04-14 03:05:31 -07001011 rtc::CritScope cs(&_criticalSectionFeedbacks);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001012 if (stats_callback_) {
danilchap92ea6012016-09-23 10:36:03 -07001013 for (const auto& report_block : packet_information.report_blocks) {
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001014 RtcpStatistics stats;
danilchap92ea6012016-09-23 10:36:03 -07001015 stats.cumulative_lost = report_block.cumulativeLost;
1016 stats.extended_max_sequence_number = report_block.extendedHighSeqNum;
1017 stats.fraction_lost = report_block.fractionLost;
1018 stats.jitter = report_block.jitter;
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001019
danilchap92ea6012016-09-23 10:36:03 -07001020 stats_callback_->StatisticsUpdated(stats, report_block.sourceSSRC);
sprang@webrtc.orga6ad6e52013-12-05 09:48:44 +00001021 }
1022 }
1023 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001024}
1025
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001026int32_t RTCPReceiver::CNAME(uint32_t remoteSSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 char cName[RTCP_CNAME_SIZE]) const {
danilchap95321242016-09-27 07:05:32 -07001028 RTC_DCHECK(cName);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001029
danilchap7c9426c2016-04-14 03:05:31 -07001030 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap95321242016-09-27 07:05:32 -07001031 auto received_cname_it = received_cnames_.find(remoteSSRC);
1032 if (received_cname_it == received_cnames_.end())
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +00001033 return -1;
danilchap95321242016-09-27 07:05:32 -07001034
1035 size_t length = received_cname_it->second.copy(cName, RTCP_CNAME_SIZE - 1);
1036 cName[length] = 0;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00001037 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038}
1039
danilchap7851bda2016-09-29 15:28:07 -07001040std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() {
danilchap7c9426c2016-04-14 03:05:31 -07001041 rtc::CritScope lock(&_criticalSectionRTCPReceiver);
danilchap287e5482016-08-16 15:15:39 -07001042 std::vector<rtcp::TmmbItem> candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001043
danilchap287e5482016-08-16 15:15:39 -07001044 int64_t now_ms = _clock->TimeInMilliseconds();
danilchap7851bda2016-09-29 15:28:07 -07001045 // Use audio define since we don't know what interval the remote peer use.
1046 int64_t timeouted_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS;
danilchap287e5482016-08-16 15:15:39 -07001047
danilchap7851bda2016-09-29 15:28:07 -07001048 for (auto& kv : received_infos_) {
1049 for (auto it = kv.second.tmmbr.begin(); it != kv.second.tmmbr.end();) {
1050 if (it->second.last_updated_ms < timeouted_ms) {
1051 // Erase timeout entries.
1052 it = kv.second.tmmbr.erase(it);
1053 } else {
1054 candidates.push_back(it->second.tmmbr_item);
1055 ++it;
1056 }
1057 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001058 }
danilchap287e5482016-08-16 15:15:39 -07001059 return candidates;
niklase@google.com470e71d2011-07-07 08:21:25 +00001060}
1061
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001062} // namespace webrtc