blob: 7c65c12373260175df6062cf841a61bccbb3da2a [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
11#include "rtc_base/bitrateallocationstrategy.h"
12#include <algorithm>
Yves Gerey2e00abc2018-10-05 15:39:24 +020013#include <map>
Alex Narest78609d52017-10-20 10:37:47 +020014#include <utility>
15
16namespace rtc {
17
Alex Nareste0b2ff52017-11-16 20:03:46 +010018// The purpose of this is to allow video streams to use extra bandwidth for FEC.
19// TODO(bugs.webrtc.org/8541): May be worth to refactor to keep this logic in
20// video send stream. Similar logic is implemented in BitrateAllocator.
21
22const int kTransmissionMaxBitrateMultiplier = 2;
23
Alex Narest78609d52017-10-20 10:37:47 +020024std::vector<uint32_t> BitrateAllocationStrategy::SetAllBitratesToMinimum(
25 const ArrayView<const TrackConfig*> track_configs) {
26 std::vector<uint32_t> track_allocations;
27 for (const auto* track_config : track_configs) {
28 track_allocations.push_back(track_config->min_bitrate_bps);
29 }
30 return track_allocations;
31}
32
33std::vector<uint32_t> BitrateAllocationStrategy::DistributeBitratesEvenly(
34 const ArrayView<const TrackConfig*> track_configs,
35 uint32_t available_bitrate) {
36 std::vector<uint32_t> track_allocations =
37 SetAllBitratesToMinimum(track_configs);
38 uint32_t sum_min_bitrates = 0;
39 uint32_t sum_max_bitrates = 0;
40 for (const auto* track_config : track_configs) {
41 sum_min_bitrates += track_config->min_bitrate_bps;
42 sum_max_bitrates += track_config->max_bitrate_bps;
43 }
44 if (sum_min_bitrates >= available_bitrate) {
45 return track_allocations;
46 } else if (available_bitrate >= sum_max_bitrates) {
47 auto track_allocations_it = track_allocations.begin();
48 for (const auto* track_config : track_configs) {
49 *track_allocations_it++ = track_config->max_bitrate_bps;
50 }
51 return track_allocations;
52 } else {
53 // If sum_min_bitrates < available_bitrate < sum_max_bitrates allocate
54 // bitrates evenly up to max_bitrate_bps starting from the track with the
55 // lowest max_bitrate_bps. Remainder of available bitrate split evenly among
56 // remaining tracks.
57 std::multimap<uint32_t, size_t> max_bitrate_sorted_configs;
58 for (const TrackConfig** track_configs_it = track_configs.begin();
59 track_configs_it != track_configs.end(); ++track_configs_it) {
60 max_bitrate_sorted_configs.insert(
61 std::make_pair((*track_configs_it)->max_bitrate_bps,
62 track_configs_it - track_configs.begin()));
63 }
64 uint32_t total_available_increase = available_bitrate - sum_min_bitrates;
65 int processed_configs = 0;
66 for (const auto& track_config_pair : max_bitrate_sorted_configs) {
67 uint32_t available_increase =
68 total_available_increase /
69 (static_cast<uint32_t>(track_configs.size() - processed_configs));
70 uint32_t consumed_increase =
71 std::min(track_configs[track_config_pair.second]->max_bitrate_bps -
72 track_configs[track_config_pair.second]->min_bitrate_bps,
73 available_increase);
74 track_allocations[track_config_pair.second] += consumed_increase;
75 total_available_increase -= consumed_increase;
76 ++processed_configs;
77 }
78 return track_allocations;
79 }
80}
81
82AudioPriorityBitrateAllocationStrategy::AudioPriorityBitrateAllocationStrategy(
83 std::string audio_track_id,
84 uint32_t sufficient_audio_bitrate)
85 : audio_track_id_(audio_track_id),
86 sufficient_audio_bitrate_(sufficient_audio_bitrate) {}
87
88std::vector<uint32_t> AudioPriorityBitrateAllocationStrategy::AllocateBitrates(
89 uint32_t available_bitrate,
90 const ArrayView<const TrackConfig*> track_configs) {
91 const TrackConfig* audio_track_config = NULL;
92 size_t audio_config_index = 0;
93 uint32_t sum_min_bitrates = 0;
Alex Nareste0b2ff52017-11-16 20:03:46 +010094 uint32_t sum_max_bitrates = 0;
Alex Narest78609d52017-10-20 10:37:47 +020095
96 for (const auto*& track_config : track_configs) {
97 sum_min_bitrates += track_config->min_bitrate_bps;
Alex Nareste0b2ff52017-11-16 20:03:46 +010098 sum_max_bitrates += track_config->max_bitrate_bps;
Alex Narest78609d52017-10-20 10:37:47 +020099 if (track_config->track_id == audio_track_id_) {
100 audio_track_config = track_config;
101 audio_config_index = &track_config - &track_configs[0];
102 }
103 }
Alex Nareste0b2ff52017-11-16 20:03:46 +0100104 if (sum_max_bitrates < available_bitrate) {
105 // Allow non audio streams to go above max upto
106 // kTransmissionMaxBitrateMultiplier * max_bitrate_bps
107 size_t track_configs_size = track_configs.size();
108 std::vector<TrackConfig> increased_track_configs(track_configs_size);
109 std::vector<const TrackConfig*> increased_track_configs_ptr(
110 track_configs_size);
111 for (unsigned long i = 0; i < track_configs_size; i++) {
112 increased_track_configs[i] = (*track_configs[i]);
113 increased_track_configs_ptr[i] = &increased_track_configs[i];
114 if (track_configs[i]->track_id != audio_track_id_) {
115 increased_track_configs[i].max_bitrate_bps =
116 track_configs[i]->max_bitrate_bps *
117 kTransmissionMaxBitrateMultiplier;
118 }
119 }
120 return DistributeBitratesEvenly(increased_track_configs_ptr,
121 available_bitrate);
122 }
Alex Narest78609d52017-10-20 10:37:47 +0200123 if (audio_track_config == nullptr) {
124 return DistributeBitratesEvenly(track_configs, available_bitrate);
125 }
126 auto safe_sufficient_audio_bitrate = std::min(
127 std::max(audio_track_config->min_bitrate_bps, sufficient_audio_bitrate_),
128 audio_track_config->max_bitrate_bps);
129 if (available_bitrate <= sum_min_bitrates) {
130 return SetAllBitratesToMinimum(track_configs);
131 } else {
132 if (available_bitrate <= sum_min_bitrates + safe_sufficient_audio_bitrate -
133 audio_track_config->min_bitrate_bps) {
134 std::vector<uint32_t> track_allocations =
135 SetAllBitratesToMinimum(track_configs);
136 track_allocations[audio_config_index] +=
137 available_bitrate - sum_min_bitrates;
138 return track_allocations;
139 } else {
140 // Setting audio track minimum to safe_sufficient_audio_bitrate will
141 // allow using DistributeBitratesEvenly to allocate at least sufficient
142 // bitrate for audio and the rest evenly.
143 TrackConfig sufficient_track_config(*track_configs[audio_config_index]);
144 sufficient_track_config.min_bitrate_bps = safe_sufficient_audio_bitrate;
145 track_configs[audio_config_index] = &sufficient_track_config;
146 std::vector<uint32_t> track_allocations =
147 DistributeBitratesEvenly(track_configs, available_bitrate);
148 return track_allocations;
149 }
150 }
151}
152
153} // namespace rtc