OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 #include "webrtc/base/logging.h" | |
13 #include "webrtc/test/encoder_settings.h" | |
14 #include "webrtc/test/fake_encoder.h" | |
15 #include "webrtc/video/send_statistics_proxy.h" | |
16 #include "webrtc/video/vie_encoder.h" | |
17 | |
18 namespace webrtc { | |
19 | |
20 class ViEEncoderTest : public ::testing::Test { | |
21 public: | |
22 static const int kDefaultTimeoutMs = 30 * 1000; | |
23 | |
24 ViEEncoderTest() | |
25 : video_send_config_(VideoSendStream::Config(nullptr)), | |
26 fake_encoder_(), | |
27 stats_proxy_(Clock::GetRealTimeClock(), | |
28 video_send_config_, | |
29 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo), | |
30 sink_(&fake_encoder_) {} | |
31 | |
32 void SetUp() override { | |
33 video_send_config_ = VideoSendStream::Config(nullptr); | |
34 video_send_config_.encoder_settings.encoder = &fake_encoder_; | |
35 video_send_config_.encoder_settings.payload_name = "FAKE"; | |
36 video_send_config_.encoder_settings.payload_type = 125; | |
37 | |
38 video_encoder_config_.streams = test::CreateVideoStreams(1); | |
39 | |
40 vie_encoder_.reset(new ViEEncoder( | |
41 1 /* number_of_cores */, &stats_proxy_, | |
42 video_send_config_.encoder_settings, nullptr /* pre_encode_callback */, | |
43 nullptr /* overuse_callback */, nullptr /* encoder_timing */)); | |
44 vie_encoder_->SetSink(&sink_); | |
45 vie_encoder_->SetStartBitrate(10000); | |
46 vie_encoder_->ConfigureEncoder(video_encoder_config_, 1440); | |
47 } | |
48 | |
49 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const { | |
50 class TestBuffer : public webrtc::I420Buffer { | |
51 public: | |
52 TestBuffer(rtc::Event* event, int width, int height) | |
53 : I420Buffer(width, height), event_(event) {} | |
54 | |
55 private: | |
56 friend class rtc::RefCountedObject<TestBuffer>; | |
57 ~TestBuffer() override { | |
58 if (event_) | |
59 event_->Set(); | |
60 } | |
61 rtc::Event* const event_; | |
62 }; | |
63 | |
64 VideoFrame frame( | |
65 new rtc::RefCountedObject<TestBuffer>( | |
66 destruction_event, | |
67 static_cast<int>(video_encoder_config_.streams[0].width), | |
68 static_cast<int>(video_encoder_config_.streams[0].height)), | |
69 99, 99, kVideoRotation_0); | |
70 frame.set_ntp_time_ms(ntp_ts); | |
71 return frame; | |
72 } | |
73 | |
74 class TestEncoder : public test::FakeEncoder { | |
75 public: | |
76 TestEncoder() | |
77 : FakeEncoder(Clock::GetRealTimeClock()), | |
78 continue_encode_event_(false, false) {} | |
79 | |
80 int32_t Encode(const VideoFrame& input_image, | |
81 const CodecSpecificInfo* codec_specific_info, | |
82 const std::vector<FrameType>* frame_types) override { | |
83 bool block_encode; | |
84 { | |
85 rtc::CritScope lock(&crit_); | |
86 EXPECT_GT(input_image.timestamp(), timestamp_); | |
87 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_); | |
88 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90); | |
89 | |
90 timestamp_ = input_image.timestamp(); | |
91 ntp_time_ms_ = input_image.ntp_time_ms(); | |
92 block_encode = block_next_encode_; | |
93 block_next_encode_ = false; | |
94 } | |
95 int32_t result = | |
96 FakeEncoder::Encode(input_image, codec_specific_info, frame_types); | |
97 if (block_encode) | |
98 continue_encode_event_.Wait(kDefaultTimeoutMs); | |
99 return result; | |
100 } | |
101 | |
102 void BlockNextEncode() { | |
103 rtc::CritScope lock(&crit_); | |
104 block_next_encode_ = true; | |
105 } | |
106 | |
107 void ContinueEncode() { continue_encode_event_.Set(); } | |
108 | |
109 void CheckLastTimeStampsMatch(int64_t ntp_time_ms, | |
110 uint32_t timestamp) const { | |
111 rtc::CritScope lock(&crit_); | |
112 EXPECT_EQ(timestamp_, timestamp); | |
113 EXPECT_EQ(ntp_time_ms_, ntp_time_ms); | |
114 } | |
115 | |
116 private: | |
117 rtc::CriticalSection crit_; | |
118 bool block_next_encode_ = false; | |
119 rtc::Event continue_encode_event_; | |
120 uint32_t timestamp_ = 0; | |
121 int64_t ntp_time_ms_ = 0; | |
122 }; | |
123 | |
124 class TestSink : public EncodedImageCallback { | |
125 public: | |
126 explicit TestSink(TestEncoder* test_encoder) | |
127 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {} | |
128 | |
129 int32_t Encoded(const EncodedImage& encoded_image, | |
130 const CodecSpecificInfo* codec_specific_info, | |
131 const RTPFragmentationHeader* fragmentation) override { | |
132 rtc::CritScope lock(&crit_); | |
133 EXPECT_TRUE(expect_frames_); | |
134 timestamp_ = encoded_image._timeStamp; | |
135 encoded_frame_event_.Set(); | |
136 return 1; | |
stefan-webrtc
2016/07/08 15:56:43
Why are you returning 1 here? 0 is what I'd expect
perkj_webrtc
2016/07/11 11:41:08
Done.
| |
137 } | |
138 | |
139 void WaitForEncodedFrame(int64_t expected_ntp_time) { | |
140 uint32_t timestamp = 0; | |
141 encoded_frame_event_.Wait(kDefaultTimeoutMs); | |
142 { | |
143 rtc::CritScope lock(&crit_); | |
144 timestamp = timestamp_; | |
145 } | |
146 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp); | |
147 } | |
148 | |
149 void SetExpectNoFrames() { | |
150 rtc::CritScope lock(&crit_); | |
151 expect_frames_ = false; | |
152 } | |
153 | |
154 private: | |
155 rtc::CriticalSection crit_; | |
156 TestEncoder* test_encoder_; | |
157 rtc::Event encoded_frame_event_; | |
158 uint32_t timestamp_ = 0; | |
159 bool expect_frames_ = true; | |
160 }; | |
161 | |
162 VideoSendStream::Config video_send_config_; | |
163 VideoEncoderConfig video_encoder_config_; | |
164 TestEncoder fake_encoder_; | |
165 SendStatisticsProxy stats_proxy_; | |
166 TestSink sink_; | |
167 std::unique_ptr<ViEEncoder> vie_encoder_; | |
168 }; | |
169 | |
170 TEST_F(ViEEncoderTest, EncodeOneFrame) { | |
171 const int kTargetBitrateBps = 100000; | |
172 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
173 rtc::Event frame_destroyed_event(false, false); | |
174 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); | |
175 sink_.WaitForEncodedFrame(1); | |
176 frame_destroyed_event.Wait(kDefaultTimeoutMs); | |
177 vie_encoder_->Stop(); | |
178 } | |
179 | |
180 TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { | |
181 // Dropped since no target bitrate has been set. | |
182 rtc::Event frame_destroyed_event(false, false); | |
183 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); | |
184 frame_destroyed_event.Wait(kDefaultTimeoutMs); | |
185 | |
186 const int kTargetBitrateBps = 100000; | |
187 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
188 | |
189 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); | |
190 sink_.WaitForEncodedFrame(2); | |
191 vie_encoder_->Stop(); | |
192 } | |
193 | |
194 TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { | |
195 const int kTargetBitrateBps = 100000; | |
196 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
197 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); | |
198 sink_.WaitForEncodedFrame(1); | |
199 | |
200 vie_encoder_->OnBitrateUpdated(0, 0, 0); | |
201 // Dropped since bitrate is zero. | |
202 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); | |
203 | |
204 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
205 vie_encoder_->IncomingCapturedFrame(CreateFrame(3, nullptr)); | |
206 sink_.WaitForEncodedFrame(3); | |
207 vie_encoder_->Stop(); | |
208 } | |
209 | |
210 TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) { | |
211 const int kTargetBitrateBps = 100000; | |
212 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
213 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); | |
214 sink_.WaitForEncodedFrame(1); | |
215 | |
216 // This frame will be dropped since it has the same ntp timestamp. | |
217 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); | |
218 | |
219 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); | |
220 sink_.WaitForEncodedFrame(2); | |
221 vie_encoder_->Stop(); | |
222 } | |
223 | |
224 TEST_F(ViEEncoderTest, DropsFrameAfterStop) { | |
225 const int kTargetBitrateBps = 100000; | |
226 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
227 | |
228 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); | |
229 sink_.WaitForEncodedFrame(1); | |
230 | |
231 vie_encoder_->Stop(); | |
232 sink_.SetExpectNoFrames(); | |
233 rtc::Event frame_destroyed_event(false, false); | |
234 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event)); | |
235 frame_destroyed_event.Wait(kDefaultTimeoutMs); | |
236 } | |
237 | |
238 TEST_F(ViEEncoderTest, DropsPendingFramesOnslowEncode) { | |
stefan-webrtc
2016/07/08 15:56:42
OnSlowEncode
perkj_webrtc
2016/07/11 11:41:08
Done.
| |
239 const int kTargetBitrateBps = 100000; | |
240 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); | |
241 | |
242 fake_encoder_.BlockNextEncode(); | |
243 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); | |
244 sink_.WaitForEncodedFrame(1); | |
245 // Here, the encoder thread will be blocked in the TestEncoder waiting for a | |
246 // call to ContinueEncode. | |
247 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); | |
248 vie_encoder_->IncomingCapturedFrame(CreateFrame(3, nullptr)); | |
249 fake_encoder_.ContinueEncode(); | |
250 sink_.WaitForEncodedFrame(3); | |
251 | |
252 vie_encoder_->Stop(); | |
253 } | |
254 | |
255 } // namespace webrtc | |
OLD | NEW |