blob: ba25a1da4d07b2dd1e497da7ab3674bbcd711be9 [file] [log] [blame]
perkj26091b12016-09-01 01:17:40 -07001/*
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"
perkja49cbd32016-09-16 07:53:41 -070015#include "webrtc/test/frame_generator.h"
perkj26091b12016-09-01 01:17:40 -070016#include "webrtc/video/send_statistics_proxy.h"
17#include "webrtc/video/vie_encoder.h"
18
19namespace webrtc {
20
21class ViEEncoderTest : public ::testing::Test {
22 public:
23 static const int kDefaultTimeoutMs = 30 * 1000;
24
25 ViEEncoderTest()
26 : video_send_config_(VideoSendStream::Config(nullptr)),
27 fake_encoder_(),
28 stats_proxy_(Clock::GetRealTimeClock(),
29 video_send_config_,
30 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo),
31 sink_(&fake_encoder_) {}
32
33 void SetUp() override {
34 video_send_config_ = VideoSendStream::Config(nullptr);
35 video_send_config_.encoder_settings.encoder = &fake_encoder_;
36 video_send_config_.encoder_settings.payload_name = "FAKE";
37 video_send_config_.encoder_settings.payload_type = 125;
38
39 video_encoder_config_.streams = test::CreateVideoStreams(1);
40
41 vie_encoder_.reset(new ViEEncoder(
42 1 /* number_of_cores */, &stats_proxy_,
43 video_send_config_.encoder_settings, nullptr /* pre_encode_callback */,
44 nullptr /* overuse_callback */, nullptr /* encoder_timing */));
45 vie_encoder_->SetSink(&sink_);
perkja49cbd32016-09-16 07:53:41 -070046 vie_encoder_->SetSource(&video_source_);
perkj26091b12016-09-01 01:17:40 -070047 vie_encoder_->SetStartBitrate(10000);
48 vie_encoder_->ConfigureEncoder(video_encoder_config_, 1440);
49 }
50
51 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const {
52 class TestBuffer : public webrtc::I420Buffer {
53 public:
54 TestBuffer(rtc::Event* event, int width, int height)
55 : I420Buffer(width, height), event_(event) {}
56
57 private:
58 friend class rtc::RefCountedObject<TestBuffer>;
59 ~TestBuffer() override {
60 if (event_)
61 event_->Set();
62 }
63 rtc::Event* const event_;
64 };
65
66 VideoFrame frame(
67 new rtc::RefCountedObject<TestBuffer>(
68 destruction_event,
69 static_cast<int>(video_encoder_config_.streams[0].width),
70 static_cast<int>(video_encoder_config_.streams[0].height)),
71 99, 99, kVideoRotation_0);
72 frame.set_ntp_time_ms(ntp_ts);
73 return frame;
74 }
75
76 class TestEncoder : public test::FakeEncoder {
77 public:
78 TestEncoder()
79 : FakeEncoder(Clock::GetRealTimeClock()),
80 continue_encode_event_(false, false) {}
81
82 int32_t Encode(const VideoFrame& input_image,
83 const CodecSpecificInfo* codec_specific_info,
84 const std::vector<FrameType>* frame_types) override {
85 bool block_encode;
86 {
87 rtc::CritScope lock(&crit_);
88 EXPECT_GT(input_image.timestamp(), timestamp_);
89 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
90 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
91
92 timestamp_ = input_image.timestamp();
93 ntp_time_ms_ = input_image.ntp_time_ms();
94 block_encode = block_next_encode_;
95 block_next_encode_ = false;
96 }
97 int32_t result =
98 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
99 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700100 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700101 return result;
102 }
103
104 void BlockNextEncode() {
105 rtc::CritScope lock(&crit_);
106 block_next_encode_ = true;
107 }
108
109 void ContinueEncode() { continue_encode_event_.Set(); }
110
111 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
112 uint32_t timestamp) const {
113 rtc::CritScope lock(&crit_);
114 EXPECT_EQ(timestamp_, timestamp);
115 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
116 }
117
118 private:
119 rtc::CriticalSection crit_;
120 bool block_next_encode_ = false;
121 rtc::Event continue_encode_event_;
122 uint32_t timestamp_ = 0;
123 int64_t ntp_time_ms_ = 0;
124 };
125
126 class TestSink : public EncodedImageCallback {
127 public:
128 explicit TestSink(TestEncoder* test_encoder)
129 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
130
131 int32_t Encoded(const EncodedImage& encoded_image,
132 const CodecSpecificInfo* codec_specific_info,
133 const RTPFragmentationHeader* fragmentation) override {
134 rtc::CritScope lock(&crit_);
135 EXPECT_TRUE(expect_frames_);
136 timestamp_ = encoded_image._timeStamp;
137 encoded_frame_event_.Set();
138 return 0;
139 }
140
141 void WaitForEncodedFrame(int64_t expected_ntp_time) {
142 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700143 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700144 {
145 rtc::CritScope lock(&crit_);
146 timestamp = timestamp_;
147 }
148 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
149 }
150
151 void SetExpectNoFrames() {
152 rtc::CritScope lock(&crit_);
153 expect_frames_ = false;
154 }
155
156 private:
157 rtc::CriticalSection crit_;
158 TestEncoder* test_encoder_;
159 rtc::Event encoded_frame_event_;
160 uint32_t timestamp_ = 0;
161 bool expect_frames_ = true;
162 };
163
164 VideoSendStream::Config video_send_config_;
165 VideoEncoderConfig video_encoder_config_;
166 TestEncoder fake_encoder_;
167 SendStatisticsProxy stats_proxy_;
168 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700169 test::FrameForwarder video_source_;
perkj26091b12016-09-01 01:17:40 -0700170 std::unique_ptr<ViEEncoder> vie_encoder_;
171};
172
173TEST_F(ViEEncoderTest, EncodeOneFrame) {
174 const int kTargetBitrateBps = 100000;
175 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
176 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700177 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700178 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700179 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700180 vie_encoder_->Stop();
181}
182
183TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
184 // Dropped since no target bitrate has been set.
185 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700186 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
187 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700188
189 const int kTargetBitrateBps = 100000;
190 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
191
perkja49cbd32016-09-16 07:53:41 -0700192 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700193 sink_.WaitForEncodedFrame(2);
194 vie_encoder_->Stop();
195}
196
197TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
198 const int kTargetBitrateBps = 100000;
199 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700200 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700201 sink_.WaitForEncodedFrame(1);
202
203 vie_encoder_->OnBitrateUpdated(0, 0, 0);
204 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700205 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700206
207 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700208 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700209 sink_.WaitForEncodedFrame(3);
210 vie_encoder_->Stop();
211}
212
213TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
214 const int kTargetBitrateBps = 100000;
215 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700216 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700217 sink_.WaitForEncodedFrame(1);
218
219 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700220 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700221
perkja49cbd32016-09-16 07:53:41 -0700222 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700223 sink_.WaitForEncodedFrame(2);
224 vie_encoder_->Stop();
225}
226
227TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
228 const int kTargetBitrateBps = 100000;
229 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
230
perkja49cbd32016-09-16 07:53:41 -0700231 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700232 sink_.WaitForEncodedFrame(1);
233
234 vie_encoder_->Stop();
235 sink_.SetExpectNoFrames();
236 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700237 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
238 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700239}
240
241TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
242 const int kTargetBitrateBps = 100000;
243 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
244
245 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700246 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700247 sink_.WaitForEncodedFrame(1);
248 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
249 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700250 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
251 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700252 fake_encoder_.ContinueEncode();
253 sink_.WaitForEncodedFrame(3);
254
255 vie_encoder_->Stop();
256}
257
258} // namespace webrtc