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 |
| 31 void SetUp() override { |
| 32 video_send_config_ = VideoSendStream::Config(nullptr); |
| 33 video_send_config_.encoder_settings.encoder = &fake_encoder_; |
| 34 video_send_config_.encoder_settings.payload_name = "FAKE"; |
| 35 video_send_config_.encoder_settings.payload_type = 125; |
| 36 |
| 37 video_encoder_config_.streams = test::CreateVideoStreams(1); |
| 38 |
| 39 vie_encoder_.reset(new ViEEncoder( |
| 40 1 /* number_of_cores */, &stats_proxy_, |
| 41 video_send_config_.encoder_settings, nullptr /* pre_encode_callback */, |
| 42 nullptr /* overuse_callback */, nullptr /* encoder_timing */)); |
| 43 vie_encoder_->SetSink(&sink_); |
| 44 vie_encoder_->SetStartBitrate(10000); |
| 45 vie_encoder_->ConfigureEncoder(video_encoder_config_, 1440); |
| 46 } |
| 47 |
| 48 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) { |
| 49 class TestBuffer : public webrtc::I420Buffer { |
| 50 public: |
| 51 TestBuffer(rtc::Event* event, int width, int height) |
| 52 : I420Buffer(width, height), event_(event) {} |
| 53 |
| 54 private: |
| 55 friend class rtc::RefCountedObject<TestBuffer>; |
| 56 ~TestBuffer() override { |
| 57 if (event_) |
| 58 event_->Set(); |
| 59 } |
| 60 rtc::Event* const event_; |
| 61 }; |
| 62 |
| 63 VideoFrame frame( |
| 64 new rtc::RefCountedObject<TestBuffer>( |
| 65 destruction_event, |
| 66 static_cast<int>(video_encoder_config_.streams[0].width), |
| 67 static_cast<int>(video_encoder_config_.streams[0].height)), |
| 68 99, 99, kVideoRotation_0); |
| 69 frame.set_ntp_time_ms(ntp_ts); |
| 70 return frame; |
| 71 } |
| 72 |
| 73 class TestEncoder : public test::FakeEncoder { |
| 74 public: |
| 75 TestEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {} |
| 76 |
| 77 int32_t Encode(const VideoFrame& input_image, |
| 78 const CodecSpecificInfo* codec_specific_info, |
| 79 const std::vector<FrameType>* frame_types) override { |
| 80 rtc::CritScope lock(&crit_); |
| 81 EXPECT_GT(input_image.timestamp(), timestamp_); |
| 82 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_); |
| 83 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90); |
| 84 |
| 85 timestamp_ = input_image.timestamp(); |
| 86 ntp_time_ms_ = input_image.ntp_time_ms(); |
| 87 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types); |
| 88 } |
| 89 |
| 90 private: |
| 91 rtc::CriticalSection crit_; |
| 92 uint32_t timestamp_ = 0; |
| 93 int64_t ntp_time_ms_ = 0; |
| 94 }; |
| 95 |
| 96 class TestSink : public EncodedImageCallback { |
| 97 public: |
| 98 TestSink() : encoded_frame_event_(false, false) {} |
| 99 |
| 100 int32_t Encoded(const EncodedImage& encoded_image, |
| 101 const CodecSpecificInfo* codec_specific_info, |
| 102 const RTPFragmentationHeader* fragmentation) override { |
| 103 rtc::CritScope lock(&crit_); |
| 104 EXPECT_TRUE(expect_frames_); |
| 105 ntp_time_ = encoded_image.ntp_time_ms_; |
| 106 encoded_frame_event_.Set(); |
| 107 return 1; |
| 108 } |
| 109 |
| 110 void WaitForEncodedFrame(int64_t expected_ntp_time) { |
| 111 encoded_frame_event_.Wait(kDefaultTimeoutMs); |
| 112 rtc::CritScope lock(&crit_); |
| 113 EXPECT_EQ(expected_ntp_time, ntp_time_); |
| 114 } |
| 115 |
| 116 void SetExpectNoFrames() { |
| 117 rtc::CritScope lock(&crit_); |
| 118 expect_frames_ = false; |
| 119 } |
| 120 |
| 121 private: |
| 122 rtc::CriticalSection crit_; |
| 123 rtc::Event encoded_frame_event_; |
| 124 int64_t ntp_time_ = 0; |
| 125 bool expect_frames_ = true; |
| 126 }; |
| 127 |
| 128 VideoSendStream::Config video_send_config_; |
| 129 VideoEncoderConfig video_encoder_config_; |
| 130 TestEncoder fake_encoder_; |
| 131 SendStatisticsProxy stats_proxy_; |
| 132 TestSink sink_; |
| 133 std::unique_ptr<ViEEncoder> vie_encoder_; |
| 134 }; |
| 135 |
| 136 TEST_F(ViEEncoderTest, EncodeOneFrame) { |
| 137 const int kTargetBitrateBps = 100000; |
| 138 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 139 rtc::Event frame_destroyed_event(false, false); |
| 140 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); |
| 141 sink_.WaitForEncodedFrame(1); |
| 142 frame_destroyed_event.Wait(kDefaultTimeoutMs); |
| 143 vie_encoder_->Stop(); |
| 144 } |
| 145 |
| 146 TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) { |
| 147 // Dropped since no target bitrate has been set. |
| 148 rtc::Event frame_destroyed_event(false, false); |
| 149 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event)); |
| 150 frame_destroyed_event.Wait(kDefaultTimeoutMs); |
| 151 |
| 152 const int kTargetBitrateBps = 100000; |
| 153 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 154 |
| 155 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); |
| 156 sink_.WaitForEncodedFrame(2); |
| 157 vie_encoder_->Stop(); |
| 158 } |
| 159 |
| 160 TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) { |
| 161 const int kTargetBitrateBps = 100000; |
| 162 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 163 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); |
| 164 sink_.WaitForEncodedFrame(1); |
| 165 |
| 166 vie_encoder_->OnBitrateUpdated(0, 0, 0); |
| 167 // Dropped since bitrate is zero. |
| 168 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); |
| 169 |
| 170 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 171 vie_encoder_->IncomingCapturedFrame(CreateFrame(3, nullptr)); |
| 172 sink_.WaitForEncodedFrame(3); |
| 173 vie_encoder_->Stop(); |
| 174 } |
| 175 |
| 176 TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) { |
| 177 const int kTargetBitrateBps = 100000; |
| 178 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 179 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); |
| 180 sink_.WaitForEncodedFrame(1); |
| 181 |
| 182 // This frame will be dropped since it has the same ntp timestamp. |
| 183 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); |
| 184 |
| 185 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, nullptr)); |
| 186 sink_.WaitForEncodedFrame(2); |
| 187 vie_encoder_->Stop(); |
| 188 } |
| 189 |
| 190 TEST_F(ViEEncoderTest, DropsFrameAfterStop) { |
| 191 const int kTargetBitrateBps = 100000; |
| 192 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| 193 |
| 194 vie_encoder_->IncomingCapturedFrame(CreateFrame(1, nullptr)); |
| 195 sink_.WaitForEncodedFrame(1); |
| 196 |
| 197 vie_encoder_->Stop(); |
| 198 sink_.SetExpectNoFrames(); |
| 199 rtc::Event frame_destroyed_event(false, false); |
| 200 vie_encoder_->IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event)); |
| 201 frame_destroyed_event.Wait(kDefaultTimeoutMs); |
| 202 } |
| 203 |
| 204 } // namespace webrtc |
OLD | NEW |