Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: webrtc/modules/video_coding/codecs/vp8/screenshare_layers_unittest.cc

Issue 1193513006: In screenshare mode, suppress VP8 bitrate overshoot and increase quality (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "gtest/gtest.h" 11 #include "gtest/gtest.h"
12 #include "vpx/vpx_encoder.h" 12 #include "vpx/vpx_encoder.h"
13 #include "vpx/vp8cx.h" 13 #include "vpx/vp8cx.h"
14 #include "webrtc/base/scoped_ptr.h" 14 #include "webrtc/base/scoped_ptr.h"
15 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" 15 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
16 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h" 16 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h"
17 #include "webrtc/modules/video_coding/utility/include/mock/mock_frame_dropper.h" 17 #include "webrtc/modules/video_coding/utility/include/mock/mock_frame_dropper.h"
18 18
19 using ::testing::_; 19 using ::testing::_;
20 using ::testing::NiceMock; 20 using ::testing::NiceMock;
21 using ::testing::Return; 21 using ::testing::Return;
22 22
23 namespace webrtc { 23 namespace webrtc {
24 24
25 enum { kTimestampDelta5Fps = 90000 / 5 }; // 5 frames per second at 90 kHz. 25 // 5 frames per second at 90 kHz.
26 enum { kTimestampDelta30Fps = 90000 / 30 }; // 30 frames per second at 90 kHz. 26 const uint32_t kTimestampDelta5Fps = 90000 / 5;
27 enum { kFrameSize = 2500 }; 27 const int kDefaultQp = 54;
28 28 const int kDefaultTl0BitrateKbps = 200;
29 const int kFlagsTL0 = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 29 const int kDefaultTl1BitrateKbps = 2000;
30 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF; 30 const int kFrameRate = 5;
31 const int kFlagsTL1 = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | 31 const int kSyncPeriodSeconds = 5;
32 VP8_EFLAG_NO_UPD_LAST; 32 const int kMaxSyncPeriodSeconds = 10;
33 const int kFlagsTL1Sync = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF |
34 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
35
36 class ScreenshareLayersFT : public ScreenshareLayers {
37 public:
38 ScreenshareLayersFT(int num_temporal_layers,
39 uint8_t initial_tl0_pic_idx,
40 FrameDropper* tl0_frame_dropper,
41 FrameDropper* tl1_frame_dropper)
42 : ScreenshareLayers(num_temporal_layers,
43 initial_tl0_pic_idx,
44 tl0_frame_dropper,
45 tl1_frame_dropper) {}
46 virtual ~ScreenshareLayersFT() {}
47 };
48 33
49 class ScreenshareLayerTest : public ::testing::Test { 34 class ScreenshareLayerTest : public ::testing::Test {
50 protected: 35 protected:
51 void SetEncodeExpectations(bool drop_tl0, bool drop_tl1, int framerate) { 36 ScreenshareLayerTest() : min_qp_(2), max_qp_(kDefaultQp), frame_size_(-1) {}
52 EXPECT_CALL(tl0_frame_dropper_, DropFrame()) 37 virtual ~ScreenshareLayerTest() {}
53 .Times(1)
54 .WillRepeatedly(Return(drop_tl0));
55 if (drop_tl0) {
56 EXPECT_CALL(tl1_frame_dropper_, DropFrame())
57 .Times(1)
58 .WillRepeatedly(Return(drop_tl1));
59 }
60 EXPECT_CALL(tl0_frame_dropper_, Leak(framerate))
61 .Times(1);
62 EXPECT_CALL(tl1_frame_dropper_, Leak(framerate))
63 .Times(1);
64 if (drop_tl0) {
65 EXPECT_CALL(tl0_frame_dropper_, Fill(_, _))
66 .Times(0);
67 if (drop_tl1) {
68 EXPECT_CALL(tl1_frame_dropper_, Fill(_, _))
69 .Times(0);
70 } else {
71 EXPECT_CALL(tl1_frame_dropper_, Fill(kFrameSize, true))
72 .Times(1);
73 }
74 } else {
75 EXPECT_CALL(tl0_frame_dropper_, Fill(kFrameSize, true))
76 .Times(1);
77 EXPECT_CALL(tl1_frame_dropper_, Fill(kFrameSize, true))
78 .Times(1);
79 }
80 }
81 38
82 void EncodeFrame(uint32_t timestamp, 39 void EncodeFrame(uint32_t timestamp,
83 bool base_sync, 40 bool base_sync,
84 CodecSpecificInfoVP8* vp8_info, 41 CodecSpecificInfoVP8* vp8_info,
85 int* flags) { 42 int* flags) {
86 *flags = layers_->EncodeFlags(timestamp); 43 *flags = layers_->EncodeFlags(timestamp);
87 layers_->PopulateCodecSpecific(base_sync, vp8_info, timestamp); 44 layers_->PopulateCodecSpecific(base_sync, vp8_info, timestamp);
88 layers_->FrameEncoded(kFrameSize, timestamp); 45 ASSERT_NE(-1, frame_size_);
46 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
89 } 47 }
90 48
91 NiceMock<MockFrameDropper> tl0_frame_dropper_; 49 void ConfigureBitrates() {
92 NiceMock<MockFrameDropper> tl1_frame_dropper_; 50 vpx_codec_enc_cfg_t vpx_cfg;
93 rtc::scoped_ptr<ScreenshareLayersFT> layers_; 51 memset(&vpx_cfg, 0, sizeof(vpx_codec_enc_cfg_t));
52 vpx_cfg.rc_min_quantizer = min_qp_;
53 vpx_cfg.rc_max_quantizer = max_qp_;
54 EXPECT_TRUE(layers_->ConfigureBitrates(
55 kDefaultTl0BitrateKbps, kDefaultTl1BitrateKbps, kFrameRate, &vpx_cfg));
56 frame_size_ = ((vpx_cfg.rc_target_bitrate * 1000) / 8) / kFrameRate;
57 }
58
59 void WithQpLimits(int min_qp, int max_qp) {
60 min_qp_ = min_qp;
61 max_qp_ = max_qp;
62 }
63
64 int RunGracePeriod() {
65 int flags = 0;
66 uint32_t timestamp = 0;
67 CodecSpecificInfoVP8 vp8_info;
68 bool got_tl0 = false;
69 bool got_tl1 = false;
70 for (int i = 0; i < 10; ++i) {
71 EncodeFrame(timestamp, false, &vp8_info, &flags);
72 timestamp += kTimestampDelta5Fps;
73 if (vp8_info.temporalIdx == 0) {
74 got_tl0 = true;
75 } else {
76 got_tl1 = true;
77 }
78 if (got_tl0 && got_tl1)
79 return timestamp;
80 }
81 ADD_FAILURE() << "Frames from both layers not received in time.";
82 return 0;
83 }
84
85 int SkipUntilTl(int layer, int timestamp) {
86 CodecSpecificInfoVP8 vp8_info;
87 for (int i = 0; i < 5; ++i) {
88 layers_->EncodeFlags(timestamp);
89 timestamp += kTimestampDelta5Fps;
90 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
91 if (vp8_info.temporalIdx != layer) {
92 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
93 } else {
94 return timestamp;
95 }
96 }
97 ADD_FAILURE() << "Did not get a frame of TL" << layer << " in time.";
98 return 0;
99 }
100
101 int min_qp_;
102 int max_qp_;
103 int frame_size_;
104 rtc::scoped_ptr<ScreenshareLayers> layers_;
94 }; 105 };
95 106
96 TEST_F(ScreenshareLayerTest, 1Layer) { 107 TEST_F(ScreenshareLayerTest, 1Layer) {
97 layers_.reset( 108 layers_.reset(new ScreenshareLayers(1, 0));
98 new ScreenshareLayersFT(1, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); 109 ConfigureBitrates();
99 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL));
100 int flags = 0; 110 int flags = 0;
101 uint32_t timestamp = 0; 111 uint32_t timestamp = 0;
102 CodecSpecificInfoVP8 vp8_info; 112 CodecSpecificInfoVP8 vp8_info;
103 // One layer screenshare should not use the frame dropper as all frames will 113 // One layer screenshare should not use the frame dropper as all frames will
104 // belong to the base layer. 114 // belong to the base layer.
105 EXPECT_CALL(tl0_frame_dropper_, DropFrame())
106 .Times(0);
107 EXPECT_CALL(tl1_frame_dropper_, DropFrame())
108 .Times(0);
109 flags = layers_->EncodeFlags(timestamp); 115 flags = layers_->EncodeFlags(timestamp);
110 EXPECT_EQ(0, flags); 116 EXPECT_EQ(0, flags);
111 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); 117 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
112 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); 118 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx);
113 EXPECT_FALSE(vp8_info.layerSync); 119 EXPECT_FALSE(vp8_info.layerSync);
114 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); 120 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx);
115 layers_->FrameEncoded(kFrameSize, timestamp); 121 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
116
117 EXPECT_CALL(tl0_frame_dropper_, DropFrame())
118 .Times(0);
119 EXPECT_CALL(tl1_frame_dropper_, DropFrame())
120 .Times(0);
121 flags = layers_->EncodeFlags(timestamp); 122 flags = layers_->EncodeFlags(timestamp);
122 EXPECT_EQ(0, flags); 123 EXPECT_EQ(0, flags);
123 timestamp += kTimestampDelta5Fps; 124 timestamp += kTimestampDelta5Fps;
124 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp); 125 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
125 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx); 126 EXPECT_EQ(static_cast<uint8_t>(kNoTemporalIdx), vp8_info.temporalIdx);
126 EXPECT_FALSE(vp8_info.layerSync); 127 EXPECT_FALSE(vp8_info.layerSync);
127 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx); 128 EXPECT_EQ(kNoTl0PicIdx, vp8_info.tl0PicIdx);
128 layers_->FrameEncoded(kFrameSize, timestamp); 129 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
129 } 130 }
130 131
131 TEST_F(ScreenshareLayerTest, 2Layer) { 132 TEST_F(ScreenshareLayerTest, 2Layer) {
132 layers_.reset( 133 layers_.reset(new ScreenshareLayers(2, 0));
133 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); 134 ConfigureBitrates();
134 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL));
135 int flags = 0; 135 int flags = 0;
136 uint32_t timestamp = 0; 136 uint32_t timestamp = 0;
137 uint8_t expected_tl0_idx = 0; 137 uint8_t expected_tl0_idx = 0;
138 CodecSpecificInfoVP8 vp8_info; 138 CodecSpecificInfoVP8 vp8_info;
139 SetEncodeExpectations(false, false, 1); 139 EncodeFrame(timestamp, false, &vp8_info, &flags);
140 EncodeFrame(timestamp, false, &vp8_info, &flags); 140 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags);
141 EXPECT_EQ(kFlagsTL0, flags);
142 EXPECT_EQ(0, vp8_info.temporalIdx); 141 EXPECT_EQ(0, vp8_info.temporalIdx);
143 EXPECT_FALSE(vp8_info.layerSync); 142 EXPECT_FALSE(vp8_info.layerSync);
144 ++expected_tl0_idx; 143 ++expected_tl0_idx;
145 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 144 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
146 145
147 EXPECT_CALL(tl1_frame_dropper_, SetRates(1000, 1)) 146 // Insert 5 frames, cover grace period. All should be in TL0.
148 .Times(1);
149 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, -1, NULL));
150 // Insert 5 frames at 30 fps. All should belong to TL0.
151 for (int i = 0; i < 5; ++i) { 147 for (int i = 0; i < 5; ++i) {
152 timestamp += kTimestampDelta30Fps; 148 timestamp += kTimestampDelta5Fps;
153 // First iteration has a framerate based on a single frame, thus 1.
154 SetEncodeExpectations(false, false, 30);
155 EncodeFrame(timestamp, false, &vp8_info, &flags); 149 EncodeFrame(timestamp, false, &vp8_info, &flags);
156 EXPECT_EQ(0, vp8_info.temporalIdx); 150 EXPECT_EQ(0, vp8_info.temporalIdx);
157 EXPECT_FALSE(vp8_info.layerSync); 151 EXPECT_FALSE(vp8_info.layerSync);
158 ++expected_tl0_idx; 152 ++expected_tl0_idx;
159 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 153 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
160 } 154 }
155
156 // First frame in TL0.
157 timestamp += kTimestampDelta5Fps;
158 EncodeFrame(timestamp, false, &vp8_info, &flags);
159 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags);
160 EXPECT_EQ(0, vp8_info.temporalIdx);
161 EXPECT_FALSE(vp8_info.layerSync);
162 ++expected_tl0_idx;
163 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
164
161 // Drop two frames from TL0, thus being coded in TL1. 165 // Drop two frames from TL0, thus being coded in TL1.
162 timestamp += kTimestampDelta30Fps; 166 timestamp += kTimestampDelta5Fps;
163 SetEncodeExpectations(true, false, 30); 167 EncodeFrame(timestamp, false, &vp8_info, &flags);
164 EncodeFrame(timestamp, false, &vp8_info, &flags); 168 // First frame is sync frame.
165 EXPECT_EQ(kFlagsTL1Sync, flags); 169 EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags);
166 EXPECT_EQ(1, vp8_info.temporalIdx); 170 EXPECT_EQ(1, vp8_info.temporalIdx);
167 EXPECT_TRUE(vp8_info.layerSync); 171 EXPECT_TRUE(vp8_info.layerSync);
168 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 172 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
169 173
170 timestamp += kTimestampDelta30Fps; 174 timestamp += kTimestampDelta5Fps;
171 SetEncodeExpectations(true, false, 30); 175 EncodeFrame(timestamp, false, &vp8_info, &flags);
172 EncodeFrame(timestamp, false, &vp8_info, &flags); 176 EXPECT_EQ(ScreenshareLayers::kTl1Flags, flags);
173 EXPECT_EQ(kFlagsTL1, flags);
174 EXPECT_EQ(1, vp8_info.temporalIdx); 177 EXPECT_EQ(1, vp8_info.temporalIdx);
175 EXPECT_FALSE(vp8_info.layerSync); 178 EXPECT_FALSE(vp8_info.layerSync);
176 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 179 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx);
177 } 180 }
178 181
179 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) { 182 TEST_F(ScreenshareLayerTest, 2LayersPeriodicSync) {
180 layers_.reset( 183 layers_.reset(new ScreenshareLayers(2, 0));
181 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); 184 ConfigureBitrates();
182 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); 185 int flags = 0;
183 int flags = 0; 186 uint32_t timestamp = 0;
184 uint32_t timestamp = 0; 187 CodecSpecificInfoVP8 vp8_info;
185 CodecSpecificInfoVP8 vp8_info; 188 std::vector<int> sync_times;
186 const int kNumFrames = 10; 189
187 const bool kDrops[kNumFrames] = {false, true, true, true, true, 190 const int kNumFrames = kSyncPeriodSeconds * kFrameRate * 2 - 1;
188 true, true, true, true, true};
189 const int kExpectedFramerates[kNumFrames] = {1, 5, 5, 5, 5, 5, 5, 5, 5, 5};
190 const bool kExpectedSyncs[kNumFrames] = {false, true, false, false, false,
191 false, false, true, false, false};
192 const int kExpectedTemporalIdx[kNumFrames] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1};
193 for (int i = 0; i < kNumFrames; ++i) { 191 for (int i = 0; i < kNumFrames; ++i) {
194 timestamp += kTimestampDelta5Fps; 192 timestamp += kTimestampDelta5Fps;
195 SetEncodeExpectations(kDrops[i], false, kExpectedFramerates[i]); 193 EncodeFrame(timestamp, false, &vp8_info, &flags);
196 EncodeFrame(timestamp, false, &vp8_info, &flags); 194 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync) {
197 EXPECT_EQ(kExpectedTemporalIdx[i], vp8_info.temporalIdx); 195 sync_times.push_back(timestamp);
198 EXPECT_EQ(kExpectedSyncs[i], vp8_info.layerSync) << "Iteration: " << i; 196 }
199 EXPECT_EQ(1, vp8_info.tl0PicIdx); 197 }
200 } 198
199 ASSERT_EQ(2u, sync_times.size());
200 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kSyncPeriodSeconds);
201 }
202
203 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterTimeout) {
204 layers_.reset(new ScreenshareLayers(2, 0));
205 ConfigureBitrates();
206 uint32_t timestamp = 0;
207 CodecSpecificInfoVP8 vp8_info;
208 std::vector<int> sync_times;
209
210 const int kNumFrames = kMaxSyncPeriodSeconds * kFrameRate * 2 - 1;
211 for (int i = 0; i < kNumFrames; ++i) {
212 timestamp += kTimestampDelta5Fps;
213 layers_->EncodeFlags(timestamp);
214 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
215
216 // Simulate TL1 being at least 8 qp steps better.
217 if (vp8_info.temporalIdx == 0) {
218 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
219 } else {
220 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8);
221 }
222
223 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync)
224 sync_times.push_back(timestamp);
225 }
226
227 ASSERT_EQ(2u, sync_times.size());
228 EXPECT_GE(sync_times[1] - sync_times[0], 90000 * kMaxSyncPeriodSeconds);
229 }
230
231 TEST_F(ScreenshareLayerTest, 2LayersSyncAfterSimilarQP) {
232 layers_.reset(new ScreenshareLayers(2, 0));
233 ConfigureBitrates();
234 uint32_t timestamp = 0;
235 CodecSpecificInfoVP8 vp8_info;
236 std::vector<int> sync_times;
237
238 const int kNumFrames = (kSyncPeriodSeconds +
239 ((kMaxSyncPeriodSeconds - kSyncPeriodSeconds) / 2)) *
240 kFrameRate;
241 for (int i = 0; i < kNumFrames; ++i) {
242 timestamp += kTimestampDelta5Fps;
243 layers_->EncodeFlags(timestamp);
244 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
245
246 // Simulate TL1 being at least 8 qp steps better.
247 if (vp8_info.temporalIdx == 0) {
248 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
249 } else {
250 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8);
251 }
252
253 if (vp8_info.temporalIdx == 1 && vp8_info.layerSync)
254 sync_times.push_back(timestamp);
255 }
256
257 ASSERT_EQ(1u, sync_times.size());
258
259 bool bumped_tl0_quality = false;
260 for (int i = 0; i < 3; ++i) {
261 timestamp += kTimestampDelta5Fps;
262 int flags = layers_->EncodeFlags(timestamp);
263 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
264
265 if (vp8_info.temporalIdx == 0) {
266 // Bump TL0 to same quality as TL1.
267 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8);
268 bumped_tl0_quality = true;
269 } else {
270 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp - 8);
271 if (bumped_tl0_quality) {
272 EXPECT_TRUE(vp8_info.layerSync);
273 EXPECT_EQ(ScreenshareLayers::kTl1SyncFlags, flags);
274 return;
275 }
276 }
277 }
278 ADD_FAILURE() << "No TL1 frame arrived within time limit.";
201 } 279 }
202 280
203 TEST_F(ScreenshareLayerTest, 2LayersToggling) { 281 TEST_F(ScreenshareLayerTest, 2LayersToggling) {
204 layers_.reset( 282 layers_.reset(new ScreenshareLayers(2, 0));
205 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); 283 ConfigureBitrates();
206 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); 284 int flags = 0;
207 int flags = 0; 285 CodecSpecificInfoVP8 vp8_info;
208 uint32_t timestamp = 0; 286 uint32_t timestamp = RunGracePeriod();
209 CodecSpecificInfoVP8 vp8_info; 287
210 const int kNumFrames = 10; 288 // Insert 50 frames. 2/5 should be TL0.
211 const bool kDrops[kNumFrames] = {false, true, false, true, false, 289 int tl0_frames = 0;
212 true, false, true, false, true}; 290 int tl1_frames = 0;
213 const int kExpectedFramerates[kNumFrames] = {1, 5, 5, 5, 5, 5, 5, 5, 5, 5}; 291 for (int i = 0; i < 50; ++i) {
214 const bool kExpectedSyncs[kNumFrames] = {false, true, false, false, false, 292 timestamp += kTimestampDelta5Fps;
215 false, false, true, false, false}; 293 EncodeFrame(timestamp, false, &vp8_info, &flags);
216 const int kExpectedTemporalIdx[kNumFrames] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; 294 switch (vp8_info.temporalIdx) {
217 const int kExpectedTl0Idx[kNumFrames] = {1, 1, 2, 2, 3, 3, 4, 4, 5, 5}; 295 case 0:
218 for (int i = 0; i < kNumFrames; ++i) { 296 ++tl0_frames;
219 timestamp += kTimestampDelta5Fps; 297 break;
220 SetEncodeExpectations(kDrops[i], false, kExpectedFramerates[i]); 298 case 1:
221 EncodeFrame(timestamp, false, &vp8_info, &flags); 299 ++tl1_frames;
222 EXPECT_EQ(kExpectedTemporalIdx[i], vp8_info.temporalIdx); 300 break;
223 EXPECT_EQ(kExpectedSyncs[i], vp8_info.layerSync) << "Iteration: " << i; 301 default:
224 EXPECT_EQ(kExpectedTl0Idx[i], vp8_info.tl0PicIdx); 302 abort();
225 } 303 }
226 } 304 }
227 305 EXPECT_EQ(20, tl0_frames);
228 TEST_F(ScreenshareLayerTest, 2LayersBothDrops) { 306 EXPECT_EQ(30, tl1_frames);
229 layers_.reset( 307 }
230 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_)); 308
231 EXPECT_TRUE(layers_->ConfigureBitrates(100, 1000, 5, NULL)); 309 TEST_F(ScreenshareLayerTest, AllFitsLayer0) {
232 int flags = 0; 310 layers_.reset(new ScreenshareLayers(2, 0));
233 uint32_t timestamp = 0; 311 ConfigureBitrates();
234 uint8_t expected_tl0_idx = 0; 312 frame_size_ = ((kDefaultTl0BitrateKbps * 1000) / 8) / kFrameRate;
235 CodecSpecificInfoVP8 vp8_info; 313
236 SetEncodeExpectations(false, false, 1); 314 int flags = 0;
237 EncodeFrame(timestamp, false, &vp8_info, &flags); 315 uint32_t timestamp = 0;
238 EXPECT_EQ(kFlagsTL0, flags); 316 CodecSpecificInfoVP8 vp8_info;
239 EXPECT_EQ(0, vp8_info.temporalIdx); 317 // Insert 50 frames, small enough that all fits in TL0.
240 EXPECT_FALSE(vp8_info.layerSync); 318 for (int i = 0; i < 50; ++i) {
241 ++expected_tl0_idx; 319 EncodeFrame(timestamp, false, &vp8_info, &flags);
242 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 320 timestamp += kTimestampDelta5Fps;
243 321 EXPECT_EQ(ScreenshareLayers::kTl0Flags, flags);
244 timestamp += kTimestampDelta5Fps; 322 EXPECT_EQ(0, vp8_info.temporalIdx);
245 SetEncodeExpectations(true, false, 5); 323 }
246 EncodeFrame(timestamp, false, &vp8_info, &flags); 324 }
247 EXPECT_EQ(kFlagsTL1Sync, flags); 325
248 EXPECT_EQ(1, vp8_info.temporalIdx); 326 TEST_F(ScreenshareLayerTest, TooHighBitrate) {
249 EXPECT_TRUE(vp8_info.layerSync); 327 layers_.reset(new ScreenshareLayers(2, 0));
250 EXPECT_EQ(expected_tl0_idx, vp8_info.tl0PicIdx); 328 ConfigureBitrates();
251 329 frame_size_ = 2 * ((kDefaultTl1BitrateKbps * 1000) / 8) / kFrameRate;
252 timestamp += kTimestampDelta5Fps; 330 int flags = 0;
253 SetEncodeExpectations(true, true, 5); 331 CodecSpecificInfoVP8 vp8_info;
254 flags = layers_->EncodeFlags(timestamp); 332 uint32_t timestamp = RunGracePeriod();
255 EXPECT_EQ(-1, flags); 333
334 // Insert 100 frames. Half should be dropped.
335 int tl0_frames = 0;
336 int tl1_frames = 0;
337 int dropped_frames = 0;
338 for (int i = 0; i < 100; ++i) {
339 timestamp += kTimestampDelta5Fps;
340 EncodeFrame(timestamp, false, &vp8_info, &flags);
341 if (flags == -1) {
342 ++dropped_frames;
343 } else {
344 switch (vp8_info.temporalIdx) {
345 case 0:
346 ++tl0_frames;
347 break;
348 case 1:
349 ++tl1_frames;
350 break;
351 default:
352 abort();
353 }
354 }
355 }
356
357 EXPECT_EQ(5, tl0_frames);
358 EXPECT_EQ(45, tl1_frames);
359 EXPECT_EQ(50, dropped_frames);
256 } 360 }
257 361
258 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) { 362 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL0) {
259 layers_.reset( 363 layers_.reset(new ScreenshareLayers(2, 0));
260 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_));
261 364
262 vpx_codec_enc_cfg_t cfg; 365 vpx_codec_enc_cfg_t cfg;
263 layers_->ConfigureBitrates(100, 1000, 5, &cfg); 366 layers_->ConfigureBitrates(100, 1000, 5, &cfg);
264 367
265 EXPECT_EQ(static_cast<unsigned int>( 368 EXPECT_EQ(static_cast<unsigned int>(
266 ScreenshareLayers::kMaxTL0FpsReduction * 100 + 0.5), 369 ScreenshareLayers::kMaxTL0FpsReduction * 100 + 0.5),
267 cfg.rc_target_bitrate); 370 cfg.rc_target_bitrate);
268 } 371 }
269 372
270 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) { 373 TEST_F(ScreenshareLayerTest, TargetBitrateCappedByTL1) {
271 layers_.reset( 374 layers_.reset(new ScreenshareLayers(2, 0));
272 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_));
273 vpx_codec_enc_cfg_t cfg; 375 vpx_codec_enc_cfg_t cfg;
274 layers_->ConfigureBitrates(100, 450, 5, &cfg); 376 layers_->ConfigureBitrates(100, 450, 5, &cfg);
275 377
276 EXPECT_EQ(static_cast<unsigned int>( 378 EXPECT_EQ(static_cast<unsigned int>(
277 450 / ScreenshareLayers::kAcceptableTargetOvershoot), 379 450 / ScreenshareLayers::kAcceptableTargetOvershoot),
278 cfg.rc_target_bitrate); 380 cfg.rc_target_bitrate);
279 } 381 }
280 382
281 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) { 383 TEST_F(ScreenshareLayerTest, TargetBitrateBelowTL0) {
282 layers_.reset( 384 layers_.reset(new ScreenshareLayers(2, 0));
283 new ScreenshareLayersFT(2, 0, &tl0_frame_dropper_, &tl1_frame_dropper_));
284 vpx_codec_enc_cfg_t cfg; 385 vpx_codec_enc_cfg_t cfg;
285 layers_->ConfigureBitrates(100, 100, 5, &cfg); 386 layers_->ConfigureBitrates(100, 100, 5, &cfg);
286 387
287 EXPECT_EQ(100U, cfg.rc_target_bitrate); 388 EXPECT_EQ(100U, cfg.rc_target_bitrate);
288 } 389 }
289 390
391 TEST_F(ScreenshareLayerTest, EncoderDrop) {
392 layers_.reset(new ScreenshareLayers(2, 0));
393 ConfigureBitrates();
394 CodecSpecificInfoVP8 vp8_info;
395 vpx_codec_enc_cfg_t cfg;
396 cfg.rc_max_quantizer = kDefaultQp;
397
398 uint32_t timestamp = RunGracePeriod();
399 timestamp = SkipUntilTl(0, timestamp);
400
401 // Size 0 indicates dropped frame.
402 layers_->FrameEncoded(0, timestamp, kDefaultQp);
403 timestamp += kTimestampDelta5Fps;
404 EXPECT_FALSE(layers_->UpdateConfiguration(&cfg));
405 EXPECT_EQ(ScreenshareLayers::kTl0Flags, layers_->EncodeFlags(timestamp));
406 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
407 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
408
409 timestamp = SkipUntilTl(0, timestamp);
410 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
411 EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
412 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
413
414 layers_->EncodeFlags(timestamp);
415 timestamp += kTimestampDelta5Fps;
416 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
417 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
418 EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
419 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
420
421 // Next drop in TL1.
422
423 timestamp = SkipUntilTl(1, timestamp);
424 layers_->FrameEncoded(0, timestamp, kDefaultQp);
425 timestamp += kTimestampDelta5Fps;
426 EXPECT_FALSE(layers_->UpdateConfiguration(&cfg));
427 EXPECT_EQ(ScreenshareLayers::kTl1Flags, layers_->EncodeFlags(timestamp));
428 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
429 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
430
431 timestamp = SkipUntilTl(1, timestamp);
432 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
433 EXPECT_LT(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
434 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
435
436 layers_->EncodeFlags(timestamp);
437 timestamp += kTimestampDelta5Fps;
438 EXPECT_TRUE(layers_->UpdateConfiguration(&cfg));
439 layers_->PopulateCodecSpecific(false, &vp8_info, timestamp);
440 EXPECT_EQ(cfg.rc_max_quantizer, static_cast<unsigned int>(kDefaultQp));
441 layers_->FrameEncoded(frame_size_, timestamp, kDefaultQp);
442 }
443
290 } // namespace webrtc 444 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698