1 /*
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
11 #include "modules/video_coding/utility/simulcast_utility.h"
12
13 #include <algorithm>
14 #include <cmath>
15
16 #include "rtc_base/checks.h"
17
18 namespace webrtc {
19
SumStreamMaxBitrate(int streams,const VideoCodec & codec)20 uint32_t SimulcastUtility::SumStreamMaxBitrate(int streams,
21 const VideoCodec& codec) {
22 uint32_t bitrate_sum = 0;
23 for (int i = 0; i < streams; ++i) {
24 bitrate_sum += codec.simulcastStream[i].maxBitrate;
25 }
26 return bitrate_sum;
27 }
28
NumberOfSimulcastStreams(const VideoCodec & codec)29 int SimulcastUtility::NumberOfSimulcastStreams(const VideoCodec& codec) {
30 int streams =
31 codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams;
32 uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec);
33 if (simulcast_max_bitrate == 0) {
34 streams = 1;
35 }
36 return streams;
37 }
38
ValidSimulcastParameters(const VideoCodec & codec,int num_streams)39 bool SimulcastUtility::ValidSimulcastParameters(const VideoCodec& codec,
40 int num_streams) {
41 // Check resolution.
42 if (codec.width != codec.simulcastStream[num_streams - 1].width ||
43 codec.height != codec.simulcastStream[num_streams - 1].height) {
44 return false;
45 }
46 for (int i = 0; i < num_streams; ++i) {
47 if (codec.width * codec.simulcastStream[i].height !=
48 codec.height * codec.simulcastStream[i].width) {
49 return false;
50 }
51 }
52 if (codec.codecType == webrtc::kVideoCodecVP8) {
53 for (int i = 1; i < num_streams; ++i) {
54 if (codec.simulcastStream[i].width < codec.simulcastStream[i - 1].width) {
55 return false;
56 }
57 }
58 } else {
59 // TODO(mirtad): H264 encoder implementation still assumes the default
60 // resolution downscaling is used.
61 for (int i = 1; i < num_streams; ++i) {
62 if (codec.simulcastStream[i].width !=
63 codec.simulcastStream[i - 1].width * 2) {
64 return false;
65 }
66 }
67 }
68
69 // Check frame-rate.
70 for (int i = 1; i < num_streams; ++i) {
71 if (fabs(codec.simulcastStream[i].maxFramerate -
72 codec.simulcastStream[i - 1].maxFramerate) > 1e-9) {
73 return false;
74 }
75 }
76
77 // Check temporal layers.
78 for (int i = 0; i < num_streams - 1; ++i) {
79 if (codec.simulcastStream[i].numberOfTemporalLayers !=
80 codec.simulcastStream[i + 1].numberOfTemporalLayers)
81 return false;
82 }
83 return true;
84 }
85
IsConferenceModeScreenshare(const VideoCodec & codec)86 bool SimulcastUtility::IsConferenceModeScreenshare(const VideoCodec& codec) {
87 if (codec.mode != VideoCodecMode::kScreensharing ||
88 NumberOfTemporalLayers(codec, 0) != 2) {
89 return false;
90 }
91
92 // Fixed default bitrates for legacy screenshare layers mode.
93 return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) ||
94 (codec.numberOfSimulcastStreams >= 1 &&
95 codec.simulcastStream[0].maxBitrate == 1000 &&
96 codec.simulcastStream[0].targetBitrate == 200);
97 }
98
NumberOfTemporalLayers(const VideoCodec & codec,int spatial_id)99 int SimulcastUtility::NumberOfTemporalLayers(const VideoCodec& codec,
100 int spatial_id) {
101 uint8_t num_temporal_layers =
102 std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
103 if (codec.numberOfSimulcastStreams > 0) {
104 RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
105 num_temporal_layers =
106 std::max(num_temporal_layers,
107 codec.simulcastStream[spatial_id].numberOfTemporalLayers);
108 }
109 return num_temporal_layers;
110 }
111
112 } // namespace webrtc
113