-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathbitrate_allocation_strategy.cc
169 lines (156 loc) · 6.75 KB
/
bitrate_allocation_strategy.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
* Copyright 2017 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "rtc_base/bitrate_allocation_strategy.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <map>
#include <utility>
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
AudioPriorityConfig::AudioPriorityConfig()
: min_rate("min"), max_rate("max"), target_rate("target") {
std::string trial_string;
// TODO(bugs.webrtc.org/9889): Remove this when Chromium build has been fixed.
#if !defined(WEBRTC_CHROMIUM_BUILD)
trial_string = field_trial::FindFullName("WebRTC-Bwe-AudioPriority");
#endif
ParseFieldTrial({&min_rate, &max_rate, &target_rate}, trial_string);
}
AudioPriorityConfig::AudioPriorityConfig(const AudioPriorityConfig&) = default;
AudioPriorityConfig::~AudioPriorityConfig() = default;
} // namespace webrtc
namespace rtc {
// The purpose of this is to allow video streams to use extra bandwidth for FEC.
// TODO(bugs.webrtc.org/8541): May be worth to refactor to keep this logic in
// video send stream. Similar logic is implemented in BitrateAllocator.
const int kTransmissionMaxBitrateMultiplier = 2;
std::vector<uint32_t> BitrateAllocationStrategy::SetAllBitratesToMinimum(
const std::vector<BitrateAllocationStrategy::TrackConfig>& track_configs) {
std::vector<uint32_t> track_allocations;
track_allocations.reserve(track_configs.size());
for (const auto& track_config : track_configs) {
track_allocations.push_back(track_config.min_bitrate_bps);
}
return track_allocations;
}
std::vector<uint32_t> BitrateAllocationStrategy::DistributeBitratesEvenly(
const std::vector<BitrateAllocationStrategy::TrackConfig>& track_configs,
uint32_t available_bitrate) {
std::vector<uint32_t> track_allocations =
SetAllBitratesToMinimum(track_configs);
uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0;
for (const auto& track_config : track_configs) {
sum_min_bitrates += track_config.min_bitrate_bps;
sum_max_bitrates += track_config.max_bitrate_bps;
}
if (sum_min_bitrates >= available_bitrate) {
return track_allocations;
} else if (available_bitrate >= sum_max_bitrates) {
auto track_allocations_it = track_allocations.begin();
for (const auto& track_config : track_configs) {
*track_allocations_it++ = track_config.max_bitrate_bps;
}
return track_allocations;
} else {
// If sum_min_bitrates < available_bitrate < sum_max_bitrates allocate
// bitrates evenly up to max_bitrate_bps starting from the track with the
// lowest max_bitrate_bps. Remainder of available bitrate split evenly among
// remaining tracks.
std::multimap<uint32_t, size_t> max_bitrate_sorted_configs;
for (const auto& track_config : track_configs) {
max_bitrate_sorted_configs.insert(
std::make_pair(track_config.max_bitrate_bps,
&track_config - &track_configs.front()));
}
uint32_t total_available_increase = available_bitrate - sum_min_bitrates;
int processed_configs = 0;
for (const auto& track_config_pair : max_bitrate_sorted_configs) {
uint32_t available_increase =
total_available_increase /
(static_cast<uint32_t>(track_configs.size() - processed_configs));
uint32_t consumed_increase =
std::min(track_configs[track_config_pair.second].max_bitrate_bps -
track_configs[track_config_pair.second].min_bitrate_bps,
available_increase);
track_allocations[track_config_pair.second] += consumed_increase;
total_available_increase -= consumed_increase;
++processed_configs;
}
return track_allocations;
}
}
AudioPriorityBitrateAllocationStrategy::AudioPriorityBitrateAllocationStrategy(
std::string audio_track_id,
uint32_t sufficient_audio_bitrate)
: audio_track_id_(audio_track_id),
sufficient_audio_bitrate_(sufficient_audio_bitrate) {
if (config_.target_rate) {
sufficient_audio_bitrate_ = config_.target_rate->bps();
}
}
std::vector<uint32_t> AudioPriorityBitrateAllocationStrategy::AllocateBitrates(
uint32_t available_bitrate,
std::vector<BitrateAllocationStrategy::TrackConfig> track_configs) {
TrackConfig* audio_track_config = nullptr;
size_t audio_config_index = 0;
uint32_t sum_min_bitrates = 0;
uint32_t sum_max_bitrates = 0;
for (auto& track_config : track_configs) {
if (track_config.track_id == audio_track_id_) {
audio_config_index = &track_config - &track_configs[0];
audio_track_config = &track_config;
if (config_.min_rate)
audio_track_config->min_bitrate_bps = config_.min_rate->bps();
if (config_.max_rate)
audio_track_config->max_bitrate_bps = config_.max_rate->bps();
}
sum_min_bitrates += track_config.min_bitrate_bps;
sum_max_bitrates += track_config.max_bitrate_bps;
}
if (sum_max_bitrates < available_bitrate) {
// Allow non audio streams to go above max upto
// kTransmissionMaxBitrateMultiplier * max_bitrate_bps
for (auto& track_config : track_configs) {
if (&track_config != audio_track_config)
track_config.max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
}
return DistributeBitratesEvenly(track_configs, available_bitrate);
}
if (!audio_track_config) {
return DistributeBitratesEvenly(track_configs, available_bitrate);
}
auto safe_sufficient_audio_bitrate = rtc::SafeClamp(
sufficient_audio_bitrate_, audio_track_config->min_bitrate_bps,
audio_track_config->max_bitrate_bps);
if (available_bitrate <= sum_min_bitrates) {
return SetAllBitratesToMinimum(track_configs);
} else {
if (available_bitrate <= sum_min_bitrates + safe_sufficient_audio_bitrate -
audio_track_config->min_bitrate_bps) {
std::vector<uint32_t> track_allocations =
SetAllBitratesToMinimum(track_configs);
track_allocations[audio_config_index] +=
available_bitrate - sum_min_bitrates;
return track_allocations;
} else {
// Setting audio track minimum to safe_sufficient_audio_bitrate will
// allow using DistributeBitratesEvenly to allocate at least sufficient
// bitrate for audio and the rest evenly.
audio_track_config->min_bitrate_bps = safe_sufficient_audio_bitrate;
std::vector<uint32_t> track_allocations =
DistributeBitratesEvenly(track_configs, available_bitrate);
return track_allocations;
}
}
}
} // namespace rtc