blob: 34a61ef5a227fcf2b886ee5cb7345566c073d1c2 [file] [log] [blame]
Alex Narest78609d52017-10-20 10:37:47 +02001/*
2 * Copyright 2017 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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/bitrate_allocation_strategy.h"
Sebastian Janssond28efe52018-10-18 12:26:46 +020012
Alex Narest78609d52017-10-20 10:37:47 +020013#include <algorithm>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <cstddef>
15#include <cstdint>
Yves Gerey2e00abc2018-10-05 15:39:24 +020016#include <map>
Alex Narest78609d52017-10-20 10:37:47 +020017#include <utility>
18
Sebastian Janssond28efe52018-10-18 12:26:46 +020019#include "rtc_base/numerics/safe_minmax.h"
20#include "system_wrappers/include/field_trial.h"
21
22namespace webrtc {
23AudioPriorityConfig::AudioPriorityConfig()
24 : min_rate("min"), max_rate("max"), target_rate("target") {
25 std::string trial_string;
26// TODO(bugs.webrtc.org/9889): Remove this when Chromium build has been fixed.
27#if !defined(WEBRTC_CHROMIUM_BUILD)
28 trial_string = field_trial::FindFullName("WebRTC-Bwe-AudioPriority");
29#endif
30 ParseFieldTrial({&min_rate, &max_rate, &target_rate}, trial_string);
31}
32AudioPriorityConfig::AudioPriorityConfig(const AudioPriorityConfig&) = default;
33AudioPriorityConfig::~AudioPriorityConfig() = default;
34
35} // namespace webrtc
36
Alex Narest78609d52017-10-20 10:37:47 +020037namespace rtc {
38
Alex Nareste0b2ff52017-11-16 20:03:46 +010039// The purpose of this is to allow video streams to use extra bandwidth for FEC.
40// TODO(bugs.webrtc.org/8541): May be worth to refactor to keep this logic in
41// video send stream. Similar logic is implemented in BitrateAllocator.
42
43const int kTransmissionMaxBitrateMultiplier = 2;
44
Alex Narest78609d52017-10-20 10:37:47 +020045std::vector<uint32_t> BitrateAllocationStrategy::SetAllBitratesToMinimum(
Sebastian Janssone2754c92018-10-24 16:02:26 +020046 const std::vector<BitrateAllocationStrategy::TrackConfig>& track_configs) {
Alex Narest78609d52017-10-20 10:37:47 +020047 std::vector<uint32_t> track_allocations;
Mirko Bonadei649a4c22019-01-29 10:11:53 +010048 track_allocations.reserve(track_configs.size());
Sebastian Janssone2754c92018-10-24 16:02:26 +020049 for (const auto& track_config : track_configs) {
50 track_allocations.push_back(track_config.min_bitrate_bps);
Alex Narest78609d52017-10-20 10:37:47 +020051 }
52 return track_allocations;
53}
54
55std::vector<uint32_t> BitrateAllocationStrategy::DistributeBitratesEvenly(
Sebastian Janssone2754c92018-10-24 16:02:26 +020056 const std::vector<BitrateAllocationStrategy::TrackConfig>& track_configs,
Alex Narest78609d52017-10-20 10:37:47 +020057 uint32_t available_bitrate) {
58 std::vector<uint32_t> track_allocations =
59 SetAllBitratesToMinimum(track_configs);
60 uint32_t sum_min_bitrates = 0;
61 uint32_t sum_max_bitrates = 0;
Sebastian Janssone2754c92018-10-24 16:02:26 +020062 for (const auto& track_config : track_configs) {
63 sum_min_bitrates += track_config.min_bitrate_bps;
64 sum_max_bitrates += track_config.max_bitrate_bps;
Alex Narest78609d52017-10-20 10:37:47 +020065 }
66 if (sum_min_bitrates >= available_bitrate) {
67 return track_allocations;
68 } else if (available_bitrate >= sum_max_bitrates) {
69 auto track_allocations_it = track_allocations.begin();
Sebastian Janssone2754c92018-10-24 16:02:26 +020070 for (const auto& track_config : track_configs) {
71 *track_allocations_it++ = track_config.max_bitrate_bps;
Alex Narest78609d52017-10-20 10:37:47 +020072 }
73 return track_allocations;
74 } else {
75 // If sum_min_bitrates < available_bitrate < sum_max_bitrates allocate
76 // bitrates evenly up to max_bitrate_bps starting from the track with the
77 // lowest max_bitrate_bps. Remainder of available bitrate split evenly among
78 // remaining tracks.
79 std::multimap<uint32_t, size_t> max_bitrate_sorted_configs;
Sebastian Janssone2754c92018-10-24 16:02:26 +020080 for (const auto& track_config : track_configs) {
Alex Narest78609d52017-10-20 10:37:47 +020081 max_bitrate_sorted_configs.insert(
Sebastian Janssone2754c92018-10-24 16:02:26 +020082 std::make_pair(track_config.max_bitrate_bps,
83 &track_config - &track_configs.front()));
Alex Narest78609d52017-10-20 10:37:47 +020084 }
85 uint32_t total_available_increase = available_bitrate - sum_min_bitrates;
86 int processed_configs = 0;
87 for (const auto& track_config_pair : max_bitrate_sorted_configs) {
88 uint32_t available_increase =
89 total_available_increase /
90 (static_cast<uint32_t>(track_configs.size() - processed_configs));
91 uint32_t consumed_increase =
Sebastian Janssone2754c92018-10-24 16:02:26 +020092 std::min(track_configs[track_config_pair.second].max_bitrate_bps -
93 track_configs[track_config_pair.second].min_bitrate_bps,
Alex Narest78609d52017-10-20 10:37:47 +020094 available_increase);
95 track_allocations[track_config_pair.second] += consumed_increase;
96 total_available_increase -= consumed_increase;
97 ++processed_configs;
98 }
99 return track_allocations;
100 }
101}
Alex Narest78609d52017-10-20 10:37:47 +0200102AudioPriorityBitrateAllocationStrategy::AudioPriorityBitrateAllocationStrategy(
103 std::string audio_track_id,
104 uint32_t sufficient_audio_bitrate)
105 : audio_track_id_(audio_track_id),
Sebastian Janssond28efe52018-10-18 12:26:46 +0200106 sufficient_audio_bitrate_(sufficient_audio_bitrate) {
107 if (config_.target_rate) {
108 sufficient_audio_bitrate_ = config_.target_rate->bps();
109 }
110}
Alex Narest78609d52017-10-20 10:37:47 +0200111
112std::vector<uint32_t> AudioPriorityBitrateAllocationStrategy::AllocateBitrates(
113 uint32_t available_bitrate,
Sebastian Janssone2754c92018-10-24 16:02:26 +0200114 std::vector<BitrateAllocationStrategy::TrackConfig> track_configs) {
115 TrackConfig* audio_track_config = nullptr;
Alex Narest78609d52017-10-20 10:37:47 +0200116 size_t audio_config_index = 0;
117 uint32_t sum_min_bitrates = 0;
Alex Nareste0b2ff52017-11-16 20:03:46 +0100118 uint32_t sum_max_bitrates = 0;
Alex Narest78609d52017-10-20 10:37:47 +0200119
Sebastian Janssone2754c92018-10-24 16:02:26 +0200120 for (auto& track_config : track_configs) {
121 if (track_config.track_id == audio_track_id_) {
Alex Narest78609d52017-10-20 10:37:47 +0200122 audio_config_index = &track_config - &track_configs[0];
Sebastian Janssone2754c92018-10-24 16:02:26 +0200123 audio_track_config = &track_config;
Sebastian Janssond28efe52018-10-18 12:26:46 +0200124 if (config_.min_rate)
125 audio_track_config->min_bitrate_bps = config_.min_rate->bps();
126 if (config_.max_rate)
127 audio_track_config->max_bitrate_bps = config_.max_rate->bps();
Alex Narest78609d52017-10-20 10:37:47 +0200128 }
Sebastian Janssone2754c92018-10-24 16:02:26 +0200129 sum_min_bitrates += track_config.min_bitrate_bps;
130 sum_max_bitrates += track_config.max_bitrate_bps;
Alex Narest78609d52017-10-20 10:37:47 +0200131 }
Alex Nareste0b2ff52017-11-16 20:03:46 +0100132 if (sum_max_bitrates < available_bitrate) {
133 // Allow non audio streams to go above max upto
134 // kTransmissionMaxBitrateMultiplier * max_bitrate_bps
Sebastian Janssone2754c92018-10-24 16:02:26 +0200135 for (auto& track_config : track_configs) {
136 if (&track_config != audio_track_config)
137 track_config.max_bitrate_bps *= kTransmissionMaxBitrateMultiplier;
Alex Nareste0b2ff52017-11-16 20:03:46 +0100138 }
Sebastian Janssone2754c92018-10-24 16:02:26 +0200139 return DistributeBitratesEvenly(track_configs, available_bitrate);
Alex Nareste0b2ff52017-11-16 20:03:46 +0100140 }
Sebastian Janssond28efe52018-10-18 12:26:46 +0200141 if (!audio_track_config) {
Alex Narest78609d52017-10-20 10:37:47 +0200142 return DistributeBitratesEvenly(track_configs, available_bitrate);
143 }
Sebastian Janssond28efe52018-10-18 12:26:46 +0200144 auto safe_sufficient_audio_bitrate = rtc::SafeClamp(
145 sufficient_audio_bitrate_, audio_track_config->min_bitrate_bps,
Alex Narest78609d52017-10-20 10:37:47 +0200146 audio_track_config->max_bitrate_bps);
147 if (available_bitrate <= sum_min_bitrates) {
148 return SetAllBitratesToMinimum(track_configs);
149 } else {
150 if (available_bitrate <= sum_min_bitrates + safe_sufficient_audio_bitrate -
151 audio_track_config->min_bitrate_bps) {
152 std::vector<uint32_t> track_allocations =
153 SetAllBitratesToMinimum(track_configs);
154 track_allocations[audio_config_index] +=
155 available_bitrate - sum_min_bitrates;
156 return track_allocations;
157 } else {
158 // Setting audio track minimum to safe_sufficient_audio_bitrate will
159 // allow using DistributeBitratesEvenly to allocate at least sufficient
160 // bitrate for audio and the rest evenly.
Sebastian Janssone2754c92018-10-24 16:02:26 +0200161 audio_track_config->min_bitrate_bps = safe_sufficient_audio_bitrate;
Alex Narest78609d52017-10-20 10:37:47 +0200162 std::vector<uint32_t> track_allocations =
163 DistributeBitratesEvenly(track_configs, available_bitrate);
164 return track_allocations;
165 }
166 }
167}
168
169} // namespace rtc