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 "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 |
OLD | NEW |