OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <stdio.h> | 11 #include <stdio.h> |
12 | 12 |
13 #include "webrtc/base/arraysize.h" | 13 #include "webrtc/base/arraysize.h" |
14 #include "webrtc/base/common.h" | 14 #include "webrtc/base/common.h" |
15 #include "webrtc/base/logging.h" | 15 #include "webrtc/base/logging.h" |
16 #include "webrtc/media/base/streamparams.h" | 16 #include "webrtc/media/base/streamparams.h" |
17 #include "webrtc/media/engine/constants.h" | |
17 #include "webrtc/media/engine/simulcast.h" | 18 #include "webrtc/media/engine/simulcast.h" |
18 #include "webrtc/system_wrappers/include/field_trial.h" | 19 #include "webrtc/system_wrappers/include/field_trial.h" |
19 | 20 |
20 namespace cricket { | 21 namespace cricket { |
21 | 22 |
22 struct SimulcastFormat { | 23 struct SimulcastFormat { |
23 int width; | 24 int width; |
24 int height; | 25 int height; |
25 // The maximum number of simulcast layers can be used for | 26 // The maximum number of simulcast layers can be used for |
26 // resolutions at |widthxheigh|. | 27 // resolutions at |widthxheigh|. |
(...skipping 15 matching lines...) Expand all Loading... | |
42 const SimulcastFormat kSimulcastFormats[] = { | 43 const SimulcastFormat kSimulcastFormats[] = { |
43 {1920, 1080, 3, 5000, 4000, 800}, | 44 {1920, 1080, 3, 5000, 4000, 800}, |
44 {1280, 720, 3, 2500, 2500, 600}, | 45 {1280, 720, 3, 2500, 2500, 600}, |
45 {960, 540, 3, 900, 900, 450}, | 46 {960, 540, 3, 900, 900, 450}, |
46 {640, 360, 2, 700, 500, 150}, | 47 {640, 360, 2, 700, 500, 150}, |
47 {480, 270, 2, 450, 350, 150}, | 48 {480, 270, 2, 450, 350, 150}, |
48 {320, 180, 1, 200, 150, 30}, | 49 {320, 180, 1, 200, 150, 30}, |
49 {0, 0, 1, 200, 150, 30} | 50 {0, 0, 1, 200, 150, 30} |
50 }; | 51 }; |
51 | 52 |
53 const int kDefaultScreenshareSimulcastStreams = 2; | |
54 | |
52 // Multiway: Number of temporal layers for each simulcast stream, for maximum | 55 // Multiway: Number of temporal layers for each simulcast stream, for maximum |
53 // possible number of simulcast streams |kMaxSimulcastStreams|. The array | 56 // possible number of simulcast streams |kMaxSimulcastStreams|. The array |
54 // goes from lowest resolution at position 0 to highest resolution. | 57 // goes from lowest resolution at position 0 to highest resolution. |
55 // For example, first three elements correspond to say: QVGA, VGA, WHD. | 58 // For example, first three elements correspond to say: QVGA, VGA, WHD. |
56 static const int | 59 static const int |
57 kDefaultConferenceNumberOfTemporalLayers[webrtc::kMaxSimulcastStreams] = | 60 kDefaultConferenceNumberOfTemporalLayers[webrtc::kMaxSimulcastStreams] = |
58 {3, 3, 3, 3}; | 61 {3, 3, 3, 3}; |
59 | 62 |
60 void GetSimulcastSsrcs(const StreamParams& sp, std::vector<uint32_t>* ssrcs) { | 63 void GetSimulcastSsrcs(const StreamParams& sp, std::vector<uint32_t>* ssrcs) { |
61 const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics); | 64 const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics); |
(...skipping 10 matching lines...) Expand all Loading... | |
72 int temp = *width; | 75 int temp = *width; |
73 *width = *height; | 76 *width = *height; |
74 *height = temp; | 77 *height = temp; |
75 } | 78 } |
76 } | 79 } |
77 | 80 |
78 int FindSimulcastFormatIndex(int width, int height) { | 81 int FindSimulcastFormatIndex(int width, int height) { |
79 MaybeExchangeWidthHeight(&width, &height); | 82 MaybeExchangeWidthHeight(&width, &height); |
80 | 83 |
81 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) { | 84 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) { |
82 if (width >= kSimulcastFormats[i].width && | 85 if (width * height >= |
83 height >= kSimulcastFormats[i].height) { | 86 kSimulcastFormats[i].width * kSimulcastFormats[i].height) { |
84 return i; | 87 return i; |
85 } | 88 } |
86 } | 89 } |
87 return -1; | 90 return -1; |
88 } | 91 } |
89 | 92 |
90 int FindSimulcastFormatIndex(int width, int height, size_t max_layers) { | 93 int FindSimulcastFormatIndex(int width, int height, size_t max_layers) { |
91 MaybeExchangeWidthHeight(&width, &height); | 94 MaybeExchangeWidthHeight(&width, &height); |
92 | 95 |
93 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) { | 96 for (uint32_t i = 0; i < arraysize(kSimulcastFormats); ++i) { |
94 if (width >= kSimulcastFormats[i].width && | 97 if (width * height >= |
95 height >= kSimulcastFormats[i].height && | 98 kSimulcastFormats[i].width * kSimulcastFormats[i].height && |
96 max_layers == kSimulcastFormats[i].max_layers) { | 99 max_layers == kSimulcastFormats[i].max_layers) { |
97 return i; | 100 return i; |
98 } | 101 } |
99 } | 102 } |
100 return -1; | 103 return -1; |
101 } | 104 } |
102 | 105 |
103 // Simulcast stream width and height must both be dividable by | 106 // Simulcast stream width and height must both be dividable by |
104 // |2 ^ simulcast_layers - 1|. | 107 // |2 ^ simulcast_layers - 1|. |
105 int NormalizeSimulcastSize(int size, size_t simulcast_layers) { | 108 int NormalizeSimulcastSize(int size, size_t simulcast_layers) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 | 163 |
161 int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& streams) { | 164 int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& streams) { |
162 int total_max_bitrate_bps = 0; | 165 int total_max_bitrate_bps = 0; |
163 for (size_t s = 0; s < streams.size() - 1; ++s) { | 166 for (size_t s = 0; s < streams.size() - 1; ++s) { |
164 total_max_bitrate_bps += streams[s].target_bitrate_bps; | 167 total_max_bitrate_bps += streams[s].target_bitrate_bps; |
165 } | 168 } |
166 total_max_bitrate_bps += streams.back().max_bitrate_bps; | 169 total_max_bitrate_bps += streams.back().max_bitrate_bps; |
167 return total_max_bitrate_bps; | 170 return total_max_bitrate_bps; |
168 } | 171 } |
169 | 172 |
170 std::vector<webrtc::VideoStream> GetSimulcastConfig( | 173 std::vector<webrtc::VideoStream> GetSimulcastConfig(size_t max_streams, |
171 size_t max_streams, | 174 int width, |
172 int width, | 175 int height, |
173 int height, | 176 int max_bitrate_bps, |
174 int max_bitrate_bps, | 177 int max_qp, |
175 int max_qp, | 178 int max_framerate, |
176 int max_framerate) { | 179 bool is_screencast) { |
177 size_t simulcast_layers = FindSimulcastMaxLayers(width, height); | 180 size_t num_simulcast_layers; |
178 if (simulcast_layers > max_streams) { | 181 if (is_screencast) { |
182 num_simulcast_layers = | |
183 UseSimulcastScreenshare() ? kDefaultScreenshareSimulcastStreams : 1; | |
184 } else { | |
185 num_simulcast_layers = FindSimulcastMaxLayers(width, height); | |
186 } | |
187 | |
188 if (num_simulcast_layers > max_streams) { | |
179 // If the number of SSRCs in the group differs from our target | 189 // If the number of SSRCs in the group differs from our target |
180 // number of simulcast streams for current resolution, switch down | 190 // number of simulcast streams for current resolution, switch down |
181 // to a resolution that matches our number of SSRCs. | 191 // to a resolution that matches our number of SSRCs. |
182 if (!SlotSimulcastMaxResolution(max_streams, &width, &height)) { | 192 if (!SlotSimulcastMaxResolution(max_streams, &width, &height)) { |
183 return std::vector<webrtc::VideoStream>(); | 193 return std::vector<webrtc::VideoStream>(); |
184 } | 194 } |
185 simulcast_layers = max_streams; | 195 num_simulcast_layers = max_streams; |
186 } | 196 } |
187 std::vector<webrtc::VideoStream> streams; | 197 std::vector<webrtc::VideoStream> streams; |
188 streams.resize(simulcast_layers); | 198 streams.resize(num_simulcast_layers); |
189 | 199 |
190 // Format width and height has to be divisible by |2 ^ number_streams - 1|. | 200 if (!is_screencast) { |
191 width = NormalizeSimulcastSize(width, simulcast_layers); | 201 // Format width and height has to be divisible by |2 ^ number_streams - 1|. |
192 height = NormalizeSimulcastSize(height, simulcast_layers); | 202 width = NormalizeSimulcastSize(width, num_simulcast_layers); |
203 height = NormalizeSimulcastSize(height, num_simulcast_layers); | |
204 } | |
193 | 205 |
194 // Add simulcast sub-streams from lower resolution to higher resolutions. | 206 // Add simulcast sub-streams from lower resolution to higher resolutions. |
195 // Add simulcast streams, from highest resolution (|s| = number_streams -1) | 207 // Add simulcast streams, from highest resolution (|s| = number_streams -1) |
196 // to lowest resolution at |s| = 0. | 208 // to lowest resolution at |s| = 0. |
197 for (size_t s = simulcast_layers - 1;; --s) { | 209 for (size_t s = num_simulcast_layers - 1;; --s) { |
198 streams[s].width = width; | 210 streams[s].width = width; |
199 streams[s].height = height; | 211 streams[s].height = height; |
200 // TODO(pbos): Fill actual temporal-layer bitrate thresholds. | 212 // TODO(pbos): Fill actual temporal-layer bitrate thresholds. |
201 streams[s].temporal_layer_thresholds_bps.resize( | |
202 kDefaultConferenceNumberOfTemporalLayers[s] - 1); | |
203 streams[s].max_bitrate_bps = | |
204 FindSimulcastMaxBitrateBps(width, height, simulcast_layers); | |
205 streams[s].target_bitrate_bps = | |
206 FindSimulcastTargetBitrateBps(width, height, simulcast_layers); | |
207 streams[s].min_bitrate_bps = | |
208 FindSimulcastMinBitrateBps(width, height, simulcast_layers); | |
209 streams[s].max_qp = max_qp; | 213 streams[s].max_qp = max_qp; |
210 streams[s].max_framerate = max_framerate; | 214 if (is_screencast && s == 0) { |
215 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); | |
216 // For legacy screenshare in conference mode, tl0 and tl1 bitrates are | |
217 // piggybacked on the VideoCodec struct as target and max bitrates, | |
218 // respectively. See eg. webrtc::VP8EncoderImpl::SetRates(). | |
219 streams[s].min_bitrate_bps = kMinVideoBitrateKbps * 1000; | |
220 streams[s].target_bitrate_bps = config.tl0_bitrate_kbps * 1000; | |
221 streams[s].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; | |
222 streams[s].temporal_layer_thresholds_bps.clear(); | |
223 streams[s].temporal_layer_thresholds_bps.push_back( | |
224 config.tl0_bitrate_kbps * 1000); | |
225 streams[s].max_framerate = 5; | |
226 } else { | |
227 streams[s].temporal_layer_thresholds_bps.resize( | |
228 kDefaultConferenceNumberOfTemporalLayers[s] - 1); | |
229 streams[s].max_bitrate_bps = | |
230 FindSimulcastMaxBitrateBps(width, height, num_simulcast_layers + 1); | |
åsapersson
2017/01/16 13:43:50
now + 1? (and below)
sprang_webrtc
2017/01/16 16:39:10
Oops, that was left from experimentation. Though i
| |
231 streams[s].target_bitrate_bps = FindSimulcastTargetBitrateBps( | |
232 width, height, num_simulcast_layers + 1); | |
233 streams[s].min_bitrate_bps = | |
234 FindSimulcastMinBitrateBps(width, height, num_simulcast_layers + 1); | |
235 streams[s].max_framerate = max_framerate; | |
236 } | |
237 | |
211 width /= 2; | 238 width /= 2; |
212 height /= 2; | 239 height /= 2; |
213 if (s == 0) { | 240 if (s == 0) |
214 break; | 241 break; |
215 } | |
216 } | 242 } |
217 | 243 |
218 // Spend additional bits to boost the max stream. | 244 // Spend additional bits to boost the max stream. |
219 int bitrate_left_bps = max_bitrate_bps - GetTotalMaxBitrateBps(streams); | 245 int bitrate_left_bps = max_bitrate_bps - GetTotalMaxBitrateBps(streams); |
220 if (bitrate_left_bps > 0) { | 246 if (bitrate_left_bps > 0) { |
221 streams.back().max_bitrate_bps += bitrate_left_bps; | 247 streams.back().max_bitrate_bps += bitrate_left_bps; |
222 } | 248 } |
223 | 249 |
224 return streams; | 250 return streams; |
225 } | 251 } |
226 | 252 |
227 static const int kScreenshareMinBitrateKbps = 50; | 253 static const int kScreenshareMinBitrateKbps = 50; |
228 static const int kScreenshareMaxBitrateKbps = 6000; | 254 static const int kScreenshareMaxBitrateKbps = 6000; |
229 static const int kScreenshareDefaultTl0BitrateKbps = 200; | 255 static const int kScreenshareDefaultTl0BitrateKbps = 200; |
230 static const int kScreenshareDefaultTl1BitrateKbps = 1000; | 256 static const int kScreenshareDefaultTl1BitrateKbps = 1000; |
231 | 257 |
232 static const char* kScreencastLayerFieldTrialName = | 258 static const char* kScreencastLayerFieldTrialName = |
233 "WebRTC-ScreenshareLayerRates"; | 259 "WebRTC-ScreenshareLayerRates"; |
260 static const char* kSimulcastScreenshareFieldTrialName = | |
261 "WebRTC-SimulcastScreenshare"; | |
234 | 262 |
235 ScreenshareLayerConfig::ScreenshareLayerConfig(int tl0_bitrate, int tl1_bitrate) | 263 ScreenshareLayerConfig::ScreenshareLayerConfig(int tl0_bitrate, int tl1_bitrate) |
236 : tl0_bitrate_kbps(tl0_bitrate), tl1_bitrate_kbps(tl1_bitrate) { | 264 : tl0_bitrate_kbps(tl0_bitrate), tl1_bitrate_kbps(tl1_bitrate) { |
237 } | 265 } |
238 | 266 |
239 ScreenshareLayerConfig ScreenshareLayerConfig::GetDefault() { | 267 ScreenshareLayerConfig ScreenshareLayerConfig::GetDefault() { |
240 std::string group = | 268 std::string group = |
241 webrtc::field_trial::FindFullName(kScreencastLayerFieldTrialName); | 269 webrtc::field_trial::FindFullName(kScreencastLayerFieldTrialName); |
242 | 270 |
243 ScreenshareLayerConfig config(kScreenshareDefaultTl0BitrateKbps, | 271 ScreenshareLayerConfig config(kScreenshareDefaultTl0BitrateKbps, |
(...skipping 22 matching lines...) Expand all Loading... | |
266 tl1_bitrate > kScreenshareMaxBitrateKbps || tl0_bitrate > tl1_bitrate) { | 294 tl1_bitrate > kScreenshareMaxBitrateKbps || tl0_bitrate > tl1_bitrate) { |
267 return false; | 295 return false; |
268 } | 296 } |
269 | 297 |
270 config->tl0_bitrate_kbps = tl0_bitrate; | 298 config->tl0_bitrate_kbps = tl0_bitrate; |
271 config->tl1_bitrate_kbps = tl1_bitrate; | 299 config->tl1_bitrate_kbps = tl1_bitrate; |
272 | 300 |
273 return true; | 301 return true; |
274 } | 302 } |
275 | 303 |
304 bool UseSimulcastScreenshare() { | |
305 return webrtc::field_trial::FindFullName( | |
306 kSimulcastScreenshareFieldTrialName) == "Enabled"; | |
307 } | |
308 | |
276 } // namespace cricket | 309 } // namespace cricket |
OLD | NEW |