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