• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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