1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2f6bb77a6f0d250f8c4c2c4dbf059556c00cf8eafpwestin@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1312dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <assert.h>  // assert
149354cc965c04a0c79ea36622043751596a6fd015stefan@webrtc.org#include <string.h>  // memcpy
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1612dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org#include <algorithm>  // min
1761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng#include <limits>     // max
18b8b6fbb7a5d2f5a14f7f6f81c253747aa28e4c7fdanilchap#include <utility>
1912dc1a38ca54a000e4fecfbc6d41138b895c9ca5pbos@webrtc.org
2061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng#include "webrtc/base/checks.h"
21ebc0b4e99365443111857a0c7cfcc8944d8f1b6ePeter Boström#include "webrtc/base/logging.h"
22e4f96501fc5b3e6de0d1ccd262372afcda1f5b4ftommi#include "webrtc/base/trace_event.h"
23a048d7cb0a5bad5ca49bbcc5273cb4cca28c1710pbos@webrtc.org#include "webrtc/common_types.h"
24779c3d16b9623f38a72439bc013102aeb0077a62sprang@webrtc.org#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
250219c9b4bfcbb778137756210eb95f40d936cc66danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
2650c5136cb2ad11eb9ba3df1a1d54d527c8a0dc77danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
272f7dea164dc49ae8a0322e3c9edb1dd23266c664danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
28a8890a57a5d03f942924ff61d3c62244f2bdab10danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
29f8385aded0943c7889d6e9b92f3c0978f3657bb2danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
3097f7e13c23ddb26543f33bce944d501e58d1dd9bDanil Chapovalov#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
3192e677a1f8d24dfa0031d307c4a7d8e530cd4eb4danilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
32ef3d805f6e50bc488f8e4e9e353068b78c73d17fdanilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
337e8145f05d5f6921ffca3d62e9c4d1301c1d8bcbdanilchap#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
34233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
35e4f96501fc5b3e6de0d1ccd262372afcda1f5b4ftommi#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
3698f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
37741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org
38470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comnamespace webrtc {
3926f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org
4026f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.orgusing RTCPUtility::RTCPCnameInformation;
4126f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org
4261be2a401635eed1d13c169dc104b9ff4a2f477bErik SprångNACKStringBuilder::NACKStringBuilder()
43162abd3562d7b08ab36569800d757b52739b9249danilchap    : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
4479b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com
45f3e4ceee47d747c8868d919c179ecc640b9541f0pbos@webrtc.orgNACKStringBuilder::~NACKStringBuilder() {}
46f3e4ceee47d747c8868d919c179ecc640b9541f0pbos@webrtc.org
47162abd3562d7b08ab36569800d757b52739b9249danilchapvoid NACKStringBuilder::PushNACK(uint16_t nack) {
48242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (count_ == 0) {
49242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    stream_ << nack;
50242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  } else if (nack == prevNack_ + 1) {
51242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    consecutive_ = true;
5261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  } else {
53242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    if (consecutive_) {
54242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      stream_ << "-" << prevNack_;
55242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      consecutive_ = false;
5679b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com    }
57242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    stream_ << "," << nack;
5861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
59242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  count_++;
60242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  prevNack_ = nack;
6179b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com}
6279b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com
6361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngstd::string NACKStringBuilder::GetResult() {
64242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (consecutive_) {
65242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    stream_ << "-" << prevNack_;
66242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    consecutive_ = false;
6761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
68242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return stream_.str();
6979b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com}
7079b0289bfc9f425d15442b1ecd73c2ae69646326edjee@google.com
7159f20bb735562d245357609799578edeed46be32pbos@webrtc.orgRTCPSender::FeedbackState::FeedbackState()
7259f20bb735562d245357609799578edeed46be32pbos@webrtc.org    : send_payload_type(0),
7359f20bb735562d245357609799578edeed46be32pbos@webrtc.org      frequency_hz(0),
742f4b14e3f31b34a50310357c6c7be86c3bca1537pbos@webrtc.org      packets_sent(0),
752f4b14e3f31b34a50310357c6c7be86c3bca1537pbos@webrtc.org      media_bytes_sent(0),
7659f20bb735562d245357609799578edeed46be32pbos@webrtc.org      send_bitrate(0),
7759f20bb735562d245357609799578edeed46be32pbos@webrtc.org      last_rr_ntp_secs(0),
7859f20bb735562d245357609799578edeed46be32pbos@webrtc.org      last_rr_ntp_frac(0),
798469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org      remote_sr(0),
8061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      has_last_xr_rr(false),
81162abd3562d7b08ab36569800d757b52739b9249danilchap      module(nullptr) {}
8259f20bb735562d245357609799578edeed46be32pbos@webrtc.org
832f7dea164dc49ae8a0322e3c9edb1dd23266c664danilchapclass PacketContainer : public rtcp::CompoundPacket,
84f7c5776d4254e31e51107388a05c66d14108a8afErik Språng                        public rtcp::RtcpPacket::PacketReadyCallback {
85f7c5776d4254e31e51107388a05c66d14108a8afErik Språng public:
86f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  explicit PacketContainer(Transport* transport)
87f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      : transport_(transport), bytes_sent_(0) {}
88f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  virtual ~PacketContainer() {
89f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    for (RtcpPacket* packet : appended_packets_)
90f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      delete packet;
91242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  }
92242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
93bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  void OnPacketReady(uint8_t* data, size_t length) override {
94f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    if (transport_->SendRtcp(data, length))
95f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      bytes_sent_ += length;
96bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  }
97f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
98f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  size_t SendPackets() {
992f7dea164dc49ae8a0322e3c9edb1dd23266c664danilchap    rtcp::CompoundPacket::Build(this);
100f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    return bytes_sent_;
10172aa9a6c6e8d05c744496ad8c53273ec49556d28Erik Språng  }
102bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng
103bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng private:
104f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  Transport* transport_;
105f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  size_t bytes_sent_;
106f7c5776d4254e31e51107388a05c66d14108a8afErik Språng};
107f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
108f7c5776d4254e31e51107388a05c66d14108a8afErik Språngclass RTCPSender::RtcpContext {
109f7c5776d4254e31e51107388a05c66d14108a8afErik Språng public:
110f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  RtcpContext(const FeedbackState& feedback_state,
111f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              int32_t nack_size,
112f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              const uint16_t* nack_list,
113f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              bool repeat,
114f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              uint64_t picture_id,
115f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              uint32_t ntp_sec,
116f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              uint32_t ntp_frac,
117f7c5776d4254e31e51107388a05c66d14108a8afErik Språng              PacketContainer* container)
118f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      : feedback_state_(feedback_state),
119f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        nack_size_(nack_size),
120f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        nack_list_(nack_list),
121f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        repeat_(repeat),
122f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        picture_id_(picture_id),
123f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        ntp_sec_(ntp_sec),
124f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        ntp_frac_(ntp_frac),
125f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        container_(container) {}
126f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
127f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  virtual ~RtcpContext() {}
128f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
129f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const FeedbackState& feedback_state_;
130f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const int32_t nack_size_;
131f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const uint16_t* nack_list_;
132f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const bool repeat_;
133f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const uint64_t picture_id_;
134f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const uint32_t ntp_sec_;
135f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const uint32_t ntp_frac_;
136f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
137f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  PacketContainer* const container_;
138bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng};
139bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng
1401d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.orgRTCPSender::RTCPSender(
1411d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    bool audio,
1421d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    Clock* clock,
1431d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    ReceiveStatistics* receive_statistics,
14486fd9ed6f9e2a38aa343db8c62764659633231fasprang    RtcpPacketTypeCounterObserver* packet_type_counter_observer,
14586fd9ed6f9e2a38aa343db8c62764659633231fasprang    Transport* outgoing_transport)
146ac547a653862744d0aae560713f8418ad2852085Peter Boström    : audio_(audio),
147242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      clock_(clock),
14847a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap      random_(clock_->TimeInMicroseconds()),
149da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos      method_(RtcpMode::kOff),
15086fd9ed6f9e2a38aa343db8c62764659633231fasprang      transport_(outgoing_transport),
151d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
152242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      critical_section_rtcp_sender_(
153d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org          CriticalSectionWrapper::CreateCriticalSection()),
154242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      using_nack_(false),
155242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      sending_(false),
156242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      remb_enabled_(false),
157242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      next_time_to_send_rtcp_(0),
158d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org      start_timestamp_(0),
159d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org      last_rtp_timestamp_(0),
160d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org      last_frame_capture_time_ms_(-1),
161242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      ssrc_(0),
162242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      remote_ssrc_(0),
163d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org      receive_statistics_(receive_statistics),
164d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
165242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      sequence_number_fir_(0),
166d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
167242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      remb_bitrate_(0),
168d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
169242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      tmmbr_help_(),
170242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      tmmbr_send_(0),
171242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      packet_oh_send_(0),
172d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
173242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      app_sub_type_(0),
174bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng      app_name_(0),
175242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      app_data_(nullptr),
176242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      app_length_(0),
177d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
178242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      xr_send_receiver_reference_time_enabled_(false),
1791d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org      packet_type_counter_observer_(packet_type_counter_observer) {
180242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  memset(last_send_report_, 0, sizeof(last_send_report_));
181242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
18286fd9ed6f9e2a38aa343db8c62764659633231fasprang  RTC_DCHECK(transport_ != nullptr);
183242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
184242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpSr] = &RTCPSender::BuildSR;
185242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpRr] = &RTCPSender::BuildRR;
1860ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
187242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpPli] = &RTCPSender::BuildPLI;
188242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpFir] = &RTCPSender::BuildFIR;
189242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpSli] = &RTCPSender::BuildSLI;
190242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
191242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
192242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpBye] = &RTCPSender::BuildBYE;
193242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpApp] = &RTCPSender::BuildAPP;
194242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
195242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
196242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpNack] = &RTCPSender::BuildNACK;
197242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
198242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpXrReceiverReferenceTime] =
199242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      &RTCPSender::BuildReceiverReferenceTime;
200242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
203162abd3562d7b08ab36569800d757b52739b9249danilchapRTCPSender::~RTCPSender() {}
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
205da903eaabbb6c6830efcafc3c2ade1d36f511e43pbosRtcpMode RTCPSender::Status() const {
206242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return method_;
208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
210da903eaabbb6c6830efcafc3c2ade1d36f511e43pbosvoid RTCPSender::SetRTCPStatus(RtcpMode method) {
211242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
212242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  method_ = method;
213d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org
214da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos  if (method == RtcpMode::kOff)
215d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org    return;
216242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  next_time_to_send_rtcp_ =
217242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      clock_->TimeInMilliseconds() +
218242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
22161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngbool RTCPSender::Sending() const {
222242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
223242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return sending_;
224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
22661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngint32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
22761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng                                     bool sending) {
22861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  bool sendRTCPBye = false;
22961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  {
230242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
23161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
232da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos    if (method_ != RtcpMode::kOff) {
233242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      if (sending == false && sending_ == true) {
23461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        // Trigger RTCP bye
23561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        sendRTCPBye = true;
23661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      }
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
238242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    sending_ = sending;
23961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
24061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  if (sendRTCPBye)
24161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return SendRTCP(feedback_state, kRtcpBye);
24261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return 0;
243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
24561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngbool RTCPSender::REMB() const {
246242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return remb_enabled_;
248741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org}
249741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org
250d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid RTCPSender::SetREMBStatus(bool enable) {
251242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  remb_enabled_ = enable;
253741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org}
254741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org
255d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid RTCPSender::SetREMBData(uint32_t bitrate,
256d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                             const std::vector<uint32_t>& ssrcs) {
257242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
258242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  remb_bitrate_ = bitrate;
259d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  remb_ssrcs_ = ssrcs;
2604ef438e2defd6c46404f6b367287364cde66b7fbstefan@webrtc.org
261242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (remb_enabled_)
262242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    SetFlag(kRtcpRemb, false);
263d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
264d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  // throttled by the caller.
265242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
266741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org}
267741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org
26861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngbool RTCPSender::TMMBR() const {
269242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
273d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid RTCPSender::SetTMMBRStatus(bool enable) {
274242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
275242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (enable) {
276242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    SetFlag(RTCPPacketType::kRtcpTmmbr, false);
277242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  } else {
278242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
279242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  }
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2827c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.orgvoid RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
283242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
2847c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org  start_timestamp_ = start_timestamp;
2857c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org}
2867c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org
2877c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.orgvoid RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
2887c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org                                int64_t capture_time_ms) {
289242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
2907c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org  last_rtp_timestamp_ = rtp_timestamp;
2917c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org  if (capture_time_ms < 0) {
2927c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org    // We don't currently get a capture time from VoiceEngine.
293242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
2947c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org  } else {
2957c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org    last_frame_capture_time_ms_ = capture_time_ms;
2967c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org  }
2977c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org}
2987c3523c1a4c828ecb2773c685145fcfbd7c3ceadstefan@webrtc.org
299d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgvoid RTCPSender::SetSSRC(uint32_t ssrc) {
300242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
30161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
302242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (ssrc_ != 0) {
30361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // not first SetSSRC, probably due to a collision
30461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // schedule a new RTCP report
30561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // make sure that we send a RTP packet
306242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
30761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
308242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  ssrc_ = ssrc;
309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
31161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngvoid RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
312242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
313242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  remote_ssrc_ = ssrc;
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3169ba52f89acd1b9bc88115880dfe2716147bf3b5dPeter Boströmint32_t RTCPSender::SetCNAME(const char* c_name) {
3179ba52f89acd1b9bc88115880dfe2716147bf3b5dPeter Boström  if (!c_name)
318a990e122c461e24d19e3249718782e671a811eadtommi@webrtc.org    return -1;
319a990e122c461e24d19e3249718782e671a811eadtommi@webrtc.org
32091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
321242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
3220ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  cname_ = c_name;
32326f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org  return 0;
324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3260ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språngint32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
3270ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  assert(c_name);
32891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
329242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
3300ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  if (csrc_cnames_.size() >= kRtpCsrcSize)
33126f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org    return -1;
3320ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng
3330ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  csrc_cnames_[SSRC] = c_name;
33426f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org  return 0;
33526f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org}
336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
337d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
338242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
3390ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  auto it = csrc_cnames_.find(SSRC);
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
341242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (it == csrc_cnames_.end())
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
34361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
344242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  csrc_cnames_.erase(it);
34526f8d9c7f3865b9f94ea83d8b67b2ebee1d93f7dpwestin@webrtc.org  return 0;
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
348d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgbool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
349162abd3562d7b08ab36569800d757b52739b9249danilchap  /*
350162abd3562d7b08ab36569800d757b52739b9249danilchap      For audio we use a fix 5 sec interval
351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
352162abd3562d7b08ab36569800d757b52739b9249danilchap      For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
353162abd3562d7b08ab36569800d757b52739b9249danilchap          technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
354162abd3562d7b08ab36569800d757b52739b9249danilchap          that should be extremely rare
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
356470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
357162abd3562d7b08ab36569800d757b52739b9249danilchap  From RFC 3550
358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
359162abd3562d7b08ab36569800d757b52739b9249danilchap      MAX RTCP BW is 5% if the session BW
360162abd3562d7b08ab36569800d757b52739b9249danilchap          A send report is approximately 65 bytes inc CNAME
361162abd3562d7b08ab36569800d757b52739b9249danilchap          A receiver report is approximately 28 bytes
362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
363162abd3562d7b08ab36569800d757b52739b9249danilchap      The RECOMMENDED value for the reduced minimum in seconds is 360
364162abd3562d7b08ab36569800d757b52739b9249danilchap        divided by the session bandwidth in kilobits/second.  This minimum
365162abd3562d7b08ab36569800d757b52739b9249danilchap        is smaller than 5 seconds for bandwidths greater than 72 kb/s.
366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
367162abd3562d7b08ab36569800d757b52739b9249danilchap      If the participant has not yet sent an RTCP packet (the variable
368162abd3562d7b08ab36569800d757b52739b9249danilchap        initial is true), the constant Tmin is set to 2.5 seconds, else it
369162abd3562d7b08ab36569800d757b52739b9249danilchap        is set to 5 seconds.
370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
371162abd3562d7b08ab36569800d757b52739b9249danilchap      The interval between RTCP packets is varied randomly over the
372162abd3562d7b08ab36569800d757b52739b9249danilchap        range [0.5,1.5] times the calculated interval to avoid unintended
373162abd3562d7b08ab36569800d757b52739b9249danilchap        synchronization of all participants
374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
375162abd3562d7b08ab36569800d757b52739b9249danilchap      if we send
376162abd3562d7b08ab36569800d757b52739b9249danilchap      If the participant is a sender (we_sent true), the constant C is
377162abd3562d7b08ab36569800d757b52739b9249danilchap        set to the average RTCP packet size (avg_rtcp_size) divided by 25%
378162abd3562d7b08ab36569800d757b52739b9249danilchap        of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
379162abd3562d7b08ab36569800d757b52739b9249danilchap        number of senders.
380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
381162abd3562d7b08ab36569800d757b52739b9249danilchap      if we receive only
382162abd3562d7b08ab36569800d757b52739b9249danilchap        If we_sent is not true, the constant C is set
383162abd3562d7b08ab36569800d757b52739b9249danilchap        to the average RTCP packet size divided by 75% of the RTCP
384162abd3562d7b08ab36569800d757b52739b9249danilchap        bandwidth.  The constant n is set to the number of receivers
385162abd3562d7b08ab36569800d757b52739b9249danilchap        (members - senders).  If the number of senders is greater than
386162abd3562d7b08ab36569800d757b52739b9249danilchap        25%, senders and receivers are treated together.
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
388162abd3562d7b08ab36569800d757b52739b9249danilchap      reconsideration NOT required for peer-to-peer
389162abd3562d7b08ab36569800d757b52739b9249danilchap        "timer reconsideration" is
390162abd3562d7b08ab36569800d757b52739b9249danilchap        employed.  This algorithm implements a simple back-off mechanism
391162abd3562d7b08ab36569800d757b52739b9249danilchap        which causes users to hold back RTCP packet transmission if the
392162abd3562d7b08ab36569800d757b52739b9249danilchap        group sizes are increasing.
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
394162abd3562d7b08ab36569800d757b52739b9249danilchap        n = number of members
395162abd3562d7b08ab36569800d757b52739b9249danilchap        C = avg_size/(rtcpBW/4)
396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
397162abd3562d7b08ab36569800d757b52739b9249danilchap     3. The deterministic calculated interval Td is set to max(Tmin, n*C).
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
399162abd3562d7b08ab36569800d757b52739b9249danilchap     4. The calculated interval T is set to a number uniformly distributed
400162abd3562d7b08ab36569800d757b52739b9249danilchap        between 0.5 and 1.5 times the deterministic calculated interval.
401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
402162abd3562d7b08ab36569800d757b52739b9249danilchap     5. The resulting value of T is divided by e-3/2=1.21828 to compensate
403162abd3562d7b08ab36569800d757b52739b9249danilchap        for the fact that the timer reconsideration algorithm converges to
404162abd3562d7b08ab36569800d757b52739b9249danilchap        a value of the RTCP bandwidth below the intended average
405162abd3562d7b08ab36569800d757b52739b9249danilchap  */
406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
407242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  int64_t now = clock_->TimeInMilliseconds();
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
409242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
411da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos  if (method_ == RtcpMode::kOff)
412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return false;
413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
414242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (!audio_ && sendKeyframeBeforeRTP) {
41561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // for video key-frames we want to send the RTCP before the large key-frame
41661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // if we have a 100 ms margin
41761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
41861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
420242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (now >= next_time_to_send_rtcp_) {
42161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return true;
42261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  } else if (now < 0x0000ffff &&
423242e22b055940be70b1df3031e2363b0d02397b2Erik Språng             next_time_to_send_rtcp_ > 0xffff0000) {  // 65 sec margin
42461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // wrap
42561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return true;
42661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
42761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return false;
428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
43016825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
431242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
43261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
43361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // This is only saved when we are the sender
434242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if ((last_send_report_[0] == 0) || (sendReport == 0)) {
43561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return 0;  // will be ignored
43661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  } else {
43761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
438242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      if (last_send_report_[i] == sendReport)
439242e22b055940be70b1df3031e2363b0d02397b2Erik Språng        return last_rtcp_time_[i];
440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
44161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
44261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return 0;
443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4458469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.orgbool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
4468469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org                                      int64_t* time_ms) const {
447242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
4488469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
4498469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  if (last_xr_rr_.empty()) {
4508469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org    return false;
4518469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  }
4528469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
4538469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  if (it == last_xr_rr_.end()) {
4548469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org    return false;
4558469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  }
4568469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  *time_ms = it->second;
4578469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  return true;
4588469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org}
4598469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
460f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
46161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
46261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    // shift old
463242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    last_send_report_[i + 1] = last_send_report_[i];
464242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    last_rtcp_time_[i + 1] = last_rtcp_time_[i];
46561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
467f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_);
468f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16);
469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
47061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // The timestamp of this RTCP packet should be estimated as the timestamp of
47161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // the frame being captured at this moment. We are calculating that
47261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // timestamp as the last frame's timestamp + the time since the last frame
47361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // was captured.
474bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  uint32_t rtp_timestamp =
475bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng      start_timestamp_ + last_rtp_timestamp_ +
476bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng      (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
477f7c5776d4254e31e51107388a05c66d14108a8afErik Språng          (ctx.feedback_state_.frequency_hz / 1000);
478bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng
479f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::SenderReport* report = new rtcp::SenderReport();
480f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->From(ssrc_);
481f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->WithNtpSec(ctx.ntp_sec_);
482f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->WithNtpFrac(ctx.ntp_frac_);
483f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->WithRtpTimestamp(rtp_timestamp);
484f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->WithPacketCount(ctx.feedback_state_.packets_sent);
485f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->WithOctetCount(ctx.feedback_state_.media_bytes_sent);
486bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng
487bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  for (auto it : report_blocks_)
488f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    report->WithReportBlock(it.second);
489242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
490bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  report_blocks_.clear();
491f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
492f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::SenderReport>(report);
49361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng}
494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
495f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
496f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
4970ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  size_t length_cname = cname_.length();
49891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
500f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Sdes* sdes = new rtcp::Sdes();
501f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  sdes->WithCName(ssrc_, cname_);
502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5030ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  for (const auto it : csrc_cnames_)
504f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    sdes->WithCName(it.first, it.second);
505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
506f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Sdes>(sdes);
507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
509f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
510f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
511f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  report->From(ssrc_);
512bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  for (auto it : report_blocks_)
513f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    report->WithReportBlock(it.second);
51461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
515bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  report_blocks_.clear();
516f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::ReceiverReport>(report);
517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
519f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
520f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Pli* pli = new rtcp::Pli();
521f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  pli->From(ssrc_);
522f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  pli->To(remote_ssrc_);
523242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
524242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
525242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                       "RTCPSender::PLI");
526242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  ++packet_type_counter_.pli_packets;
527242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
528242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                    ssrc_, packet_type_counter_.pli_packets);
529242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
530f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Pli>(pli);
531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
533f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
534f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  if (!ctx.repeat_)
53562dae190985454188de112e35a16e35fc6e912a4sprang    ++sequence_number_fir_;  // Do not increase if repetition.
536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
537f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Fir* fir = new rtcp::Fir();
538f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  fir->From(ssrc_);
539f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  fir->To(remote_ssrc_);
540f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  fir->WithCommandSeqNum(sequence_number_fir_);
541242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
542242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
543242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                       "RTCPSender::FIR");
544242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  ++packet_type_counter_.fir_packets;
545242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
546242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                    ssrc_, packet_type_counter_.fir_packets);
547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
548f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Fir>(fir);
549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0                   1                   2                   3
553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   |            First        |        Number           | PictureID |
556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
558f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
559f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Sli* sli = new rtcp::Sli();
560f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  sli->From(ssrc_);
561f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  sli->To(remote_ssrc_);
5620365a27f56aa2d2376d2f356bf70d161c3450244sprang  // Crop picture id to 6 least significant bits.
563f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  sli->WithPictureId(ctx.picture_id_ & 0x3F);
564242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
565f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Sli>(sli);
566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0                   1                   2                   3
570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   |      PB       |0| Payload Type|    Native RPSI bit string     |
573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   |   defined per codec          ...                | Padding (0) |
575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*    Note: not generic made for VP8
579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
580f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
581f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
582f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  if (ctx.feedback_state_.send_payload_type == 0xFF)
583f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    return nullptr;
584242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
585f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Rpsi* rpsi = new rtcp::Rpsi();
586f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rpsi->From(ssrc_);
587f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rpsi->To(remote_ssrc_);
588f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type);
589f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rpsi->WithPictureId(ctx.picture_id_);
59061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
591f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Rpsi>(rpsi);
592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
594f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
595f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
596f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Remb* remb = new rtcp::Remb();
597f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  remb->From(ssrc_);
598dd4edc5813a0331049f53a93ac2404a8899e6ae8sprang  for (uint32_t ssrc : remb_ssrcs_)
599f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    remb->AppliesTo(ssrc);
600f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  remb->WithBitrateBps(remb_bitrate_);
601141c5951f4beda868797c2746002a4b1b267ab2asprang
602242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
603242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                       "RTCPSender::REMB");
604242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
605f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Remb>(remb);
606741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org}
607741da942ecb5b449d71f66aed5d991535b374188pwestin@webrtc.org
60861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngvoid RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
609242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
610242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  tmmbr_send_ = target_bitrate / 1000;
611117c119501e3ed80d12b18979959357e8bf2ba61mflodman@webrtc.org}
612117c119501e3ed80d12b18979959357e8bf2ba61mflodman@webrtc.org
613f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
614f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
615f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  if (ctx.feedback_state_.module == nullptr)
616f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    return nullptr;
61761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // Before sending the TMMBR check the received TMMBN, only an owner is
61861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // allowed to raise the bitrate:
61961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // * If the sender is an owner of the TMMBN -> send TMMBR
62061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
62161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
62261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // get current bounding set from RTCP receiver
62361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  bool tmmbrOwner = false;
62461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // store in candidateSet, allocates one extra slot
625242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
62661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
627242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
628242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
62961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // since RTCPreceiver is not doing the reverse we should be fine
63061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  int32_t lengthOfBoundingSet =
6316db6cdc604f9a866991ecf8454eb7f7aa69918eadanilchap      ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet);
63261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
63361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  if (lengthOfBoundingSet > 0) {
63461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
635242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
636242e22b055940be70b1df3031e2363b0d02397b2Erik Språng          candidateSet->PacketOH(i) == packet_oh_send_) {
637f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        // Do not send the same tuple.
638f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        return nullptr;
63961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      }
640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
64161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    if (!tmmbrOwner) {
64261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      // use received bounding set as candidate set
64361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      // add current tuple
644242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
645242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                             ssrc_);
64661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      int numCandidates = lengthOfBoundingSet + 1;
64761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
64861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      // find bounding set
649f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      TMMBRSet* boundingSet = nullptr;
650242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
65161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
652242e22b055940be70b1df3031e2363b0d02397b2Erik Språng        tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
65361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      if (!tmmbrOwner) {
654f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        // Did not enter bounding set, no meaning to send this request.
655f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        return nullptr;
65661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      }
657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
65861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
660f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  if (!tmmbr_send_)
661f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    return nullptr;
66281a3e60c639b5b05486acd1fb84e376271e50012sprang
663f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
664f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  tmmbr->From(ssrc_);
665f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  tmmbr->To(remote_ssrc_);
666f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  tmmbr->WithBitrateKbps(tmmbr_send_);
667f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  tmmbr->WithOverhead(packet_oh_send_);
668f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
669f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr);
670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
672f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
673f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
674242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
675f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  if (boundingSet == nullptr)
676f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    return nullptr;
67761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
678f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
679f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  tmmbn->From(ssrc_);
680d83df50e95a73859bee1568ec7375ff832e1d628sprang  for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
681d83df50e95a73859bee1568ec7375ff832e1d628sprang    if (boundingSet->Tmmbr(i) > 0) {
682f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
683f7c5776d4254e31e51107388a05c66d14108a8afErik Språng                       boundingSet->PacketOH(i));
684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
68561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
686d83df50e95a73859bee1568ec7375ff832e1d628sprang
687f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn);
68861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng}
689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
690f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
691f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::App* app = new rtcp::App();
692f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  app->From(ssrc_);
693f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  app->WithSubType(app_sub_type_);
694f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  app->WithName(app_name_);
695f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  app->WithData(app_data_.get(), app_length_);
696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
697f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::App>(app);
698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
700f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
701f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
702f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Nack* nack = new rtcp::Nack();
703f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  nack->From(ssrc_);
704f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  nack->To(remote_ssrc_);
705f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  nack->WithList(ctx.nack_list_, ctx.nack_size_);
7062dd3134e50f884f6a9e16fb643b2a8f2f6920c1dasapersson@webrtc.org
70761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  // Report stats.
70861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  NACKStringBuilder stringBuilder;
709f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  for (int idx = 0; idx < ctx.nack_size_; ++idx) {
710f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    stringBuilder.PushNACK(ctx.nack_list_[idx]);
711f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    nack_stats_.ReportRequest(ctx.nack_list_[idx]);
71261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
71361be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  packet_type_counter_.nack_requests = nack_stats_.requests();
71461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
715242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
716242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
717242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                       "RTCPSender::NACK", "nacks",
718242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                       TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
719242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  ++packet_type_counter_.nack_packets;
720242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
721242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                    ssrc_, packet_type_counter_.nack_packets);
722242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
723f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Nack>(nack);
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
726f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
727f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Bye* bye = new rtcp::Bye();
728f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  bye->From(ssrc_);
729d8ee4f99154691752dd8d2f2d70750554dca7ca7sprang  for (uint32_t csrc : csrcs_)
730f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    bye->WithCsrc(csrc);
731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
732f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Bye>(bye);
733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
735f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime(
736f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
73761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
7388469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org    last_xr_rr_.erase(last_xr_rr_.begin());
7398469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org  last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
740f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_),
741f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_)));
7428469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
743f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Xr* xr = new rtcp::Xr();
744f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->From(ssrc_);
7458469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
746ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  rtcp::Rrtr rrtr;
747fc47ed6c0524d7ee0bc7947f0ad65fcefda34a29Danil Chapovalov  rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_));
7488469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
749f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->WithRrtr(&rrtr);
750ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng
751ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
752ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng
753f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Xr>(xr);
7548469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org}
7558469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
756f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr(
757f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& ctx) {
758f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Xr* xr = new rtcp::Xr();
759f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->From(ssrc_);
7608469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
761ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  rtcp::Dlrr dlrr;
762f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr;
763ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
7648469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
765f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->WithDlrr(&dlrr);
7668469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
767f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Xr>(xr);
7688469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org}
7698469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
770242e22b055940be70b1df3031e2363b0d02397b2Erik Språng// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
771f7c5776d4254e31e51107388a05c66d14108a8afErik Språngrtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric(
772f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const RtcpContext& context) {
773f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  rtcp::Xr* xr = new rtcp::Xr();
774f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->From(ssrc_);
775ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng
776ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  rtcp::VoipMetric voip;
777ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng  voip.To(remote_ssrc_);
77891941ae493cb37a4e1250c7d3aad1c7394b5850edanilchap  voip.WithVoipMetric(xr_voip_metric_);
779ca28fdcf9f061193671ef71c492ad3cd8c193a59Erik Språng
780f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  xr->WithVoipMetric(&voip);
781242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
782f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return rtc::scoped_ptr<rtcp::Xr>(xr);
783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
78559f20bb735562d245357609799578edeed46be32pbos@webrtc.orgint32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
786242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                             RTCPPacketType packetType,
787242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                             int32_t nack_size,
788242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                             const uint16_t* nack_list,
78959f20bb735562d245357609799578edeed46be32pbos@webrtc.org                             bool repeat,
79059f20bb735562d245357609799578edeed46be32pbos@webrtc.org                             uint64_t pictureID) {
791242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return SendCompoundRTCP(
792242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
793242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      nack_size, nack_list, repeat, pictureID);
794242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
795242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
796242e22b055940be70b1df3031e2363b0d02397b2Erik Språngint32_t RTCPSender::SendCompoundRTCP(
797242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    const FeedbackState& feedback_state,
798f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    const std::set<RTCPPacketType>& packet_types,
799242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    int32_t nack_size,
800242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    const uint16_t* nack_list,
801242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    bool repeat,
802242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    uint64_t pictureID) {
803f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  PacketContainer container(transport_);
804286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  {
805242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
806da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos    if (method_ == RtcpMode::kOff) {
80761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
80861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      return -1;
809286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    }
81061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
811f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    // We need to send our NTP even if we haven't received any reports.
812f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    uint32_t ntp_sec;
813f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    uint32_t ntp_frac;
814f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    clock_->CurrentNtp(ntp_sec, ntp_frac);
815f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
816f7c5776d4254e31e51107388a05c66d14108a8afErik Språng                        ntp_sec, ntp_frac, &container);
817f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
818f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    PrepareReport(packet_types, feedback_state);
819f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
820f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    auto it = report_flags_.begin();
821f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    while (it != report_flags_.end()) {
822f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      auto builder_it = builders_.find(it->type);
823f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      RTC_DCHECK(builder_it != builders_.end());
824f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      if (it->is_volatile) {
825f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        report_flags_.erase(it++);
826f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      } else {
827f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        ++it;
828f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      }
82961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
830f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      BuilderFunc func = builder_it->second;
831f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
832f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      if (packet.get() == nullptr)
833f7c5776d4254e31e51107388a05c66d14108a8afErik Språng        return -1;
834f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      container.Append(packet.release());
835f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    }
836a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org
837f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    if (packet_type_counter_observer_ != nullptr) {
838f7c5776d4254e31e51107388a05c66d14108a8afErik Språng      packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
839f7c5776d4254e31e51107388a05c66d14108a8afErik Språng          remote_ssrc_, packet_type_counter_);
840f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    }
841242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
842f7c5776d4254e31e51107388a05c66d14108a8afErik Språng    RTC_DCHECK(AllVolatileFlagsConsumed());
843f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  }
844f7c5776d4254e31e51107388a05c66d14108a8afErik Språng
845f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  size_t bytes_sent = container.SendPackets();
846f7c5776d4254e31e51107388a05c66d14108a8afErik Språng  return bytes_sent == 0 ? -1 : 0;
847f7c5776d4254e31e51107388a05c66d14108a8afErik Språng}
848a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org
849f7c5776d4254e31e51107388a05c66d14108a8afErik Språngvoid RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes,
850f7c5776d4254e31e51107388a05c66d14108a8afErik Språng                               const FeedbackState& feedback_state) {
851242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  // Add all flags as volatile. Non volatile entries will not be overwritten
852242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  // and all new volatile flags added will be consumed by the end of this call.
853242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  SetFlags(packetTypes, true);
854a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org
85561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  if (packet_type_counter_.first_packet_time_ms == -1)
856242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
85761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
858242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  bool generate_report;
859242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
860242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    // Report type already explicitly set, don't automatically populate.
861242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    generate_report = true;
86291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
863242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  } else {
864242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    generate_report =
865da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos        (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
866da903eaabbb6c6830efcafc3c2ade1d36f511e43pbos        method_ == RtcpMode::kCompound;
867242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    if (generate_report)
868242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
869286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  }
870242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
8710ea42d319e2a18785f5de5fe8d52e0a7a5fd1448Erik Språng  if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
872242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    SetFlag(kRtcpSdes, true);
873242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
874242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (generate_report) {
875242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    if (!sending_ && xr_send_receiver_reference_time_enabled_)
876242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      SetFlag(kRtcpXrReceiverReferenceTime, true);
87761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    if (feedback_state.has_last_xr_rr)
878242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      SetFlag(kRtcpXrDlrrReportBlock, true);
879242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
880242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    // generate next time to send an RTCP report
88147a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap    uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
88247a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap
88347a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap    if (!audio_) {
884242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      if (sending_) {
88561be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
88661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
88761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        if (send_bitrate_kbit != 0)
88861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng          minIntervalMs = 360000 / send_bitrate_kbit;
889286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org      }
89061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng      if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
89161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng        minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
89261be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    }
89347a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap    // The interval between RTCP packets is varied randomly over the
89447a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap    // range [1/2,3/2] times the calculated interval.
89547a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap    uint32_t timeToNext =
89647a740bc5e36bcaf19385f9d4c0afb0cad070a05danilchap        random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
897242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
898a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org
899286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    StatisticianMap statisticians =
900286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org        receive_statistics_->GetActiveStatisticians();
901a72e7349d52366655076e609e9e32d456da7f5a2danilchap    RTC_DCHECK(report_blocks_.empty());
902a72e7349d52366655076e609e9e32d456da7f5a2danilchap    for (auto& it : statisticians) {
903a72e7349d52366655076e609e9e32d456da7f5a2danilchap      AddReportBlock(feedback_state, it.first, it.second);
904286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    }
905286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  }
906286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org}
907a0218a84d17a727111e2e24cf5af915b1b91c06ehenrike@webrtc.org
908a72e7349d52366655076e609e9e32d456da7f5a2danilchapbool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
909a72e7349d52366655076e609e9e32d456da7f5a2danilchap                                uint32_t ssrc,
910a72e7349d52366655076e609e9e32d456da7f5a2danilchap                                StreamStatistician* statistician) {
911286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  // Do we have receive statistics to send?
91254ae4ffb9e235a9742e2b11298327e02d870571csprang@webrtc.org  RtcpStatistics stats;
913286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  if (!statistician->GetStatistics(&stats, true))
914286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org    return false;
915a72e7349d52366655076e609e9e32d456da7f5a2danilchap
916a72e7349d52366655076e609e9e32d456da7f5a2danilchap  if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
917a72e7349d52366655076e609e9e32d456da7f5a2danilchap    LOG(LS_WARNING) << "Too many report blocks.";
918a72e7349d52366655076e609e9e32d456da7f5a2danilchap    return false;
919a72e7349d52366655076e609e9e32d456da7f5a2danilchap  }
920a72e7349d52366655076e609e9e32d456da7f5a2danilchap  RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
921a72e7349d52366655076e609e9e32d456da7f5a2danilchap  rtcp::ReportBlock* block = &report_blocks_[ssrc];
922a72e7349d52366655076e609e9e32d456da7f5a2danilchap  block->To(ssrc);
923a72e7349d52366655076e609e9e32d456da7f5a2danilchap  block->WithFractionLost(stats.fraction_lost);
924a72e7349d52366655076e609e9e32d456da7f5a2danilchap  if (!block->WithCumulativeLost(stats.cumulative_lost)) {
925a72e7349d52366655076e609e9e32d456da7f5a2danilchap    report_blocks_.erase(ssrc);
926a72e7349d52366655076e609e9e32d456da7f5a2danilchap    LOG(LS_WARNING) << "Cumulative lost is oversized.";
927a72e7349d52366655076e609e9e32d456da7f5a2danilchap    return false;
928a72e7349d52366655076e609e9e32d456da7f5a2danilchap  }
929a72e7349d52366655076e609e9e32d456da7f5a2danilchap  block->WithExtHighestSeqNum(stats.extended_max_sequence_number);
930a72e7349d52366655076e609e9e32d456da7f5a2danilchap  block->WithJitter(stats.jitter);
931a72e7349d52366655076e609e9e32d456da7f5a2danilchap  block->WithLastSr(feedback_state.remote_sr);
932286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org
933bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  // TODO(sprang): Do we really need separate time stamps for each report?
934bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  // Get our NTP as late as possible to avoid a race.
935bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  uint32_t ntp_secs;
936bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  uint32_t ntp_frac;
937bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  clock_->CurrentNtp(ntp_secs, ntp_frac);
938286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org
939bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng  // Delay since last received report.
94059f20bb735562d245357609799578edeed46be32pbos@webrtc.org  if ((feedback_state.last_rr_ntp_secs != 0) ||
94159f20bb735562d245357609799578edeed46be32pbos@webrtc.org      (feedback_state.last_rr_ntp_frac != 0)) {
942bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng    // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
943bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng    uint32_t now = ntp_secs & 0x0000FFFF;
94461be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    now <<= 16;
945bdc0b0d869e9a14bbfafcbb84e294a13383e6fa6Erik Språng    now += (ntp_frac & 0xffff0000) >> 16;
946286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org
94761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
94861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    receiveTime <<= 16;
94961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
950286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org
951a72e7349d52366655076e609e9e32d456da7f5a2danilchap    block->WithDelayLastSr(now - receiveTime);
952286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  }
953286fe0b04d97205ac84688bbe613d5749192b2d1stefan@webrtc.org  return true;
954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9569334ac2d78f760b37f512ef6c12bff220d1654c1pbos@webrtc.orgvoid RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
9579334ac2d78f760b37f512ef6c12bff220d1654c1pbos@webrtc.org  assert(csrcs.size() <= kRtpCsrcSize);
958242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
9599334ac2d78f760b37f512ef6c12bff220d1654c1pbos@webrtc.org  csrcs_ = csrcs;
960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
962d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
963d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                               uint32_t name,
964d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                               const uint8_t* data,
965d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                               uint16_t length) {
96661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  if (length % 4 != 0) {
96761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
96861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return -1;
96961be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
970242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
971242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
972242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  SetFlag(kRtcpApp, true);
973242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  app_sub_type_ = subType;
974242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  app_name_ = name;
975242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  app_data_.reset(new uint8_t[length]);
976242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  app_length_ = length;
977242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  memcpy(app_data_.get(), data, length);
97861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return 0;
979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
98161be2a401635eed1d13c169dc104b9ff4a2f477bErik Språngint32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
982242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
983242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
985242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  SetFlag(kRtcpXrVoipMetric, true);
98661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return 0;
987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9898469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.orgvoid RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
990242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
991242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  xr_send_receiver_reference_time_enabled_ = enable;
9928469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org}
9938469f7b328ec980f80fa79931b4e07872d0feb23asapersson@webrtc.org
9948d02f5dc7146ebc35c30fc3f7e1cbfa6802486a2asapersson@webrtc.orgbool RTCPSender::RtcpXrReceiverReferenceTime() const {
995242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
996242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return xr_send_receiver_reference_time_enabled_;
9978d02f5dc7146ebc35c30fc3f7e1cbfa6802486a2asapersson@webrtc.org}
9988d02f5dc7146ebc35c30fc3f7e1cbfa6802486a2asapersson@webrtc.org
999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com// no callbacks allowed inside this function
1000d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.orgint32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1001d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                             uint32_t maxBitrateKbit) {
1002242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1004242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1005242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    SetFlag(kRtcpTmmbn, true);
100661be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng    return 0;
100761be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  }
100861be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng  return -1;
1009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
101061be2a401635eed1d13c169dc104b9ff4a2f477bErik Språng
1011242e22b055940be70b1df3031e2363b0d02397b2Erik Språngvoid RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1012242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  report_flags_.insert(ReportFlag(type, is_volatile));
1013242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
1014242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
1015242e22b055940be70b1df3031e2363b0d02397b2Erik Språngvoid RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1016242e22b055940be70b1df3031e2363b0d02397b2Erik Språng                          bool is_volatile) {
1017242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  for (RTCPPacketType type : types)
1018242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    SetFlag(type, is_volatile);
1019242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
1020242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
1021242e22b055940be70b1df3031e2363b0d02397b2Erik Språngbool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1022242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1023242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
1024242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
1025242e22b055940be70b1df3031e2363b0d02397b2Erik Språngbool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1026242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  auto it = report_flags_.find(ReportFlag(type, false));
1027242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (it == report_flags_.end())
1028242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    return false;
1029242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  if (it->is_volatile || forced)
1030242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    report_flags_.erase((it));
1031242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return true;
1032242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
1033242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
1034242e22b055940be70b1df3031e2363b0d02397b2Erik Språngbool RTCPSender::AllVolatileFlagsConsumed() const {
1035242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  for (const ReportFlag& flag : report_flags_) {
1036242e22b055940be70b1df3031e2363b0d02397b2Erik Språng    if (flag.is_volatile)
1037242e22b055940be70b1df3031e2363b0d02397b2Erik Språng      return false;
1038242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  }
1039242e22b055940be70b1df3031e2363b0d02397b2Erik Språng  return true;
1040242e22b055940be70b1df3031e2363b0d02397b2Erik Språng}
1041242e22b055940be70b1df3031e2363b0d02397b2Erik Språng
1042233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprangbool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
1043233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang  class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1044233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang   public:
10456db6cdc604f9a866991ecf8454eb7f7aa69918eadanilchap    explicit Sender(Transport* transport)
1046ac547a653862744d0aae560713f8418ad2852085Peter Boström        : transport_(transport), send_failure_(false) {}
1047233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang
1048233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang    void OnPacketReady(uint8_t* data, size_t length) override {
10492d566686a23fe93ada58f1c38a0d4b9a0d68556epbos      if (!transport_->SendRtcp(data, length))
1050233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang        send_failure_ = true;
1051233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang    }
1052233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang
1053233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang    Transport* const transport_;
1054233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang    bool send_failure_;
105586fd9ed6f9e2a38aa343db8c62764659633231fasprang  } sender(transport_);
1056233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang
1057233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang  uint8_t buffer[IP_PACKET_SIZE];
1058233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang  return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1059233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang         !sender.send_failure_;
1060233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang}
1061233bd87d45bbeeec50d7687e7d98c1cfc7f65562sprang
1062d900e8bea84c474696bf0219aed1353ce65ffd8epbos@webrtc.org}  // namespace webrtc
1063