blob: b517455cca02b78d0549d451744c7dba007d57f5 [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
Erik Språng8abd56c2018-10-01 18:47:03 +020011#include <algorithm>
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include "common_types.h" // NOLINT(build/include)
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020014#include "modules/video_coding/utility/simulcast_utility.h"
Yves Gerey3e707812018-11-28 16:47:49 +010015#include "rtc_base/checks.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020016
17namespace webrtc {
18
19uint32_t SimulcastUtility::SumStreamMaxBitrate(int streams,
20 const VideoCodec& codec) {
21 uint32_t bitrate_sum = 0;
22 for (int i = 0; i < streams; ++i) {
23 bitrate_sum += codec.simulcastStream[i].maxBitrate;
24 }
25 return bitrate_sum;
26}
27
28int SimulcastUtility::NumberOfSimulcastStreams(const VideoCodec& codec) {
29 int streams =
30 codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams;
31 uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec);
32 if (simulcast_max_bitrate == 0) {
33 streams = 1;
34 }
35 return streams;
36}
37
38bool SimulcastUtility::ValidSimulcastResolutions(const VideoCodec& codec,
39 int num_streams) {
40 if (codec.width != codec.simulcastStream[num_streams - 1].width ||
41 codec.height != codec.simulcastStream[num_streams - 1].height) {
42 return false;
43 }
44 for (int i = 0; i < num_streams; ++i) {
45 if (codec.width * codec.simulcastStream[i].height !=
46 codec.height * codec.simulcastStream[i].width) {
47 return false;
48 }
49 }
Mirta Dvornicic788f5772019-02-13 17:35:40 +010050 if (codec.codecType == webrtc::kVideoCodecVP8) {
51 for (int i = 1; i < num_streams; ++i) {
52 if (codec.simulcastStream[i].width < codec.simulcastStream[i - 1].width) {
53 return false;
54 }
55 }
56 } else {
57 // TODO(mirtad): H264 encoder implementation still assumes the default
58 // resolution downscaling is used.
59 for (int i = 1; i < num_streams; ++i) {
60 if (codec.simulcastStream[i].width !=
61 codec.simulcastStream[i - 1].width * 2) {
62 return false;
63 }
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020064 }
65 }
66 return true;
67}
68
69bool SimulcastUtility::ValidSimulcastTemporalLayers(const VideoCodec& codec,
70 int num_streams) {
71 for (int i = 0; i < num_streams - 1; ++i) {
72 if (codec.simulcastStream[i].numberOfTemporalLayers !=
73 codec.simulcastStream[i + 1].numberOfTemporalLayers)
74 return false;
75 }
76 return true;
77}
78
Erik Språng8abd56c2018-10-01 18:47:03 +020079bool SimulcastUtility::IsConferenceModeScreenshare(const VideoCodec& codec) {
80 if (codec.mode != VideoCodecMode::kScreensharing ||
81 NumberOfTemporalLayers(codec, 0) != 2) {
82 return false;
83 }
84 // Fixed default bitrates for legacy screenshare layers mode.
85 return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) ||
86 (codec.numberOfSimulcastStreams >= 1 &&
87 codec.simulcastStream[0].maxBitrate == 1000 &&
88 codec.simulcastStream[0].targetBitrate == 200);
89}
90
91int SimulcastUtility::NumberOfTemporalLayers(const VideoCodec& codec,
92 int spatial_id) {
93 uint8_t num_temporal_layers =
94 std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
95 if (codec.numberOfSimulcastStreams > 0) {
96 RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
97 num_temporal_layers =
98 std::max(num_temporal_layers,
99 codec.simulcastStream[spatial_id].numberOfTemporalLayers);
100 }
101 return num_temporal_layers;
102}
103
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200104} // namespace webrtc