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