Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/video/vie_remb.h"
12 :
13 : #include <assert.h>
14 :
15 : #include <algorithm>
16 :
17 : #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
18 : #include "webrtc/modules/utility/include/process_thread.h"
19 : #include "webrtc/system_wrappers/include/trace.h"
20 :
21 : namespace webrtc {
22 :
23 : const int kRembSendIntervalMs = 200;
24 :
25 : // % threshold for if we should send a new REMB asap.
26 : const uint32_t kSendThresholdPercent = 97;
27 :
28 0 : VieRemb::VieRemb(Clock* clock)
29 : : clock_(clock),
30 0 : last_remb_time_(clock_->TimeInMilliseconds()),
31 : last_send_bitrate_(0),
32 0 : bitrate_(0) {}
33 :
34 0 : VieRemb::~VieRemb() {}
35 :
36 0 : void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
37 0 : assert(rtp_rtcp);
38 :
39 0 : rtc::CritScope lock(&list_crit_);
40 0 : if (std::find(receive_modules_.begin(), receive_modules_.end(), rtp_rtcp) !=
41 0 : receive_modules_.end())
42 0 : return;
43 :
44 : // The module probably doesn't have a remote SSRC yet, so don't add it to the
45 : // map.
46 0 : receive_modules_.push_back(rtp_rtcp);
47 : }
48 :
49 0 : void VieRemb::RemoveReceiveChannel(RtpRtcp* rtp_rtcp) {
50 0 : assert(rtp_rtcp);
51 :
52 0 : rtc::CritScope lock(&list_crit_);
53 0 : for (RtpModules::iterator it = receive_modules_.begin();
54 0 : it != receive_modules_.end(); ++it) {
55 0 : if ((*it) == rtp_rtcp) {
56 0 : receive_modules_.erase(it);
57 0 : break;
58 : }
59 : }
60 0 : }
61 :
62 0 : void VieRemb::AddRembSender(RtpRtcp* rtp_rtcp) {
63 0 : assert(rtp_rtcp);
64 :
65 0 : rtc::CritScope lock(&list_crit_);
66 :
67 : // Verify this module hasn't been added earlier.
68 0 : if (std::find(rtcp_sender_.begin(), rtcp_sender_.end(), rtp_rtcp) !=
69 0 : rtcp_sender_.end())
70 0 : return;
71 0 : rtcp_sender_.push_back(rtp_rtcp);
72 : }
73 :
74 0 : void VieRemb::RemoveRembSender(RtpRtcp* rtp_rtcp) {
75 0 : assert(rtp_rtcp);
76 :
77 0 : rtc::CritScope lock(&list_crit_);
78 0 : for (RtpModules::iterator it = rtcp_sender_.begin();
79 0 : it != rtcp_sender_.end(); ++it) {
80 0 : if ((*it) == rtp_rtcp) {
81 0 : rtcp_sender_.erase(it);
82 0 : return;
83 : }
84 : }
85 : }
86 :
87 0 : bool VieRemb::InUse() const {
88 0 : rtc::CritScope lock(&list_crit_);
89 0 : return !receive_modules_.empty() || !rtcp_sender_.empty();
90 : }
91 :
92 0 : void VieRemb::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
93 : uint32_t bitrate) {
94 0 : RtpRtcp* sender = nullptr;
95 : {
96 0 : rtc::CritScope lock(&list_crit_);
97 : // If we already have an estimate, check if the new total estimate is below
98 : // kSendThresholdPercent of the previous estimate.
99 0 : if (last_send_bitrate_ > 0) {
100 0 : uint32_t new_remb_bitrate = last_send_bitrate_ - bitrate_ + bitrate;
101 :
102 0 : if (new_remb_bitrate < kSendThresholdPercent * last_send_bitrate_ / 100) {
103 : // The new bitrate estimate is less than kSendThresholdPercent % of the
104 : // last report. Send a REMB asap.
105 0 : last_remb_time_ = clock_->TimeInMilliseconds() - kRembSendIntervalMs;
106 : }
107 : }
108 0 : bitrate_ = bitrate;
109 :
110 : // Calculate total receive bitrate estimate.
111 0 : int64_t now = clock_->TimeInMilliseconds();
112 :
113 0 : if (now - last_remb_time_ < kRembSendIntervalMs) {
114 0 : return;
115 : }
116 0 : last_remb_time_ = now;
117 :
118 0 : if (ssrcs.empty() || receive_modules_.empty()) {
119 0 : return;
120 : }
121 :
122 : // Send a REMB packet.
123 0 : if (!rtcp_sender_.empty()) {
124 0 : sender = rtcp_sender_.front();
125 : } else {
126 0 : sender = receive_modules_.front();
127 : }
128 0 : last_send_bitrate_ = bitrate_;
129 : }
130 :
131 0 : if (sender) {
132 0 : sender->SetREMBData(bitrate_, ssrcs);
133 : }
134 : }
135 :
136 : } // namespace webrtc
|