congestion_controller.cc revision 867fb5224e1ba6a1c2cd523c005499a93ed61a08
19ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org/*
29ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
39ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *
49ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  Use of this source code is governed by a BSD-style license
59ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  that can be found in the LICENSE file in the root of the source
69ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  tree. An additional intellectual property rights grant can be found
79ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  in the file PATENTS.  All contributing project authors may
89ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
99ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org */
109ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org
1129b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/vie_channel_group.h"
129ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org
13a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org#include "webrtc/base/checks.h"
1438344ed2806c8fed60d67d280ca44c32e36707c0pbos@webrtc.org#include "webrtc/base/thread_annotations.h"
1529b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/common.h"
16e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer#include "webrtc/modules/pacing/include/paced_sender.h"
17e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer#include "webrtc/modules/pacing/include/packet_router.h"
18867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h"
19468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h"
20468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
2129b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
2229b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/modules/utility/interface/process_thread.h"
23a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
245574dacd1f83d8ac83458d27e54be6507f3a06a4mflodman@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
2529b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/call_stats.h"
2629b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/encoder_state_feedback.h"
27a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org#include "webrtc/video_engine/payload_router.h"
2829b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/vie_channel.h"
2929b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/vie_encoder.h"
3029b2219914a059fe5164c312e7cc6d1bf0b4e610andresp@webrtc.org#include "webrtc/video_engine/vie_remb.h"
31a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org#include "webrtc/voice_engine/include/voe_video_sync.h"
329ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org
339ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.orgnamespace webrtc {
34a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.orgnamespace {
35a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
365ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.orgstatic const uint32_t kTimeOffsetSwitchThreshold = 30;
37ef35f069e739feaae16fdfcc815d7af5cb05e9aepbosstatic const uint32_t kMinBitrateBps = 30000;
385ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org
39a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.orgclass WrappingBitrateEstimator : public RemoteBitrateEstimator {
40a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org public:
41ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos  WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock)
42a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org      : observer_(observer),
43a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org        clock_(clock),
44a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org        crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
45ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos        min_bitrate_bps_(kMinBitrateBps),
46468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng        rbe_(new RemoteBitrateEstimatorSingleStream(observer_,
47a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org                                                    clock_,
48e9abd591d73218e11a8bd3e7c72d4d7af9a3cea8henrik.lundin@webrtc.org                                                    min_bitrate_bps_)),
495ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org        using_absolute_send_time_(false),
50468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng        packets_since_absolute_send_time_(0) {}
51a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
521295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org  virtual ~WrappingBitrateEstimator() {}
531295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org
5414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void IncomingPacket(int64_t arrival_time_ms,
5514665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org                      size_t payload_size,
56ff4ea9310e981da6292fb044cff9eeefd986cf2bStefan Holmer                      const RTPHeader& header,
57ff4ea9310e981da6292fb044cff9eeefd986cf2bStefan Holmer                      bool was_paced) override {
58a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
59a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org    PickEstimatorFromHeader(header);
60ff4ea9310e981da6292fb044cff9eeefd986cf2bStefan Holmer    rbe_->IncomingPacket(arrival_time_ms, payload_size, header, was_paced);
61a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
62a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
6314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int32_t Process() override {
641295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
651295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org    return rbe_->Process();
66a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
67a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
6814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  int64_t TimeUntilNextProcess() override {
691295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
701295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org    return rbe_->TimeUntilNextProcess();
71a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
72a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
7314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void OnRttUpdate(int64_t rtt) override {
74a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
75a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    rbe_->OnRttUpdate(rtt);
76a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
77a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
7814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  void RemoveStream(unsigned int ssrc) override {
79a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
80a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    rbe_->RemoveStream(ssrc);
81a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
82a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
8314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool LatestEstimate(std::vector<unsigned int>* ssrcs,
8414665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org                      unsigned int* bitrate_bps) const override {
85a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
86a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org    return rbe_->LatestEstimate(ssrcs, bitrate_bps);
87a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  }
88a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
8914665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org  bool GetStats(ReceiveBandwidthEstimatorStats* output) const override {
901f64f067840212b3e5b67a0d6a50bcd805b5bc1ajiayl@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
911f64f067840212b3e5b67a0d6a50bcd805b5bc1ajiayl@webrtc.org    return rbe_->GetStats(output);
921f64f067840212b3e5b67a0d6a50bcd805b5bc1ajiayl@webrtc.org  }
931f64f067840212b3e5b67a0d6a50bcd805b5bc1ajiayl@webrtc.org
94a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org private:
95a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org  void PickEstimatorFromHeader(const RTPHeader& header)
96a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org      EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) {
975ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    if (header.extension.hasAbsoluteSendTime) {
985ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      // If we see AST in header, switch RBE strategy immediately.
995ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      if (!using_absolute_send_time_) {
1005574dacd1f83d8ac83458d27e54be6507f3a06a4mflodman@webrtc.org        LOG(LS_INFO) <<
1015574dacd1f83d8ac83458d27e54be6507f3a06a4mflodman@webrtc.org            "WrappingBitrateEstimator: Switching to absolute send time RBE.";
1025ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org        using_absolute_send_time_ = true;
103a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org        PickEstimator();
1045ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      }
1055ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      packets_since_absolute_send_time_ = 0;
1065ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    } else {
1075ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      // When we don't see AST, wait for a few packets before going back to TOF.
1085ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      if (using_absolute_send_time_) {
1095ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org        ++packets_since_absolute_send_time_;
1105ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org        if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) {
1115574dacd1f83d8ac83458d27e54be6507f3a06a4mflodman@webrtc.org          LOG(LS_INFO) << "WrappingBitrateEstimator: Switching to transmission "
1125574dacd1f83d8ac83458d27e54be6507f3a06a4mflodman@webrtc.org                       << "time offset RBE.";
1135ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org          using_absolute_send_time_ = false;
114a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org          PickEstimator();
1155ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org        }
1165ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org      }
1175ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org    }
1185ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org  }
1195ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org
120a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org  // Instantiate RBE for Time Offset or Absolute Send Time extensions.
121a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org  void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()) {
122a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org    if (using_absolute_send_time_) {
123468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng      rbe_.reset(new RemoteBitrateEstimatorAbsSendTime(observer_, clock_,
124468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng                                                       min_bitrate_bps_));
125a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org    } else {
126468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng      rbe_.reset(new RemoteBitrateEstimatorSingleStream(observer_, clock_,
127468e62a97426a8d001e9187f3ca1d1e43f80b970Erik Språng                                                        min_bitrate_bps_));
128a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org    }
129a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org  }
130a16147c03726e54b2ecb1e48c7171a33d83a5261stefan@webrtc.org
131a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  RemoteBitrateObserver* observer_;
132a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  Clock* clock_;
13300b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_;
134e9abd591d73218e11a8bd3e7c72d4d7af9a3cea8henrik.lundin@webrtc.org  const uint32_t min_bitrate_bps_;
13500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<RemoteBitrateEstimator> rbe_;
1365ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org  bool using_absolute_send_time_;
1375ab756703ea32f2c2ff9878d6eae628c7380bc14pbos@webrtc.org  uint32_t packets_since_absolute_send_time_;
138a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
139a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org  DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator);
140a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org};
141867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang
142867fb5224e1ba6a1c2cd523c005499a93ed61a08sprangstatic const int64_t kSendTimeHistoryWindowMs = 2000;
143867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang
144a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org}  // namespace
1459ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org
146867fb5224e1ba6a1c2cd523c005499a93ed61a08sprangclass AdaptedSendTimeHistory : public SendTimeHistory, public SendTimeObserver {
147867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang public:
148867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  AdaptedSendTimeHistory() : SendTimeHistory(kSendTimeHistoryWindowMs) {}
149867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  virtual ~AdaptedSendTimeHistory() {}
150867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang
151867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  void OnPacketSent(uint16_t sequence_number, int64_t send_time) override {
152867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang    SendTimeHistory::AddAndRemoveOldSendTimes(sequence_number, send_time);
153867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang  }
154867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang};
155867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang
1562251d6e17438e1a085ff4f88ad19de513214bec1Peter BoströmChannelGroup::ChannelGroup(ProcessThread* process_thread)
157b5865079868c4dec49571e7aef0aa52124b50c64stefan@webrtc.org    : remb_(new VieRemb()),
158792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org      bitrate_allocator_(new BitrateAllocator()),
1597c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org      call_stats_(new CallStats()),
1607c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org      encoder_state_feedback_(new EncoderStateFeedback()),
161e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      packet_router_(new PacketRouter()),
162e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      pacer_(new PacedSender(Clock::GetRealTimeClock(),
163e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer                             packet_router_.get(),
164e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer                             BitrateController::kDefaultStartBitrateKbps,
165e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer                             PacedSender::kDefaultPaceMultiplier *
166e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer                                 BitrateController::kDefaultStartBitrateKbps,
167e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer                             0)),
168e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      process_thread_(process_thread),
169e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      pacer_thread_(ProcessThread::Create()),
170e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      // Constructed last as this object calls the provided callback on
171e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      // construction.
172e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      bitrate_controller_(
173e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer          BitrateController::CreateBitrateController(Clock::GetRealTimeClock(),
174867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang                                                     this)),
175867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      send_time_history_(new AdaptedSendTimeHistory()) {
1762251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström  remote_bitrate_estimator_.reset(new WrappingBitrateEstimator(
177ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos      remb_.get(), Clock::GetRealTimeClock()));
1781295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org
1791295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org  call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
18044caf01c34d4fddec039f917c83fed7e0ce977b2andresp@webrtc.org
181e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  pacer_thread_->RegisterModule(pacer_.get());
182e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  pacer_thread_->Start();
183e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer
1841295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org  process_thread->RegisterModule(remote_bitrate_estimator_.get());
1857c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org  process_thread->RegisterModule(call_stats_.get());
18644caf01c34d4fddec039f917c83fed7e0ce977b2andresp@webrtc.org  process_thread->RegisterModule(bitrate_controller_.get());
18749888ce42858e308c7b0575697f06e2483a34daepwestin@webrtc.org}
1889ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org
1899ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.orgChannelGroup::~ChannelGroup() {
190e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  pacer_thread_->Stop();
191e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  pacer_thread_->DeRegisterModule(pacer_.get());
19244caf01c34d4fddec039f917c83fed7e0ce977b2andresp@webrtc.org  process_thread_->DeRegisterModule(bitrate_controller_.get());
1936cd201cf31dc8e50bf815139b0c9fdc83d3ba2bfandrew@webrtc.org  process_thread_->DeRegisterModule(call_stats_.get());
1941295dc6a237a7c2d2cb0dbfd53c57babf1034901andresp@webrtc.org  process_thread_->DeRegisterModule(remote_bitrate_estimator_.get());
19544caf01c34d4fddec039f917c83fed7e0ce977b2andresp@webrtc.org  call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
196a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  DCHECK(channel_map_.empty());
197a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  DCHECK(!remb_->InUse());
198a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  DCHECK(vie_encoder_map_.empty());
199a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
200a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
201a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgbool ChannelGroup::CreateSendChannel(int channel_id,
202a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                     int engine_id,
2032251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström                                     Transport* transport,
2045a3ebd761cb2789aa63e4ae7c0035234a3e3b5f3Peter Boström                                     int number_of_cores,
205d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos                                     const std::vector<uint32_t>& ssrcs) {
2068ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos  // TODO(pbos): Remove checks for empty ssrcs and add this check when there's
2078ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos  // no base channel.
2088ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos  // DCHECK(!ssrcs.empty());
209ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos  rtc::scoped_ptr<ViEEncoder> vie_encoder(new ViEEncoder(
210ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos      channel_id, number_of_cores, *process_thread_, pacer_.get(),
211ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos      bitrate_allocator_.get(), bitrate_controller_.get(), false));
212a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  if (!vie_encoder->Init()) {
213a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    return false;
214a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
215a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ViEEncoder* encoder = vie_encoder.get();
2162251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström  if (!CreateChannel(channel_id, engine_id, transport, number_of_cores,
2178ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos                     vie_encoder.release(), ssrcs.empty() ? 1 : ssrcs.size(),
218d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos                     true)) {
219a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    return false;
220a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
221a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ViEChannel* channel = channel_map_[channel_id];
222a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  // Connect the encoder with the send packet router, to enable sending.
223a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  encoder->StartThreadsAndSetSharedMembers(channel->send_payload_router(),
224a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                           channel->vcm_protection_callback());
225a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
2268ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos  if (!ssrcs.empty()) {
2278ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos    encoder_state_feedback_->AddEncoder(ssrcs, encoder);
2288ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos    std::vector<uint32_t> first_ssrc(1, ssrcs[0]);
2298ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos    encoder->SetSsrcs(first_ssrc);
2308ff04d6b3b9a2fc28394ef6ad77201a1443e24c8pbos  }
231a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  return true;
232a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
233a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
234a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgbool ChannelGroup::CreateReceiveChannel(int channel_id,
235a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                        int engine_id,
2362251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström                                        Transport* transport,
237d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos                                        int number_of_cores) {
2382251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström  return CreateChannel(channel_id, engine_id, transport, number_of_cores,
239d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos                       nullptr, 1, false);
240a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
241a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
242a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgbool ChannelGroup::CreateChannel(int channel_id,
243a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                 int engine_id,
2442251d6e17438e1a085ff4f88ad19de513214bec1Peter Boström                                 Transport* transport,
245a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                 int number_of_cores,
246a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org                                 ViEEncoder* vie_encoder,
247d6f1a38165455d743fbe61f6980f22be6a3c4de9Peter Boström                                 size_t max_rtp_streams,
248d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos                                 bool sender) {
249a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  rtc::scoped_ptr<ViEChannel> channel(new ViEChannel(
250ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos      channel_id, engine_id, number_of_cores, transport, process_thread_,
251ef35f069e739feaae16fdfcc815d7af5cb05e9aepbos      encoder_state_feedback_->GetRtcpIntraFrameObserver(),
252a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org      bitrate_controller_->CreateRtcpBandwidthObserver(),
253867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      send_time_history_.get(), remote_bitrate_estimator_.get(),
254867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      call_stats_->rtcp_rtt_stats(), pacer_.get(), packet_router_.get(),
255867fb5224e1ba6a1c2cd523c005499a93ed61a08sprang      max_rtp_streams, sender));
256a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  if (channel->Init() != 0) {
257a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    return false;
258a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
259a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
260a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  // Register the channel to receive stats updates.
261a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  call_stats_->RegisterStatsObserver(channel->GetStatsObserver());
262a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
263a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  // Store the channel, add it to the channel group and save the vie_encoder.
264a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  channel_map_[channel_id] = channel.release();
265d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  if (vie_encoder) {
266d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    rtc::CritScope lock(&encoder_map_crit_);
267e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer    vie_encoder_map_[channel_id] = vie_encoder;
268e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  }
269a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
270a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  return true;
271a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
272a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
273a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgvoid ChannelGroup::DeleteChannel(int channel_id) {
274a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ViEChannel* vie_channel = PopChannel(channel_id);
275a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
276a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ViEEncoder* vie_encoder = GetEncoder(channel_id);
277a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
278a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  call_stats_->DeregisterStatsObserver(vie_channel->GetStatsObserver());
27976c53d36bc455fe89ca1f860d5171633198fe907Peter Boström  SetChannelRembStatus(false, false, vie_channel);
280a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
281d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  // If we're a sender, remove the feedback and stop all encoding threads and
282d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  // processing. This must be done before deleting the channel.
283d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  if (vie_encoder) {
284a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    encoder_state_feedback_->RemoveEncoder(vie_encoder);
285a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    vie_encoder->StopThreadsAndRemoveSharedMembers();
286a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
287a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
288a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  unsigned int remote_ssrc = 0;
289a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  vie_channel->GetRemoteSSRC(&remote_ssrc);
290d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  channel_map_.erase(channel_id);
291a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  remote_bitrate_estimator_->RemoveStream(remote_ssrc);
292a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
293a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  delete vie_channel;
294d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos
295a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  if (vie_encoder) {
296d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    {
297d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos      rtc::CritScope lock(&encoder_map_crit_);
298d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos      vie_encoder_map_.erase(vie_encoder_map_.find(channel_id));
299d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    }
300a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    delete vie_encoder;
301a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
302a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
303a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  LOG(LS_VERBOSE) << "Channel deleted " << channel_id;
3049ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org}
305a6db54d4c9a2bfc703bc208eb5cbc19505e9cef3solenberg@webrtc.org
306a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgViEChannel* ChannelGroup::GetChannel(int channel_id) const {
307a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ChannelMap::const_iterator it = channel_map_.find(channel_id);
308a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  if (it == channel_map_.end()) {
309a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    LOG(LS_ERROR) << "Channel doesn't exist " << channel_id;
310a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    return NULL;
311a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  }
312a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  return it->second;
313a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
314a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
315a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgViEEncoder* ChannelGroup::GetEncoder(int channel_id) const {
316d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  rtc::CritScope lock(&encoder_map_crit_);
317a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  EncoderMap::const_iterator it = vie_encoder_map_.find(channel_id);
318d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  if (it == vie_encoder_map_.end())
319d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    return nullptr;
320a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  return it->second;
321a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
322a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
323a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgViEChannel* ChannelGroup::PopChannel(int channel_id) {
324a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ChannelMap::iterator c_it = channel_map_.find(channel_id);
325a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  DCHECK(c_it != channel_map_.end());
326a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  ViEChannel* channel = c_it->second;
327a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  channel_map_.erase(c_it);
328a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
329a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org  return channel;
330a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org}
331a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org
332a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgvoid ChannelGroup::SetSyncInterface(VoEVideoSync* sync_interface) {
333d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos  for (auto channel : channel_map_)
334a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.org    channel.second->SetVoiceChannel(-1, sync_interface);
335792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org}
336792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org
337a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgBitrateController* ChannelGroup::GetBitrateController() const {
338cb89c6f91491e683e47e5505536c154c905d5194bjornv@webrtc.org  return bitrate_controller_.get();
339f72881406fba86adc2d649bb1caee0d5604f9339stefan@webrtc.org}
340f72881406fba86adc2d649bb1caee0d5604f9339stefan@webrtc.org
341a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgRemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() const {
3429354cc965c04a0c79ea36622043751596a6fd015stefan@webrtc.org  return remote_bitrate_estimator_.get();
3439354cc965c04a0c79ea36622043751596a6fd015stefan@webrtc.org}
3449354cc965c04a0c79ea36622043751596a6fd015stefan@webrtc.org
345a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgCallStats* ChannelGroup::GetCallStats() const {
3467c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org  return call_stats_.get();
3477c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org}
3487c894b7cc718773f32d21985ff33a64f9e13946emflodman@webrtc.org
349a50e6f073deecfd9004e6e4946eabd8c34621608stefan@webrtc.orgEncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() const {
350aca26292aeb35c91e70dd22d5923bf74ce68fa30mflodman@webrtc.org  return encoder_state_feedback_.get();
351aca26292aeb35c91e70dd22d5923bf74ce68fa30mflodman@webrtc.org}
352aca26292aeb35c91e70dd22d5923bf74ce68fa30mflodman@webrtc.org
353e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmerint64_t ChannelGroup::GetPacerQueuingDelayMs() const {
354e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  return pacer_->QueueInMs();
355e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer}
356e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer
35776c53d36bc455fe89ca1f860d5171633198fe907Peter Boströmvoid ChannelGroup::SetChannelRembStatus(bool sender,
358d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                        bool receiver,
359d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org                                        ViEChannel* channel) {
3609ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  // Update the channel state.
361d16e839c6d29831e79312180085b6a19149df43fpbos@webrtc.org  channel->EnableRemb(sender || receiver);
3629354cc965c04a0c79ea36622043751596a6fd015stefan@webrtc.org  // Update the REMB instance with necessary RTP modules.
3639ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  RtpRtcp* rtp_module = channel->rtp_rtcp();
3649ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  if (sender) {
3659ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org    remb_->AddRembSender(rtp_module);
3669ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  } else {
3679ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org    remb_->RemoveRembSender(rtp_module);
3689ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  }
3699ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  if (receiver) {
3709ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org    remb_->AddReceiveChannel(rtp_module);
3719ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  } else {
3729ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org    remb_->RemoveReceiveChannel(rtp_module);
3739ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org  }
3749ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org}
375792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org
376792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.orgvoid ChannelGroup::OnNetworkChanged(uint32_t target_bitrate_bps,
377792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org                                    uint8_t fraction_loss,
378792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org                                    int64_t rtt) {
379792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org  bitrate_allocator_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt);
380e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  int pad_up_to_bitrate_bps = 0;
381e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  {
382d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    rtc::CritScope lock(&encoder_map_crit_);
383d6fc47ea9585fa405d8617ccc0b7704d2c9e8a0apbos    for (const auto& encoder : vie_encoder_map_)
384a4a8d4ad27bd0bd7a6cc5df697951d4531ddb4eestefan      pad_up_to_bitrate_bps += encoder.second->GetPaddingNeededBps();
385e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  }
386e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  pacer_->UpdateBitrate(
387e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      target_bitrate_bps / 1000,
388e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      PacedSender::kDefaultPaceMultiplier * target_bitrate_bps / 1000,
389e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer      pad_up_to_bitrate_bps / 1000);
390792f1a14e2b62382c5c6080d0b8fdc5c89d27bc6stefan@webrtc.org}
3919ec883e8bd334acfc246741f7a2cca3e55d7f5b2mflodman@webrtc.org}  // namespace webrtc
392