| /* | |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "modules/video_coding/codecs/test/videoprocessor.h" | |
| #include <cstdint> | |
| #include <memory> | |
| #include <vector> | |
| #include "api/environment/environment_factory.h" | |
| #include "api/test/mock_video_decoder.h" | |
| #include "api/test/mock_video_encoder.h" | |
| #include "api/test/videocodec_test_fixture.h" | |
| #include "api/video/i420_buffer.h" | |
| #include "api/video/video_frame.h" | |
| #include "api/video_codecs/video_decoder.h" | |
| #include "api/video_codecs/video_encoder.h" | |
| #include "media/base/media_constants.h" | |
| #include "modules/video_coding/codecs/test/videocodec_test_stats_impl.h" | |
| #include "rtc_base/task_queue_for_test.h" | |
| #include "test/gmock.h" | |
| #include "test/gtest.h" | |
| #include "test/testsupport/mock/mock_frame_reader.h" | |
| using ::testing::_; | |
| using ::testing::AllOf; | |
| using ::testing::Field; | |
| using ::testing::Property; | |
| using ::testing::ResultOf; | |
| using ::testing::Return; | |
| namespace webrtc { | |
| namespace test { | |
| namespace { | |
| constexpr int kWidth = 352; | |
| constexpr int kHeight = 288; | |
| } // namespace | |
| class VideoProcessorTest : public ::testing::Test { | |
| protected: | |
| VideoProcessorTest() : q_("VP queue") { | |
| config_.SetCodecSettings(kVp8CodecName, 1, 1, 1, false, false, false, | |
| kWidth, kHeight); | |
| decoder_mock_ = new MockVideoDecoder(); | |
| decoders_.push_back(std::unique_ptr<VideoDecoder>(decoder_mock_)); | |
| ExpectInit(); | |
| q_.SendTask([this] { | |
| video_processor_ = std::make_unique<VideoProcessor>( | |
| CreateEnvironment(), &encoder_mock_, &decoders_, &frame_reader_mock_, | |
| config_, &stats_, &encoded_frame_writers_, | |
| /*decoded_frame_writers=*/nullptr); | |
| }); | |
| } | |
| ~VideoProcessorTest() override { | |
| q_.SendTask([this] { video_processor_.reset(); }); | |
| } | |
| void ExpectInit() { | |
| EXPECT_CALL(encoder_mock_, InitEncode(_, _)); | |
| EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback); | |
| EXPECT_CALL(*decoder_mock_, Configure); | |
| EXPECT_CALL(*decoder_mock_, RegisterDecodeCompleteCallback); | |
| } | |
| void ExpectRelease() { | |
| EXPECT_CALL(encoder_mock_, Release()).Times(1); | |
| EXPECT_CALL(encoder_mock_, RegisterEncodeCompleteCallback(_)).Times(1); | |
| EXPECT_CALL(*decoder_mock_, Release()).Times(1); | |
| EXPECT_CALL(*decoder_mock_, RegisterDecodeCompleteCallback(_)).Times(1); | |
| } | |
| TaskQueueForTest q_; | |
| VideoCodecTestFixture::Config config_; | |
| MockVideoEncoder encoder_mock_; | |
| MockVideoDecoder* decoder_mock_; | |
| std::vector<std::unique_ptr<VideoDecoder>> decoders_; | |
| MockFrameReader frame_reader_mock_; | |
| VideoCodecTestStatsImpl stats_; | |
| VideoProcessor::IvfFileWriterMap encoded_frame_writers_; | |
| std::unique_ptr<VideoProcessor> video_processor_; | |
| }; | |
| TEST_F(VideoProcessorTest, InitRelease) { | |
| ExpectRelease(); | |
| } | |
| TEST_F(VideoProcessorTest, ProcessFrames_FixedFramerate) { | |
| const int kBitrateKbps = 456; | |
| const int kFramerateFps = 31; | |
| EXPECT_CALL( | |
| encoder_mock_, | |
| SetRates(Field(&VideoEncoder::RateControlParameters::framerate_fps, | |
| static_cast<double>(kFramerateFps)))) | |
| .Times(1); | |
| q_.SendTask( | |
| [this] { video_processor_->SetRates(kBitrateKbps, kFramerateFps); }); | |
| EXPECT_CALL(frame_reader_mock_, PullFrame(_, _, _)) | |
| .WillRepeatedly(Return(I420Buffer::Create(kWidth, kHeight))); | |
| EXPECT_CALL(encoder_mock_, Encode(Property(&VideoFrame::rtp_timestamp, | |
| 1 * 90000 / kFramerateFps), | |
| _)) | |
| .Times(1); | |
| q_.SendTask([this] { video_processor_->ProcessFrame(); }); | |
| EXPECT_CALL(encoder_mock_, Encode(Property(&VideoFrame::rtp_timestamp, | |
| 2 * 90000 / kFramerateFps), | |
| _)) | |
| .Times(1); | |
| q_.SendTask([this] { video_processor_->ProcessFrame(); }); | |
| ExpectRelease(); | |
| } | |
| TEST_F(VideoProcessorTest, ProcessFrames_VariableFramerate) { | |
| const int kBitrateKbps = 456; | |
| const int kStartFramerateFps = 27; | |
| const int kStartTimestamp = 90000 / kStartFramerateFps; | |
| EXPECT_CALL( | |
| encoder_mock_, | |
| SetRates(Field(&VideoEncoder::RateControlParameters::framerate_fps, | |
| static_cast<double>(kStartFramerateFps)))) | |
| .Times(1); | |
| q_.SendTask( | |
| [this] { video_processor_->SetRates(kBitrateKbps, kStartFramerateFps); }); | |
| EXPECT_CALL(frame_reader_mock_, PullFrame(_, _, _)) | |
| .WillRepeatedly(Return(I420Buffer::Create(kWidth, kHeight))); | |
| EXPECT_CALL(encoder_mock_, | |
| Encode(Property(&VideoFrame::rtp_timestamp, kStartTimestamp), _)) | |
| .Times(1); | |
| q_.SendTask([this] { video_processor_->ProcessFrame(); }); | |
| const int kNewFramerateFps = 13; | |
| EXPECT_CALL( | |
| encoder_mock_, | |
| SetRates(Field(&VideoEncoder::RateControlParameters::framerate_fps, | |
| static_cast<double>(kNewFramerateFps)))) | |
| .Times(1); | |
| q_.SendTask( | |
| [this] { video_processor_->SetRates(kBitrateKbps, kNewFramerateFps); }); | |
| EXPECT_CALL(encoder_mock_, | |
| Encode(Property(&VideoFrame::rtp_timestamp, | |
| kStartTimestamp + 90000 / kNewFramerateFps), | |
| _)) | |
| .Times(1); | |
| q_.SendTask([this] { video_processor_->ProcessFrame(); }); | |
| ExpectRelease(); | |
| } | |
| TEST_F(VideoProcessorTest, SetRates) { | |
| const uint32_t kBitrateKbps = 123; | |
| const int kFramerateFps = 17; | |
| EXPECT_CALL( | |
| encoder_mock_, | |
| SetRates(AllOf(ResultOf( | |
| [](const VideoEncoder::RateControlParameters& params) { | |
| return params.bitrate.get_sum_kbps(); | |
| }, | |
| kBitrateKbps), | |
| Field(&VideoEncoder::RateControlParameters::framerate_fps, | |
| static_cast<double>(kFramerateFps))))) | |
| .Times(1); | |
| q_.SendTask( | |
| [this] { video_processor_->SetRates(kBitrateKbps, kFramerateFps); }); | |
| const uint32_t kNewBitrateKbps = 456; | |
| const int kNewFramerateFps = 34; | |
| EXPECT_CALL( | |
| encoder_mock_, | |
| SetRates(AllOf(ResultOf( | |
| [](const VideoEncoder::RateControlParameters& params) { | |
| return params.bitrate.get_sum_kbps(); | |
| }, | |
| kNewBitrateKbps), | |
| Field(&VideoEncoder::RateControlParameters::framerate_fps, | |
| static_cast<double>(kNewFramerateFps))))) | |
| .Times(1); | |
| q_.SendTask([this] { | |
| video_processor_->SetRates(kNewBitrateKbps, kNewFramerateFps); | |
| }); | |
| ExpectRelease(); | |
| } | |
| } // namespace test | |
| } // namespace webrtc |