blob: dc05081acea9d3645ae49ff0fd3908304dd08c45 [file] [log] [blame]
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
buildbot@webrtc.orga8530772014-12-10 09:01:18 +00009 */
10
sprang@webrtc.org46d4d292014-12-23 15:19:35 +000011#include <stdio.h>
Steve Antone78bcb92017-10-31 09:53:08 -070012#include <algorithm>
13#include <string>
sprang@webrtc.org46d4d292014-12-23 15:19:35 +000014
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "media/base/streamparams.h"
16#include "media/engine/constants.h"
17#include "media/engine/simulcast.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020018#include "modules/video_coding/utility/simulcast_rate_allocator.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/arraysize.h"
20#include "rtc_base/logging.h"
21#include "system_wrappers/include/field_trial.h"
tfarina5237aaf2015-11-10 23:44:30 -080022
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000023namespace cricket {
24
Rasmus Brandt195d1d72018-05-09 11:28:01 +020025namespace {
26
Erik Språngb6b1cac2018-08-09 16:12:54 +020027// Limits for legacy conference screensharing mode. Currently used for the
28// lower of the two simulcast streams.
Rasmus Brandt195d1d72018-05-09 11:28:01 +020029constexpr int kScreenshareDefaultTl0BitrateKbps = 200;
30constexpr int kScreenshareDefaultTl1BitrateKbps = 1000;
31
Erik Språngb6b1cac2018-08-09 16:12:54 +020032// Max bitrate for the higher one of the two simulcast stream used for screen
33// content.
34constexpr int kScreenshareHighStreamMaxBitrateBps = 1600000;
35
Rasmus Brandt195d1d72018-05-09 11:28:01 +020036} // namespace
37
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000038struct SimulcastFormat {
39 int width;
40 int height;
41 // The maximum number of simulcast layers can be used for
42 // resolutions at |widthxheigh|.
43 size_t max_layers;
44 // The maximum bitrate for encoding stream at |widthxheight|, when we are
45 // not sending the next higher spatial stream.
pbosbe16f792015-10-16 12:49:39 -070046 int max_bitrate_kbps;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000047 // The target bitrate for encoding stream at |widthxheight|, when this layer
48 // is not the highest layer (i.e., when we are sending another higher spatial
49 // stream).
pbosbe16f792015-10-16 12:49:39 -070050 int target_bitrate_kbps;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000051 // The minimum bitrate needed for encoding stream at |widthxheight|.
pbosbe16f792015-10-16 12:49:39 -070052 int min_bitrate_kbps;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000053};
54
55// These tables describe from which resolution we can use how many
56// simulcast layers at what bitrates (maximum, target, and minimum).
57// Important!! Keep this table from high resolution to low resolution.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020058// clang-format off
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000059const SimulcastFormat kSimulcastFormats[] = {
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020060 {1920, 1080, 3, 5000, 4000, 800},
61 {1280, 720, 3, 2500, 2500, 600},
62 {960, 540, 3, 900, 900, 450},
63 {640, 360, 2, 700, 500, 150},
64 {480, 270, 2, 450, 350, 150},
65 {320, 180, 1, 200, 150, 30},
66 {0, 0, 1, 200, 150, 30}
67};
68// clang-format on
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000069
Seth Hampson1370e302018-02-07 08:50:36 -080070const int kMaxScreenshareSimulcastLayers = 2;
sprang429600d2017-01-26 06:12:26 -080071
Erik Språngbfe3d852018-05-15 09:54:14 +020072// Multiway: Number of temporal layers for each simulcast stream.
73int DefaultNumberOfTemporalLayers(int simulcast_id) {
74 RTC_CHECK_GE(simulcast_id, 0);
75 RTC_CHECK_LT(simulcast_id, webrtc::kMaxSimulcastStreams);
76
77 const int kDefaultNumTemporalLayers = 3;
78
79 const std::string group_name =
80 webrtc::field_trial::FindFullName("WebRTC-VP8ConferenceTemporalLayers");
81 if (group_name.empty())
82 return kDefaultNumTemporalLayers;
83
84 int num_temporal_layers = kDefaultNumTemporalLayers;
85 if (sscanf(group_name.c_str(), "%d", &num_temporal_layers) == 1 &&
86 num_temporal_layers > 0 &&
87 num_temporal_layers <= webrtc::kMaxTemporalStreams) {
88 return num_temporal_layers;
89 }
90
91 RTC_LOG(LS_WARNING) << "Attempt to set number of temporal layers to "
92 "incorrect value: "
93 << group_name;
94
95 return kDefaultNumTemporalLayers;
96}
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000097
buildbot@webrtc.orga8530772014-12-10 09:01:18 +000098int FindSimulcastFormatIndex(int width, int height) {
Seth Hampson438663e2018-01-09 11:14:14 -080099 RTC_DCHECK_GE(width, 0);
100 RTC_DCHECK_GE(height, 0);
kjellandera96e2d72016-02-04 23:52:28 -0800101 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) {
sprang429600d2017-01-26 06:12:26 -0800102 if (width * height >=
103 kSimulcastFormats[i].width * kSimulcastFormats[i].height) {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000104 return i;
105 }
106 }
Seth Hampson438663e2018-01-09 11:14:14 -0800107 RTC_NOTREACHED();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000108 return -1;
109}
110
111int FindSimulcastFormatIndex(int width, int height, size_t max_layers) {
Seth Hampson438663e2018-01-09 11:14:14 -0800112 RTC_DCHECK_GE(width, 0);
113 RTC_DCHECK_GE(height, 0);
114 RTC_DCHECK_GT(max_layers, 0);
kjellandera96e2d72016-02-04 23:52:28 -0800115 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) {
sprang429600d2017-01-26 06:12:26 -0800116 if (width * height >=
117 kSimulcastFormats[i].width * kSimulcastFormats[i].height &&
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000118 max_layers == kSimulcastFormats[i].max_layers) {
119 return i;
120 }
121 }
Seth Hampson438663e2018-01-09 11:14:14 -0800122 RTC_NOTREACHED();
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000123 return -1;
124}
125
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000126// Simulcast stream width and height must both be dividable by
Rasmus Brandtefbdcb02018-04-26 17:47:42 +0200127// |2 ^ (simulcast_layers - 1)|.
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000128int NormalizeSimulcastSize(int size, size_t simulcast_layers) {
129 const int base2_exponent = static_cast<int>(simulcast_layers) - 1;
130 return ((size >> base2_exponent) << base2_exponent);
131}
132
133size_t FindSimulcastMaxLayers(int width, int height) {
134 int index = FindSimulcastFormatIndex(width, height);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000135 return kSimulcastFormats[index].max_layers;
136}
137
sprang429600d2017-01-26 06:12:26 -0800138int FindSimulcastMaxBitrateBps(int width, int height) {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000139 const int format_index = FindSimulcastFormatIndex(width, height);
pbosbe16f792015-10-16 12:49:39 -0700140 return kSimulcastFormats[format_index].max_bitrate_kbps * 1000;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000141}
142
sprang429600d2017-01-26 06:12:26 -0800143int FindSimulcastTargetBitrateBps(int width, int height) {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000144 const int format_index = FindSimulcastFormatIndex(width, height);
pbosbe16f792015-10-16 12:49:39 -0700145 return kSimulcastFormats[format_index].target_bitrate_kbps * 1000;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000146}
147
sprang429600d2017-01-26 06:12:26 -0800148int FindSimulcastMinBitrateBps(int width, int height) {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000149 const int format_index = FindSimulcastFormatIndex(width, height);
pbosbe16f792015-10-16 12:49:39 -0700150 return kSimulcastFormats[format_index].min_bitrate_kbps * 1000;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000151}
152
Seth Hampson438663e2018-01-09 11:14:14 -0800153void SlotSimulcastMaxResolution(size_t max_layers, int* width, int* height) {
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000154 int index = FindSimulcastFormatIndex(*width, *height, max_layers);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000155 *width = kSimulcastFormats[index].width;
156 *height = kSimulcastFormats[index].height;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100157 RTC_LOG(LS_INFO) << "SlotSimulcastMaxResolution to width:" << *width
158 << " height:" << *height;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000159}
160
Seth Hampson1370e302018-02-07 08:50:36 -0800161void BoostMaxSimulcastLayer(int max_bitrate_bps,
162 std::vector<webrtc::VideoStream>* layers) {
Åsa Persson55659812018-06-18 17:51:32 +0200163 if (layers->empty())
164 return;
165
Seth Hampson1370e302018-02-07 08:50:36 -0800166 // Spend additional bits to boost the max layer.
167 int bitrate_left_bps = max_bitrate_bps - GetTotalMaxBitrateBps(*layers);
168 if (bitrate_left_bps > 0) {
169 layers->back().max_bitrate_bps += bitrate_left_bps;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000170 }
Seth Hampson1370e302018-02-07 08:50:36 -0800171}
172
173int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& layers) {
Åsa Persson55659812018-06-18 17:51:32 +0200174 if (layers.empty())
175 return 0;
176
Seth Hampson1370e302018-02-07 08:50:36 -0800177 int total_max_bitrate_bps = 0;
178 for (size_t s = 0; s < layers.size() - 1; ++s) {
179 total_max_bitrate_bps += layers[s].target_bitrate_bps;
180 }
181 total_max_bitrate_bps += layers.back().max_bitrate_bps;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000182 return total_max_bitrate_bps;
183}
184
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200185std::vector<webrtc::VideoStream> GetSimulcastConfig(
186 size_t max_layers,
187 int width,
188 int height,
189 int /*max_bitrate_bps*/,
190 double bitrate_priority,
191 int max_qp,
192 int max_framerate,
193 bool is_screenshare,
194 bool temporal_layers_supported) {
Seth Hampson1370e302018-02-07 08:50:36 -0800195 if (is_screenshare) {
Åsa Persson55659812018-06-18 17:51:32 +0200196 return GetScreenshareLayers(max_layers, width, height, bitrate_priority,
197 max_qp, max_framerate,
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200198 temporal_layers_supported);
sprang429600d2017-01-26 06:12:26 -0800199 } else {
Åsa Persson55659812018-06-18 17:51:32 +0200200 return GetNormalSimulcastLayers(max_layers, width, height, bitrate_priority,
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200201 max_qp, max_framerate,
202 temporal_layers_supported);
sprang429600d2017-01-26 06:12:26 -0800203 }
Seth Hampson1370e302018-02-07 08:50:36 -0800204}
sprang429600d2017-01-26 06:12:26 -0800205
Seth Hampson1370e302018-02-07 08:50:36 -0800206std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
207 size_t max_layers,
208 int width,
209 int height,
Seth Hampson1370e302018-02-07 08:50:36 -0800210 double bitrate_priority,
211 int max_qp,
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200212 int max_framerate,
213 bool temporal_layers_supported) {
Seth Hampson1370e302018-02-07 08:50:36 -0800214 // TODO(bugs.webrtc.org/8785): Currently if the resolution isn't large enough
215 // (defined in kSimulcastFormats) we scale down the number of simulcast
216 // layers. Consider changing this so that the application can have more
217 // control over exactly how many simulcast layers are used.
218 size_t num_simulcast_layers = FindSimulcastMaxLayers(width, height);
219 if (num_simulcast_layers > max_layers) {
220 // TODO(bugs.webrtc.org/8486): This scales down the resolution if the
221 // number of simulcast layers created by the application isn't sufficient
222 // (defined in kSimulcastFormats). For example if the input frame's
223 // resolution is HD, but there are only 2 simulcast layers, the
224 // resolution gets scaled down to VGA. Consider taking this logic out to
225 // allow the application more control over the resolutions.
226 SlotSimulcastMaxResolution(max_layers, &width, &height);
227 num_simulcast_layers = max_layers;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000228 }
Seth Hampson1370e302018-02-07 08:50:36 -0800229 std::vector<webrtc::VideoStream> layers(num_simulcast_layers);
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000230
Seth Hampson1370e302018-02-07 08:50:36 -0800231 // Format width and height has to be divisible by |2 ^ num_simulcast_layers -
232 // 1|.
233 width = NormalizeSimulcastSize(width, num_simulcast_layers);
234 height = NormalizeSimulcastSize(height, num_simulcast_layers);
235 // Add simulcast streams, from highest resolution (|s| = num_simulcast_layers
236 // -1) to lowest resolution at |s| = 0.
237 for (size_t s = num_simulcast_layers - 1;; --s) {
238 layers[s].width = width;
239 layers[s].height = height;
240 // TODO(pbos): Fill actual temporal-layer bitrate thresholds.
241 layers[s].max_qp = max_qp;
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200242 layers[s].num_temporal_layers =
243 temporal_layers_supported ? DefaultNumberOfTemporalLayers(s)
244 : 0;
Seth Hampson1370e302018-02-07 08:50:36 -0800245 layers[s].max_bitrate_bps = FindSimulcastMaxBitrateBps(width, height);
246 layers[s].target_bitrate_bps = FindSimulcastTargetBitrateBps(width, height);
Erik Språng79478ad2018-05-18 09:39:55 +0200247 int num_temporal_layers = DefaultNumberOfTemporalLayers(s);
Erik Språngd497e6b2018-07-06 17:17:10 +0200248 if (s == 0) {
Erik Språng79478ad2018-05-18 09:39:55 +0200249 // If alternative number temporal layers is selected, adjust the
Erik Språngd92288f2018-07-04 10:07:40 +0200250 // bitrate of the lowest simulcast stream so that absolute bitrate for
251 // the base temporal layer matches the bitrate for the base temporal
252 // layer with the default 3 simulcast streams. Otherwise we risk a
253 // higher threshold for receiving a feed at all.
Erik Språngd497e6b2018-07-06 17:17:10 +0200254 float rate_factor = 1.0;
255 if (num_temporal_layers == 3) {
256 if (webrtc::field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
257 // Shortened pattern increases TL0 bitrate from 40% to 60%.
258 rate_factor = 0.4 / 0.6;
259 }
260 } else {
261 rate_factor =
262 webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(3, 0) /
263 webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
264 num_temporal_layers, 0);
265 }
266
Erik Språng79478ad2018-05-18 09:39:55 +0200267 layers[s].max_bitrate_bps =
268 static_cast<int>(layers[s].max_bitrate_bps * rate_factor);
269 layers[s].target_bitrate_bps =
270 static_cast<int>(layers[s].target_bitrate_bps * rate_factor);
271 }
Seth Hampson1370e302018-02-07 08:50:36 -0800272 layers[s].min_bitrate_bps = FindSimulcastMinBitrateBps(width, height);
273 layers[s].max_framerate = max_framerate;
sprang02569ad2017-07-06 05:05:50 -0700274
Seth Hampson1370e302018-02-07 08:50:36 -0800275 width /= 2;
276 height /= 2;
sprang02569ad2017-07-06 05:05:50 -0700277
Seth Hampson1370e302018-02-07 08:50:36 -0800278 if (s == 0) {
279 break;
sprang02569ad2017-07-06 05:05:50 -0700280 }
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000281 }
Seth Hampson1370e302018-02-07 08:50:36 -0800282 // Currently the relative bitrate priority of the sender is controlled by
283 // the value of the lowest VideoStream.
284 // TODO(bugs.webrtc.org/8630): The web specification describes being able to
285 // control relative bitrate for each individual simulcast layer, but this
286 // is currently just implemented per rtp sender.
287 layers[0].bitrate_priority = bitrate_priority;
288 return layers;
289}
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000290
Seth Hampson1370e302018-02-07 08:50:36 -0800291std::vector<webrtc::VideoStream> GetScreenshareLayers(
292 size_t max_layers,
293 int width,
294 int height,
Seth Hampson1370e302018-02-07 08:50:36 -0800295 double bitrate_priority,
296 int max_qp,
297 int max_framerate,
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200298 bool temporal_layers_supported) {
Seth Hampson1370e302018-02-07 08:50:36 -0800299 size_t num_simulcast_layers =
Ilya Nikolaevskiya3df0f22018-07-24 17:02:07 +0200300 std::min<int>(max_layers, kMaxScreenshareSimulcastLayers);
Seth Hampson1370e302018-02-07 08:50:36 -0800301
302 std::vector<webrtc::VideoStream> layers(num_simulcast_layers);
Seth Hampson1370e302018-02-07 08:50:36 -0800303 // For legacy screenshare in conference mode, tl0 and tl1 bitrates are
304 // piggybacked on the VideoCodec struct as target and max bitrates,
Erik Språngcc681cc2018-03-14 17:52:55 +0100305 // respectively. See eg. webrtc::LibvpxVp8Encoder::SetRates().
Seth Hampson1370e302018-02-07 08:50:36 -0800306 layers[0].width = width;
307 layers[0].height = height;
308 layers[0].max_qp = max_qp;
309 layers[0].max_framerate = 5;
310 layers[0].min_bitrate_bps = kMinVideoBitrateBps;
Rasmus Brandt195d1d72018-05-09 11:28:01 +0200311 layers[0].target_bitrate_bps = kScreenshareDefaultTl0BitrateKbps * 1000;
312 layers[0].max_bitrate_bps = kScreenshareDefaultTl1BitrateKbps * 1000;
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200313 layers[0].num_temporal_layers = temporal_layers_supported ? 2 : 0;
Seth Hampson1370e302018-02-07 08:50:36 -0800314
315 // With simulcast enabled, add another spatial layer. This one will have a
316 // more normal layout, with the regular 3 temporal layer pattern and no fps
317 // restrictions. The base simulcast layer will still use legacy setup.
318 if (num_simulcast_layers == kMaxScreenshareSimulcastLayers) {
319 // Add optional upper simulcast layer.
Erik Språngb6b1cac2018-08-09 16:12:54 +0200320 const int num_temporal_layers = DefaultNumberOfTemporalLayers(1);
321 int max_bitrate_bps;
322 if (!temporal_layers_supported) {
323 // Set the max bitrate to where the base layer would have been if temporal
324 // layer were enabled.
325 max_bitrate_bps = static_cast<int>(
326 kScreenshareHighStreamMaxBitrateBps *
327 webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
328 num_temporal_layers, 0));
329 } else if (DefaultNumberOfTemporalLayers(1) != 3 ||
330 webrtc::field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
331 // Experimental temporal layer mode used, use increased max bitrate.
332 max_bitrate_bps = kScreenshareHighStreamMaxBitrateBps;
333 } else {
334 // Keep current bitrates with default 3tl/8 frame settings.
335 // Lowest temporal layers of a 3 layer setup will have 40% of the total
336 // bitrate allocation for that simulcast layer. Make sure the gap between
337 // the target of the lower simulcast layer and first temporal layer of the
338 // higher one is at most 2x the bitrate, so that upswitching is not
339 // hampered by stalled bitrate estimates.
340 max_bitrate_bps = 2 * ((layers[0].target_bitrate_bps * 10) / 4);
341 }
342
Seth Hampson1370e302018-02-07 08:50:36 -0800343 // Cap max bitrate so it isn't overly high for the given resolution.
344 max_bitrate_bps = std::min<int>(max_bitrate_bps,
345 FindSimulcastMaxBitrateBps(width, height));
Seth Hampson1370e302018-02-07 08:50:36 -0800346 layers[1].width = width;
347 layers[1].height = height;
348 layers[1].max_qp = max_qp;
349 layers[1].max_framerate = max_framerate;
Erik Språngb6b1cac2018-08-09 16:12:54 +0200350 layers[1].num_temporal_layers =
351 temporal_layers_supported ? DefaultNumberOfTemporalLayers(1) : 0;
Seth Hampson1370e302018-02-07 08:50:36 -0800352 layers[1].min_bitrate_bps = layers[0].target_bitrate_bps * 2;
353 layers[1].target_bitrate_bps = max_bitrate_bps;
354 layers[1].max_bitrate_bps = max_bitrate_bps;
355 }
356
Seth Hampson24722b32017-12-22 09:36:42 -0800357 // The bitrate priority currently implemented on a per-sender level, so we
Seth Hampson1370e302018-02-07 08:50:36 -0800358 // just set it for the first simulcast layer.
359 layers[0].bitrate_priority = bitrate_priority;
360 return layers;
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000361}
362
buildbot@webrtc.orga8530772014-12-10 09:01:18 +0000363} // namespace cricket