blob: 3c3e2358963a83d77e8ec0108f16ca9436586edd [file] [log] [blame]
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +02001/*
2 * Copyright (c) 2018 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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/video_coding/utility/simulcast_utility.h"
Erik Språng8abd56c2018-10-01 18:47:03 +020012
Jonas Olssona4d87372019-07-05 19:08:33 +020013#include <algorithm>
Ilya Nikolaevskiydda5fdc2019-02-27 10:00:06 +010014#include <cmath>
15
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "rtc_base/checks.h"
Erik Språngd7ee76c2019-08-02 16:32:24 +020017#include "rtc_base/experiments/experimental_screenshare_settings.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020018
19namespace webrtc {
20
21uint32_t SimulcastUtility::SumStreamMaxBitrate(int streams,
22 const VideoCodec& codec) {
23 uint32_t bitrate_sum = 0;
24 for (int i = 0; i < streams; ++i) {
25 bitrate_sum += codec.simulcastStream[i].maxBitrate;
26 }
27 return bitrate_sum;
28}
29
30int SimulcastUtility::NumberOfSimulcastStreams(const VideoCodec& codec) {
31 int streams =
32 codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams;
33 uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec);
34 if (simulcast_max_bitrate == 0) {
35 streams = 1;
36 }
37 return streams;
38}
39
Ilya Nikolaevskiydda5fdc2019-02-27 10:00:06 +010040bool SimulcastUtility::ValidSimulcastParameters(const VideoCodec& codec,
41 int num_streams) {
42 // Check resolution.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020043 if (codec.width != codec.simulcastStream[num_streams - 1].width ||
44 codec.height != codec.simulcastStream[num_streams - 1].height) {
45 return false;
46 }
47 for (int i = 0; i < num_streams; ++i) {
48 if (codec.width * codec.simulcastStream[i].height !=
49 codec.height * codec.simulcastStream[i].width) {
50 return false;
51 }
52 }
Mirta Dvornicic788f5772019-02-13 17:35:40 +010053 if (codec.codecType == webrtc::kVideoCodecVP8) {
54 for (int i = 1; i < num_streams; ++i) {
55 if (codec.simulcastStream[i].width < codec.simulcastStream[i - 1].width) {
56 return false;
57 }
58 }
59 } else {
60 // TODO(mirtad): H264 encoder implementation still assumes the default
61 // resolution downscaling is used.
62 for (int i = 1; i < num_streams; ++i) {
63 if (codec.simulcastStream[i].width !=
64 codec.simulcastStream[i - 1].width * 2) {
65 return false;
66 }
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020067 }
68 }
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020069
Ilya Nikolaevskiydda5fdc2019-02-27 10:00:06 +010070 // Check frame-rate.
71 for (int i = 1; i < num_streams; ++i) {
72 if (fabs(codec.simulcastStream[i].maxFramerate -
73 codec.simulcastStream[i - 1].maxFramerate) > 1e-9) {
74 return false;
75 }
76 }
77
78 // Check temporal layers.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020079 for (int i = 0; i < num_streams - 1; ++i) {
80 if (codec.simulcastStream[i].numberOfTemporalLayers !=
81 codec.simulcastStream[i + 1].numberOfTemporalLayers)
82 return false;
83 }
84 return true;
85}
86
Erik Språng8abd56c2018-10-01 18:47:03 +020087bool SimulcastUtility::IsConferenceModeScreenshare(const VideoCodec& codec) {
88 if (codec.mode != VideoCodecMode::kScreensharing ||
89 NumberOfTemporalLayers(codec, 0) != 2) {
90 return false;
91 }
Erik Språngd7ee76c2019-08-02 16:32:24 +020092
93 if (codec.numberOfSimulcastStreams > 0 &&
94 ExperimentalScreenshareSettings::ParseFromFieldTrials()
95 .DefaultTlInBaseLayer()
96 .value_or(false)) {
97 // Don't use ScreenshareLayers for base layer, regardless of flags.
98 return false;
99 }
100
Erik Språng8abd56c2018-10-01 18:47:03 +0200101 // Fixed default bitrates for legacy screenshare layers mode.
102 return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) ||
103 (codec.numberOfSimulcastStreams >= 1 &&
104 codec.simulcastStream[0].maxBitrate == 1000 &&
105 codec.simulcastStream[0].targetBitrate == 200);
106}
107
108int SimulcastUtility::NumberOfTemporalLayers(const VideoCodec& codec,
109 int spatial_id) {
110 uint8_t num_temporal_layers =
111 std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
112 if (codec.numberOfSimulcastStreams > 0) {
113 RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
114 num_temporal_layers =
115 std::max(num_temporal_layers,
116 codec.simulcastStream[spatial_id].numberOfTemporalLayers);
117 }
118 return num_temporal_layers;
119}
120
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200121} // namespace webrtc