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