video_codec_unittest.cc (7281B)
1 /* 2 * Copyright (c) 2017 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 "modules/video_coding/codecs/test/video_codec_unittest.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 #include <vector> 19 20 #include "api/environment/environment_factory.h" 21 #include "api/test/create_frame_generator.h" 22 #include "api/test/frame_generator_interface.h" 23 #include "api/units/time_delta.h" 24 #include "api/video/encoded_image.h" 25 #include "api/video/video_codec_type.h" 26 #include "api/video/video_frame.h" 27 #include "api/video_codecs/video_codec.h" 28 #include "api/video_codecs/video_decoder.h" 29 #include "api/video_codecs/video_encoder.h" 30 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 31 #include "modules/video_coding/include/video_error_codes.h" 32 #include "rtc_base/checks.h" 33 #include "rtc_base/synchronization/mutex.h" 34 #include "test/gtest.h" 35 #include "test/video_codec_settings.h" 36 37 static constexpr webrtc::TimeDelta kEncodeTimeout = 38 webrtc::TimeDelta::Millis(100); 39 static constexpr webrtc::TimeDelta kDecodeTimeout = 40 webrtc::TimeDelta::Millis(25); 41 // Set bitrate to get higher quality. 42 static const int kStartBitrate = 300; 43 static const int kMaxBitrate = 4000; 44 static const int kWidth = 176; // Width of the input image. 45 static const int kHeight = 144; // Height of the input image. 46 static const int kMaxFramerate = 30; // Arbitrary value. 47 48 namespace webrtc { 49 namespace { 50 const VideoEncoder::Capabilities kCapabilities(false); 51 } // namespace 52 53 EncodedImageCallback::Result 54 VideoCodecUnitTest::FakeEncodeCompleteCallback::OnEncodedImage( 55 const EncodedImage& frame, 56 const CodecSpecificInfo* codec_specific_info) { 57 MutexLock lock(&test_->encoded_frame_section_); 58 test_->encoded_frames_.push_back(frame); 59 RTC_DCHECK(codec_specific_info); 60 test_->codec_specific_infos_.push_back(*codec_specific_info); 61 if (!test_->wait_for_encoded_frames_threshold_) { 62 test_->encoded_frame_event_.Set(); 63 return Result(Result::OK); 64 } 65 66 if (test_->encoded_frames_.size() == 67 test_->wait_for_encoded_frames_threshold_) { 68 test_->wait_for_encoded_frames_threshold_ = 1; 69 test_->encoded_frame_event_.Set(); 70 } 71 return Result(Result::OK); 72 } 73 74 void VideoCodecUnitTest::FakeDecodeCompleteCallback::Decoded( 75 VideoFrame& frame, 76 std::optional<int32_t> /* decode_time_ms */, 77 std::optional<uint8_t> qp) { 78 MutexLock lock(&test_->decoded_frame_section_); 79 test_->decoded_frame_.emplace(frame); 80 test_->decoded_qp_ = qp; 81 test_->decoded_frame_event_.Set(); 82 } 83 84 void VideoCodecUnitTest::SetUp() { 85 EnvironmentFactory factory(env_); 86 factory.Set(field_trials_.CreateCopy()); 87 env_ = factory.Create(); 88 test::CodecSettings(kVideoCodecVP8, &codec_settings_); 89 codec_settings_.startBitrate = kStartBitrate; 90 codec_settings_.maxBitrate = kMaxBitrate; 91 codec_settings_.maxFramerate = kMaxFramerate; 92 codec_settings_.width = kWidth; 93 codec_settings_.height = kHeight; 94 95 ModifyCodecSettings(&codec_settings_); 96 97 input_frame_generator_ = test::CreateSquareFrameGenerator( 98 codec_settings_.width, codec_settings_.height, 99 test::FrameGeneratorInterface::OutputType::kI420, std::optional<int>()); 100 101 encoder_ = CreateEncoder(); 102 decoder_ = CreateDecoder(); 103 encoder_->RegisterEncodeCompleteCallback(&encode_complete_callback_); 104 decoder_->RegisterDecodeCompleteCallback(&decode_complete_callback_); 105 106 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, 107 encoder_->InitEncode( 108 &codec_settings_, 109 VideoEncoder::Settings(kCapabilities, 1 /* number of cores */, 110 0 /* max payload size (unused) */))); 111 112 VideoDecoder::Settings decoder_settings; 113 decoder_settings.set_codec_type(codec_settings_.codecType); 114 decoder_settings.set_max_render_resolution( 115 {codec_settings_.width, codec_settings_.height}); 116 EXPECT_TRUE(decoder_->Configure(decoder_settings)); 117 } 118 119 void VideoCodecUnitTest::ModifyCodecSettings(VideoCodec* /* codec_settings */) { 120 } 121 122 VideoFrame VideoCodecUnitTest::NextInputFrame() { 123 test::FrameGeneratorInterface::VideoFrameData frame_data = 124 input_frame_generator_->NextFrame(); 125 VideoFrame input_frame = VideoFrame::Builder() 126 .set_video_frame_buffer(frame_data.buffer) 127 .set_update_rect(frame_data.update_rect) 128 .build(); 129 130 const uint32_t timestamp = 131 last_input_frame_timestamp_ + 132 kVideoPayloadTypeFrequency / codec_settings_.maxFramerate; 133 input_frame.set_rtp_timestamp(timestamp); 134 input_frame.set_timestamp_us(timestamp * (1000 / 90)); 135 136 last_input_frame_timestamp_ = timestamp; 137 return input_frame; 138 } 139 140 bool VideoCodecUnitTest::WaitForEncodedFrame( 141 EncodedImage* frame, 142 CodecSpecificInfo* codec_specific_info) { 143 std::vector<EncodedImage> frames; 144 std::vector<CodecSpecificInfo> codec_specific_infos; 145 if (!WaitForEncodedFrames(&frames, &codec_specific_infos)) 146 return false; 147 EXPECT_EQ(frames.size(), static_cast<size_t>(1)); 148 EXPECT_EQ(frames.size(), codec_specific_infos.size()); 149 *frame = frames[0]; 150 *codec_specific_info = codec_specific_infos[0]; 151 return true; 152 } 153 154 void VideoCodecUnitTest::SetWaitForEncodedFramesThreshold(size_t num_frames) { 155 MutexLock lock(&encoded_frame_section_); 156 wait_for_encoded_frames_threshold_ = num_frames; 157 } 158 159 bool VideoCodecUnitTest::WaitForEncodedFrames( 160 std::vector<EncodedImage>* frames, 161 std::vector<CodecSpecificInfo>* codec_specific_info) { 162 EXPECT_TRUE(encoded_frame_event_.Wait(kEncodeTimeout)) 163 << "Timed out while waiting for encoded frame."; 164 // This becomes unsafe if there are multiple threads waiting for frames. 165 MutexLock lock(&encoded_frame_section_); 166 EXPECT_FALSE(encoded_frames_.empty()); 167 EXPECT_FALSE(codec_specific_infos_.empty()); 168 EXPECT_EQ(encoded_frames_.size(), codec_specific_infos_.size()); 169 if (!encoded_frames_.empty()) { 170 *frames = encoded_frames_; 171 encoded_frames_.clear(); 172 RTC_DCHECK(!codec_specific_infos_.empty()); 173 *codec_specific_info = codec_specific_infos_; 174 codec_specific_infos_.clear(); 175 return true; 176 } else { 177 return false; 178 } 179 } 180 181 bool VideoCodecUnitTest::WaitForDecodedFrame(std::unique_ptr<VideoFrame>* frame, 182 std::optional<uint8_t>* qp) { 183 bool ret = decoded_frame_event_.Wait(kDecodeTimeout); 184 EXPECT_TRUE(ret) << "Timed out while waiting for a decoded frame."; 185 // This becomes unsafe if there are multiple threads waiting for frames. 186 MutexLock lock(&decoded_frame_section_); 187 EXPECT_TRUE(decoded_frame_); 188 if (decoded_frame_) { 189 frame->reset(new VideoFrame(std::move(*decoded_frame_))); 190 *qp = decoded_qp_; 191 decoded_frame_.reset(); 192 return true; 193 } else { 194 return false; 195 } 196 } 197 198 size_t VideoCodecUnitTest::GetNumEncodedFrames() { 199 MutexLock lock(&encoded_frame_section_); 200 return encoded_frames_.size(); 201 } 202 203 } // namespace webrtc