OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 <memory> | 11 #include <memory> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "gtest/gtest.h" | 14 #include "gtest/gtest.h" |
15 #include "vpx/vpx_encoder.h" | 15 #include "vpx/vpx_encoder.h" |
16 #include "vpx/vp8cx.h" | 16 #include "vpx/vp8cx.h" |
17 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 17 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
18 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" | 18 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" |
19 #include "webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h" | 19 #include "webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h" |
| 20 #include "webrtc/system_wrappers/include/clock.h" |
| 21 #include "webrtc/system_wrappers/include/metrics.h" |
| 22 #include "webrtc/test/histogram.h" |
20 | 23 |
21 using ::testing::_; | 24 using ::testing::_; |
22 using ::testing::NiceMock; | 25 using ::testing::NiceMock; |
23 using ::testing::Return; | 26 using ::testing::Return; |
24 | 27 |
25 namespace webrtc { | 28 namespace webrtc { |
26 | 29 |
27 // 5 frames per second at 90 kHz. | 30 // 5 frames per second at 90 kHz. |
28 const uint32_t kTimestampDelta5Fps = 90000 / 5; | 31 const uint32_t kTimestampDelta5Fps = 90000 / 5; |
29 const int kDefaultQp = 54; | 32 const int kDefaultQp = 54; |
30 const int kDefaultTl0BitrateKbps = 200; | 33 const int kDefaultTl0BitrateKbps = 200; |
31 const int kDefaultTl1BitrateKbps = 2000; | 34 const int kDefaultTl1BitrateKbps = 2000; |
32 const int kFrameRate = 5; | 35 const int kFrameRate = 5; |
33 const int kSyncPeriodSeconds = 5; | 36 const int kSyncPeriodSeconds = 5; |
34 const int kMaxSyncPeriodSeconds = 10; | 37 const int kMaxSyncPeriodSeconds = 10; |
35 | 38 |
36 class ScreenshareLayerTest : public ::testing::Test { | 39 class ScreenshareLayerTest : public ::testing::Test { |
37 protected: | 40 protected: |
38 ScreenshareLayerTest() : min_qp_(2), max_qp_(kDefaultQp), frame_size_(-1) {} | 41 ScreenshareLayerTest() |
| 42 : min_qp_(2), max_qp_(kDefaultQp), frame_size_(-1), clock_(1) {} |
39 virtual ~ScreenshareLayerTest() {} | 43 virtual ~ScreenshareLayerTest() {} |
40 | 44 |
| 45 void SetUp() override { layers_.reset(new ScreenshareLayers(2, 0, &clock_)); } |
| 46 |
41 void EncodeFrame(uint32_t timestamp, | 47 void EncodeFrame(uint32_t timestamp, |
42 bool base_sync, | 48 bool base_sync, |
43 CodecSpecificInfoVP8* vp8_info, | 49 CodecSpecificInfoVP8* vp8_info, |
44 int* flags) { | 50 int* flags) { |
45 *flags = layers_->EncodeFlags(timestamp); | 51 *flags = layers_->EncodeFlags(timestamp); |
46 if (*flags == -1) | 52 if (*flags == -1) |
47 return; | 53 return; |
48 layers_->PopulateCodecSpecific(base_sync, vp8_info, timestamp); | 54 layers_->PopulateCodecSpecific(base_sync, vp8_info, timestamp); |
49 ASSERT_NE(-1, frame_size_); | 55 ASSERT_NE(-1, frame_size_); |
50 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 56 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 return timestamp; | 104 return timestamp; |
99 } | 105 } |
100 } | 106 } |
101 ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time."; | 107 ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time."; |
102 return 0; | 108 return 0; |
103 } | 109 } |
104 | 110 |
105 int min_qp_; | 111 int min_qp_; |
106 int max_qp_; | 112 int max_qp_; |
107 int frame_size_; | 113 int frame_size_; |
| 114 SimulatedClock clock_; |
108 std::unique_ptr<ScreenshareLayers> layers_; | 115 std::unique_ptr<ScreenshareLayers> layers_; |
109 }; | 116 }; |
110 | 117 |
111 TEST_F(ScreenshareLayerTest, 1Layer) { | 118 TEST_F(ScreenshareLayerTest, 1Layer) { |
112 layers_.reset(new ScreenshareLayers(1, 0)); | 119 layers_.reset(new ScreenshareLayers(1, 0, &clock_)); |
113 ConfigureBitrates(); | 120 ConfigureBitrates(); |
114 int flags = 0; | 121 int flags = 0; |
115 uint32_t timestamp = 0; | 122 uint32_t timestamp = 0; |
116 CodecSpecificInfoVP8 vp8_info; | 123 CodecSpecificInfoVP8 vp8_info; |
117 // One layer screenshare should not use the frame dropper as all frames will | 124 // One layer screenshare should not use the frame dropper as all frames will |
118 // belong to the base layer. | 125 // belong to the base layer. |
119 const int kSingleLayerFlags = 0; | 126 const int kSingleLayerFlags = 0; |
120 flags = layers_->EncodeFlags(timestamp); | 127 flags = layers_->EncodeFlags(timestamp); |
121 EXPECT_EQ(kSingleLayerFlags, flags); | 128 EXPECT_EQ(kSingleLayerFlags, flags); |
122 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); | 129 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
123 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); | 130 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); |
124 EXPECT_FALSE(vp8_info.layerSync); | 131 EXPECT_FALSE(vp8_info.layerSync); |
125 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); | 132 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); |
126 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 133 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
127 flags = layers_->EncodeFlags(timestamp); | 134 flags = layers_->EncodeFlags(timestamp); |
128 EXPECT_EQ(kSingleLayerFlags, flags); | 135 EXPECT_EQ(kSingleLayerFlags, flags); |
129 timestamp += kTimestampDelta5Fps; | 136 timestamp += kTimestampDelta5Fps; |
130 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); | 137 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
131 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); | 138 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); |
132 EXPECT_FALSE(vp8_info.layerSync); | 139 EXPECT_FALSE(vp8_info.layerSync); |
133 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); | 140 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); |
134 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 141 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
135 } | 142 } |
136 | 143 |
137 TEST_F(ScreenshareLayerTest, 2Layer) { | 144 TEST_F(ScreenshareLayerTest, 2Layer) { |
138 layers_.reset(new ScreenshareLayers(2, 0)); | |
139 ConfigureBitrates(); | 145 ConfigureBitrates(); |
140 int flags = 0; | 146 int flags = 0; |
141 uint32_t timestamp = 0; | 147 uint32_t timestamp = 0; |
142 uint8_t expected_tl0_idx = 0; | 148 uint8_t expected_tl0_idx = 0; |
143 CodecSpecificInfoVP8 vp8_info; | 149 CodecSpecificInfoVP8 vp8_info; |
144 EncodeFrame(timestamp, false, &vp8_info, &flags); | 150 EncodeFrame(timestamp, false, &vp8_info, &flags); |
145 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); | 151 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); |
146 EXPECT_EQ(0, vp8_info.temporalIdx); | 152 EXPECT_EQ(0, vp8_info.temporalIdx); |
147 EXPECT_FALSE(vp8_info.layerSync); | 153 EXPECT_FALSE(vp8_info.layerSync); |
148 ++expected_tl0_idx; | 154 ++expected_tl0_idx; |
(...skipping 29 matching lines...) Expand all Loading... |
178 | 184 |
179 timestamp += kTimestampDelta5Fps; | 185 timestamp += kTimestampDelta5Fps; |
180 EncodeFrame(timestamp, false, &vp8_info, &flags); | 186 EncodeFrame(timestamp, false, &vp8_info, &flags); |
181 EXPECT_EQ(ScreenshareLayers::kTl1Flags, flags); | 187 EXPECT_EQ(ScreenshareLayers::kTl1Flags, flags); |
182 EXPECT_EQ(1, vp8_info.temporalIdx); | 188 EXPECT_EQ(1, vp8_info.temporalIdx); |
183 EXPECT_FALSE(vp8_info.layerSync); | 189 EXPECT_FALSE(vp8_info.layerSync); |
184 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); | 190 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); |
185 } | 191 } |
186 | 192 |
187 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) { | 193 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) { |
188 layers_.reset(new ScreenshareLayers(2, 0)); | |
189 ConfigureBitrates(); | 194 ConfigureBitrates(); |
190 int flags = 0; | 195 int flags = 0; |
191 uint32_t timestamp = 0; | 196 uint32_t timestamp = 0; |
192 CodecSpecificInfoVP8 vp8_info; | 197 CodecSpecificInfoVP8 vp8_info; |
193 std::vector<int> sync_times; | 198 std::vector<int> sync_times; |
194 | 199 |
195 const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1; | 200 const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1; |
196 for (int i = 0; i < kNumFrames; ++i) { | 201 for (int i = 0; i < kNumFrames; ++i) { |
197 timestamp += kTimestampDelta5Fps; | 202 timestamp += kTimestampDelta5Fps; |
198 EncodeFrame(timestamp, false, &vp8_info, &flags); | 203 EncodeFrame(timestamp, false, &vp8_info, &flags); |
199 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) { | 204 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) { |
200 sync_times.push_back(timestamp); | 205 sync_times.push_back(timestamp); |
201 } | 206 } |
202 } | 207 } |
203 | 208 |
204 ASSERT_EQ(2u, sync_times.size()); | 209 ASSERT_EQ(2u, sync_times.size()); |
205 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds); | 210 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds); |
206 } | 211 } |
207 | 212 |
208 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) { | 213 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) { |
209 layers_.reset(new ScreenshareLayers(2, 0)); | |
210 ConfigureBitrates(); | 214 ConfigureBitrates(); |
211 uint32_t timestamp = 0; | 215 uint32_t timestamp = 0; |
212 CodecSpecificInfoVP8 vp8_info; | 216 CodecSpecificInfoVP8 vp8_info; |
213 std::vector<int> sync_times; | 217 std::vector<int> sync_times; |
214 | 218 |
215 const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1; | 219 const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1; |
216 for (int i = 0; i < kNumFrames; ++i) { | 220 for (int i = 0; i < kNumFrames; ++i) { |
217 timestamp += kTimestampDelta5Fps; | 221 timestamp += kTimestampDelta5Fps; |
218 layers_->EncodeFlags(timestamp); | 222 layers_->EncodeFlags(timestamp); |
219 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); | 223 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
220 | 224 |
221 // Simulate TL1 being at least 8 qp steps better. | 225 // Simulate TL1 being at least 8 qp steps better. |
222 if (vp8_info.temporalIdx == 0) { | 226 if (vp8_info.temporalIdx == 0) { |
223 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 227 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
224 } else { | 228 } else { |
225 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); | 229 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8); |
226 } | 230 } |
227 | 231 |
228 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) | 232 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) |
229 sync_times.push_back(timestamp); | 233 sync_times.push_back(timestamp); |
230 } | 234 } |
231 | 235 |
232 ASSERT_EQ(2u, sync_times.size()); | 236 ASSERT_EQ(2u, sync_times.size()); |
233 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds); | 237 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds); |
234 } | 238 } |
235 | 239 |
236 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) { | 240 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) { |
237 layers_.reset(new ScreenshareLayers(2, 0)); | |
238 ConfigureBitrates(); | 241 ConfigureBitrates(); |
239 uint32_t timestamp = 0; | 242 uint32_t timestamp = 0; |
240 CodecSpecificInfoVP8 vp8_info; | 243 CodecSpecificInfoVP8 vp8_info; |
241 std::vector<int> sync_times; | 244 std::vector<int> sync_times; |
242 | 245 |
243 const int kNumFrames = (kSyncPeriodSeconds + | 246 const int kNumFrames = (kSyncPeriodSeconds + |
244 ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) * | 247 ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) * |
245 kFrameRate; | 248 kFrameRate; |
246 for (int i = 0; i < kNumFrames; ++i) { | 249 for (int i = 0; i < kNumFrames; ++i) { |
247 timestamp += kTimestampDelta5Fps; | 250 timestamp += kTimestampDelta5Fps; |
(...skipping 29 matching lines...) Expand all Loading... |
277 EXPECT_TRUE(vp8_info.layerSync); | 280 EXPECT_TRUE(vp8_info.layerSync); |
278 EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags); | 281 EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags); |
279 return; | 282 return; |
280 } | 283 } |
281 } | 284 } |
282 } | 285 } |
283 ADD_FAILURE() << "No TL1 frame arrived within time limit."; | 286 ADD_FAILURE() << "No TL1 frame arrived within time limit."; |
284 } | 287 } |
285 | 288 |
286 TEST_F(ScreenshareLayerTest, 2LayersToggling) { | 289 TEST_F(ScreenshareLayerTest, 2LayersToggling) { |
287 layers_.reset(new ScreenshareLayers(2, 0)); | |
288 ConfigureBitrates(); | 290 ConfigureBitrates(); |
289 int flags = 0; | 291 int flags = 0; |
290 CodecSpecificInfoVP8 vp8_info; | 292 CodecSpecificInfoVP8 vp8_info; |
291 uint32_t timestamp = RunGracePeriod(); | 293 uint32_t timestamp = RunGracePeriod(); |
292 | 294 |
293 // Insert 50 frames. 2/5 should be TL0. | 295 // Insert 50 frames. 2/5 should be TL0. |
294 int tl0_frames = 0; | 296 int tl0_frames = 0; |
295 int tl1_frames = 0; | 297 int tl1_frames = 0; |
296 for (int i = 0; i < 50; ++i) { | 298 for (int i = 0; i < 50; ++i) { |
297 timestamp += kTimestampDelta5Fps; | 299 timestamp += kTimestampDelta5Fps; |
298 EncodeFrame(timestamp, false, &vp8_info, &flags); | 300 EncodeFrame(timestamp, false, &vp8_info, &flags); |
299 switch (vp8_info.temporalIdx) { | 301 switch (vp8_info.temporalIdx) { |
300 case 0: | 302 case 0: |
301 ++tl0_frames; | 303 ++tl0_frames; |
302 break; | 304 break; |
303 case 1: | 305 case 1: |
304 ++tl1_frames; | 306 ++tl1_frames; |
305 break; | 307 break; |
306 default: | 308 default: |
307 abort(); | 309 abort(); |
308 } | 310 } |
309 } | 311 } |
310 EXPECT_EQ(20, tl0_frames); | 312 EXPECT_EQ(20, tl0_frames); |
311 EXPECT_EQ(30, tl1_frames); | 313 EXPECT_EQ(30, tl1_frames); |
312 } | 314 } |
313 | 315 |
314 TEST_F(ScreenshareLayerTest, AllFitsLayer0) { | 316 TEST_F(ScreenshareLayerTest, AllFitsLayer0) { |
315 layers_.reset(new ScreenshareLayers(2, 0)); | |
316 ConfigureBitrates(); | 317 ConfigureBitrates(); |
317 frame_size_ = ((kDefaultTl0BitrateKbps * 1000) / 8) / kFrameRate; | 318 frame_size_ = ((kDefaultTl0BitrateKbps * 1000) / 8) / kFrameRate; |
318 | 319 |
319 int flags = 0; | 320 int flags = 0; |
320 uint32_t timestamp = 0; | 321 uint32_t timestamp = 0; |
321 CodecSpecificInfoVP8 vp8_info; | 322 CodecSpecificInfoVP8 vp8_info; |
322 // Insert 50 frames, small enough that all fits in TL0. | 323 // Insert 50 frames, small enough that all fits in TL0. |
323 for (int i = 0; i < 50; ++i) { | 324 for (int i = 0; i < 50; ++i) { |
324 EncodeFrame(timestamp, false, &vp8_info, &flags); | 325 EncodeFrame(timestamp, false, &vp8_info, &flags); |
325 timestamp += kTimestampDelta5Fps; | 326 timestamp += kTimestampDelta5Fps; |
326 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); | 327 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags); |
327 EXPECT_EQ(0, vp8_info.temporalIdx); | 328 EXPECT_EQ(0, vp8_info.temporalIdx); |
328 } | 329 } |
329 } | 330 } |
330 | 331 |
331 TEST_F(ScreenshareLayerTest, TooHighBitrate) { | 332 TEST_F(ScreenshareLayerTest, TooHighBitrate) { |
332 layers_.reset(new ScreenshareLayers(2, 0)); | |
333 ConfigureBitrates(); | 333 ConfigureBitrates(); |
334 frame_size_ = 2 * ((kDefaultTl1BitrateKbps * 1000) / 8) / kFrameRate; | 334 frame_size_ = 2 * ((kDefaultTl1BitrateKbps * 1000) / 8) / kFrameRate; |
335 int flags = 0; | 335 int flags = 0; |
336 CodecSpecificInfoVP8 vp8_info; | 336 CodecSpecificInfoVP8 vp8_info; |
337 uint32_t timestamp = RunGracePeriod(); | 337 uint32_t timestamp = RunGracePeriod(); |
338 | 338 |
339 // Insert 100 frames. Half should be dropped. | 339 // Insert 100 frames. Half should be dropped. |
340 int tl0_frames = 0; | 340 int tl0_frames = 0; |
341 int tl1_frames = 0; | 341 int tl1_frames = 0; |
342 int dropped_frames = 0; | 342 int dropped_frames = 0; |
(...skipping 15 matching lines...) Expand all Loading... |
358 } | 358 } |
359 } | 359 } |
360 } | 360 } |
361 | 361 |
362 EXPECT_EQ(5, tl0_frames); | 362 EXPECT_EQ(5, tl0_frames); |
363 EXPECT_EQ(45, tl1_frames); | 363 EXPECT_EQ(45, tl1_frames); |
364 EXPECT_EQ(50, dropped_frames); | 364 EXPECT_EQ(50, dropped_frames); |
365 } | 365 } |
366 | 366 |
367 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) { | 367 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) { |
368 layers_.reset(new ScreenshareLayers(2, 0)); | |
369 | |
370 vpx_codec_enc_cfg_t cfg; | 368 vpx_codec_enc_cfg_t cfg; |
371 layers_->ConfigureBitrates(100, 1000, 5, &cfg); | 369 layers_->ConfigureBitrates(100, 1000, 5, &cfg); |
372 | 370 |
373 EXPECT_EQ(static_cast<unsigned int>( | 371 EXPECT_EQ(static_cast<unsigned int>( |
374 ScreenshareLayers::kMaxTL0FpsReduction * 100 + 0.5), | 372 ScreenshareLayers::kMaxTL0FpsReduction * 100 + 0.5), |
375 cfg.rc_target_bitrate); | 373 cfg.rc_target_bitrate); |
376 } | 374 } |
377 | 375 |
378 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) { | 376 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) { |
379 layers_.reset(new ScreenshareLayers(2, 0)); | |
380 vpx_codec_enc_cfg_t cfg; | 377 vpx_codec_enc_cfg_t cfg; |
381 layers_->ConfigureBitrates(100, 450, 5, &cfg); | 378 layers_->ConfigureBitrates(100, 450, 5, &cfg); |
382 | 379 |
383 EXPECT_EQ(static_cast<unsigned int>( | 380 EXPECT_EQ(static_cast<unsigned int>( |
384 450 / ScreenshareLayers::kAcceptableTargetOvershoot), | 381 450 / ScreenshareLayers::kAcceptableTargetOvershoot), |
385 cfg.rc_target_bitrate); | 382 cfg.rc_target_bitrate); |
386 } | 383 } |
387 | 384 |
388 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) { | 385 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) { |
389 layers_.reset(new ScreenshareLayers(2, 0)); | |
390 vpx_codec_enc_cfg_t cfg; | 386 vpx_codec_enc_cfg_t cfg; |
391 layers_->ConfigureBitrates(100, 100, 5, &cfg); | 387 layers_->ConfigureBitrates(100, 100, 5, &cfg); |
392 | 388 |
393 EXPECT_EQ(100U, cfg.rc_target_bitrate); | 389 EXPECT_EQ(100U, cfg.rc_target_bitrate); |
394 } | 390 } |
395 | 391 |
396 TEST_F(ScreenshareLayerTest, EncoderDrop) { | 392 TEST_F(ScreenshareLayerTest, EncoderDrop) { |
397 layers_.reset(new ScreenshareLayers(2, 0)); | |
398 ConfigureBitrates(); | 393 ConfigureBitrates(); |
399 CodecSpecificInfoVP8 vp8_info; | 394 CodecSpecificInfoVP8 vp8_info; |
400 vpx_codec_enc_cfg_t cfg; | 395 vpx_codec_enc_cfg_t cfg; |
401 cfg.rc_max_quantizer = kDefaultQp; | 396 cfg.rc_max_quantizer = kDefaultQp; |
402 | 397 |
403 uint32_t timestamp = RunGracePeriod(); | 398 uint32_t timestamp = RunGracePeriod(); |
404 timestamp = SkipUntilTl(0, timestamp); | 399 timestamp = SkipUntilTl(0, timestamp); |
405 | 400 |
406 // Size 0 indicates dropped frame. | 401 // Size 0 indicates dropped frame. |
407 layers_->FrameEncoded(0, timestamp, kDefaultQp); | 402 layers_->FrameEncoded(0, timestamp, kDefaultQp); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 434 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
440 | 435 |
441 layers_->EncodeFlags(timestamp); | 436 layers_->EncodeFlags(timestamp); |
442 timestamp += kTimestampDelta5Fps; | 437 timestamp += kTimestampDelta5Fps; |
443 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); | 438 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg)); |
444 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); | 439 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); |
445 EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); | 440 EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp)); |
446 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); | 441 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp); |
447 } | 442 } |
448 | 443 |
| 444 TEST_F(ScreenshareLayerTest, UpdatesHistograms) { |
| 445 ConfigureBitrates(); |
| 446 vpx_codec_enc_cfg_t cfg; |
| 447 cfg.rc_max_quantizer = kDefaultQp; |
| 448 bool trigger_drop = false; |
| 449 bool dropped_frame = false; |
| 450 bool overshoot = false; |
| 451 const int kTl0Qp = 35; |
| 452 const int kTl1Qp = 30; |
| 453 for (int64_t timestamp = 0; |
| 454 timestamp < kTimestampDelta5Fps * 5 * metrics::kMinRunTimeInSeconds; |
| 455 timestamp += kTimestampDelta5Fps) { |
| 456 int flags = layers_->EncodeFlags(timestamp); |
| 457 if (flags != -1) |
| 458 layers_->UpdateConfiguration(&cfg); |
| 459 |
| 460 if (timestamp >= kTimestampDelta5Fps * 5 && !overshoot && flags != -1) { |
| 461 // Simulate one overshoot. |
| 462 layers_->FrameEncoded(0, timestamp, 0); |
| 463 overshoot = true; |
| 464 flags = layers_->EncodeFlags(timestamp); |
| 465 } |
| 466 |
| 467 if (flags == ScreenshareLayers::kTl0Flags) { |
| 468 if (timestamp >= kTimestampDelta5Fps * 20 && !trigger_drop) { |
| 469 // Simulate a too large frame, to cause frame drop. |
| 470 layers_->FrameEncoded(frame_size_ * 5, timestamp, kTl0Qp); |
| 471 trigger_drop = true; |
| 472 } else { |
| 473 layers_->FrameEncoded(frame_size_, timestamp, kTl0Qp); |
| 474 } |
| 475 } else if (flags == ScreenshareLayers::kTl1Flags || |
| 476 flags == ScreenshareLayers::kTl1SyncFlags) { |
| 477 layers_->FrameEncoded(frame_size_, timestamp, kTl1Qp); |
| 478 } else if (flags == -1) { |
| 479 dropped_frame = true; |
| 480 } else { |
| 481 RTC_NOTREACHED() << "Unexpected flags"; |
| 482 } |
| 483 clock_.AdvanceTimeMilliseconds(1000 / 5); |
| 484 } |
| 485 |
| 486 EXPECT_TRUE(overshoot); |
| 487 EXPECT_TRUE(dropped_frame); |
| 488 |
| 489 layers_.reset(); // Histograms are reported on destruction. |
| 490 |
| 491 EXPECT_EQ(1, test::NumHistogramSamples( |
| 492 "WebRTC.Video.Screenshare.Layer0.FrameRate")); |
| 493 EXPECT_EQ(1, test::NumHistogramSamples( |
| 494 "WebRTC.Video.Screenshare.Layer1.FrameRate")); |
| 495 EXPECT_EQ( |
| 496 1, test::NumHistogramSamples("WebRTC.Video.Screenshare.FramesPerDrop")); |
| 497 EXPECT_EQ(1, test::NumHistogramSamples( |
| 498 "WebRTC.Video.Screenshare.FramesPerOvershoot")); |
| 499 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Screenshare.Layer0.Qp")); |
| 500 EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Screenshare.Layer1.Qp")); |
| 501 EXPECT_EQ(1, test::NumHistogramSamples( |
| 502 "WebRTC.Video.Screenshare.Layer0.TargetBitrate")); |
| 503 EXPECT_EQ(1, test::NumHistogramSamples( |
| 504 "WebRTC.Video.Screenshare.Layer1.TargetBitrate")); |
| 505 |
| 506 EXPECT_GT( |
| 507 test::LastHistogramSample("WebRTC.Video.Screenshare.Layer0.FrameRate"), |
| 508 1); |
| 509 EXPECT_GT( |
| 510 test::LastHistogramSample("WebRTC.Video.Screenshare.Layer1.FrameRate"), |
| 511 1); |
| 512 EXPECT_GT(test::LastHistogramSample("WebRTC.Video.Screenshare.FramesPerDrop"), |
| 513 1); |
| 514 EXPECT_GT( |
| 515 test::LastHistogramSample("WebRTC.Video.Screenshare.FramesPerOvershoot"), |
| 516 1); |
| 517 EXPECT_EQ(kTl0Qp, |
| 518 test::LastHistogramSample("WebRTC.Video.Screenshare.Layer0.Qp")); |
| 519 EXPECT_EQ(kTl1Qp, |
| 520 test::LastHistogramSample("WebRTC.Video.Screenshare.Layer1.Qp")); |
| 521 EXPECT_EQ(kDefaultTl0BitrateKbps, |
| 522 test::LastHistogramSample( |
| 523 "WebRTC.Video.Screenshare.Layer0.TargetBitrate")); |
| 524 EXPECT_EQ(kDefaultTl1BitrateKbps, |
| 525 test::LastHistogramSample( |
| 526 "WebRTC.Video.Screenshare.Layer1.TargetBitrate")); |
| 527 } |
| 528 |
449 } // namespace webrtc | 529 } // namespace webrtc |
OLD | NEW |