1 /*
2 * Copyright 2018 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 <memory>
12 #include "absl/types/optional.h"
13 #include "api/test/video/function_video_encoder_factory.h"
14 #include "api/video/color_space.h"
15 #include "api/video/video_rotation.h"
16 #include "common_video/test/utilities.h"
17 #include "media/engine/internal_decoder_factory.h"
18 #include "media/engine/internal_encoder_factory.h"
19 #include "modules/video_coding/codecs/h264/include/h264.h"
20 #include "modules/video_coding/codecs/multiplex/include/multiplex_decoder_adapter.h"
21 #include "modules/video_coding/codecs/multiplex/include/multiplex_encoder_adapter.h"
22 #include "modules/video_coding/codecs/vp8/include/vp8.h"
23 #include "modules/video_coding/codecs/vp9/include/vp9.h"
24 #include "test/call_test.h"
25 #include "test/encoder_settings.h"
26 #include "test/field_trial.h"
27 #include "test/gtest.h"
28
29 namespace webrtc {
30 namespace {
31 enum : int { // The first valid value is 1.
32 kColorSpaceExtensionId = 1,
33 kVideoRotationExtensionId,
34 };
35 } // namespace
36
37 class CodecEndToEndTest : public test::CallTest {
38 public:
CodecEndToEndTest()39 CodecEndToEndTest() {
40 RegisterRtpExtension(
41 RtpExtension(RtpExtension::kColorSpaceUri, kColorSpaceExtensionId));
42 RegisterRtpExtension(RtpExtension(RtpExtension::kVideoRotationUri,
43 kVideoRotationExtensionId));
44 }
45 };
46
47 class CodecObserver : public test::EndToEndTest,
48 public rtc::VideoSinkInterface<VideoFrame> {
49 public:
CodecObserver(int no_frames_to_wait_for,VideoRotation rotation_to_test,absl::optional<ColorSpace> color_space_to_test,const std::string & payload_name,VideoEncoderFactory * encoder_factory,VideoDecoderFactory * decoder_factory)50 CodecObserver(int no_frames_to_wait_for,
51 VideoRotation rotation_to_test,
52 absl::optional<ColorSpace> color_space_to_test,
53 const std::string& payload_name,
54 VideoEncoderFactory* encoder_factory,
55 VideoDecoderFactory* decoder_factory)
56 : EndToEndTest(4 * CodecEndToEndTest::kDefaultTimeout),
57 // TODO(hta): This timeout (120 seconds) is excessive.
58 // https://bugs.webrtc.org/6830
59 no_frames_to_wait_for_(no_frames_to_wait_for),
60 expected_rotation_(rotation_to_test),
61 expected_color_space_(color_space_to_test),
62 payload_name_(payload_name),
63 encoder_factory_(encoder_factory),
64 decoder_factory_(decoder_factory),
65 frame_counter_(0) {}
66
PerformTest()67 void PerformTest() override {
68 EXPECT_TRUE(Wait())
69 << "Timed out while waiting for enough frames to be decoded.";
70 }
71
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)72 void ModifyVideoConfigs(
73 VideoSendStream::Config* send_config,
74 std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
75 VideoEncoderConfig* encoder_config) override {
76 encoder_config->codec_type = PayloadStringToCodecType(payload_name_);
77 send_config->encoder_settings.encoder_factory = encoder_factory_;
78 send_config->rtp.payload_name = payload_name_;
79 send_config->rtp.payload_type = test::CallTest::kVideoSendPayloadType;
80
81 (*receive_configs)[0].renderer = this;
82 (*receive_configs)[0].decoders.resize(1);
83 (*receive_configs)[0].decoders[0].payload_type =
84 send_config->rtp.payload_type;
85 (*receive_configs)[0].decoders[0].video_format =
86 SdpVideoFormat(send_config->rtp.payload_name);
87 (*receive_configs)[0].decoder_factory = decoder_factory_;
88 }
89
OnFrame(const VideoFrame & video_frame)90 void OnFrame(const VideoFrame& video_frame) override {
91 EXPECT_EQ(expected_rotation_, video_frame.rotation());
92 // Test only if explicit color space has been specified since otherwise the
93 // color space is codec dependent.
94 if (expected_color_space_) {
95 EXPECT_EQ(expected_color_space_,
96 video_frame.color_space()
97 ? absl::make_optional(*video_frame.color_space())
98 : absl::nullopt);
99 }
100 if (++frame_counter_ == no_frames_to_wait_for_)
101 observation_complete_.Set();
102 }
103
OnFrameGeneratorCapturerCreated(test::FrameGeneratorCapturer * frame_generator_capturer)104 void OnFrameGeneratorCapturerCreated(
105 test::FrameGeneratorCapturer* frame_generator_capturer) override {
106 frame_generator_capturer->SetFakeRotation(expected_rotation_);
107 frame_generator_capturer->SetFakeColorSpace(expected_color_space_);
108 }
109
110 private:
111 int no_frames_to_wait_for_;
112 VideoRotation expected_rotation_;
113 absl::optional<ColorSpace> expected_color_space_;
114 std::string payload_name_;
115 VideoEncoderFactory* encoder_factory_;
116 VideoDecoderFactory* decoder_factory_;
117 int frame_counter_;
118 };
119
TEST_F(CodecEndToEndTest,SendsAndReceivesVP8)120 TEST_F(CodecEndToEndTest, SendsAndReceivesVP8) {
121 test::FunctionVideoEncoderFactory encoder_factory(
122 []() { return VP8Encoder::Create(); });
123 test::FunctionVideoDecoderFactory decoder_factory(
124 []() { return VP8Decoder::Create(); });
125 CodecObserver test(5, kVideoRotation_0, absl::nullopt, "VP8",
126 &encoder_factory, &decoder_factory);
127 RunBaseTest(&test);
128 }
129
TEST_F(CodecEndToEndTest,SendsAndReceivesVP8Rotation90)130 TEST_F(CodecEndToEndTest, SendsAndReceivesVP8Rotation90) {
131 test::FunctionVideoEncoderFactory encoder_factory(
132 []() { return VP8Encoder::Create(); });
133 test::FunctionVideoDecoderFactory decoder_factory(
134 []() { return VP8Decoder::Create(); });
135 CodecObserver test(5, kVideoRotation_90, absl::nullopt, "VP8",
136 &encoder_factory, &decoder_factory);
137 RunBaseTest(&test);
138 }
139
140 #if defined(RTC_ENABLE_VP9)
TEST_F(CodecEndToEndTest,SendsAndReceivesVP9)141 TEST_F(CodecEndToEndTest, SendsAndReceivesVP9) {
142 test::FunctionVideoEncoderFactory encoder_factory(
143 []() { return VP9Encoder::Create(); });
144 test::FunctionVideoDecoderFactory decoder_factory(
145 []() { return VP9Decoder::Create(); });
146 CodecObserver test(500, kVideoRotation_0, absl::nullopt, "VP9",
147 &encoder_factory, &decoder_factory);
148 RunBaseTest(&test);
149 }
150
TEST_F(CodecEndToEndTest,SendsAndReceivesVP9VideoRotation90)151 TEST_F(CodecEndToEndTest, SendsAndReceivesVP9VideoRotation90) {
152 test::FunctionVideoEncoderFactory encoder_factory(
153 []() { return VP9Encoder::Create(); });
154 test::FunctionVideoDecoderFactory decoder_factory(
155 []() { return VP9Decoder::Create(); });
156 CodecObserver test(5, kVideoRotation_90, absl::nullopt, "VP9",
157 &encoder_factory, &decoder_factory);
158 RunBaseTest(&test);
159 }
160
TEST_F(CodecEndToEndTest,SendsAndReceivesVP9ExplicitColorSpace)161 TEST_F(CodecEndToEndTest, SendsAndReceivesVP9ExplicitColorSpace) {
162 test::FunctionVideoEncoderFactory encoder_factory(
163 []() { return VP9Encoder::Create(); });
164 test::FunctionVideoDecoderFactory decoder_factory(
165 []() { return VP9Decoder::Create(); });
166 CodecObserver test(5, kVideoRotation_90,
167 CreateTestColorSpace(/*with_hdr_metadata=*/false), "VP9",
168 &encoder_factory, &decoder_factory);
169 RunBaseTest(&test);
170 }
171
TEST_F(CodecEndToEndTest,SendsAndReceivesVP9ExplicitColorSpaceWithHdrMetadata)172 TEST_F(CodecEndToEndTest,
173 SendsAndReceivesVP9ExplicitColorSpaceWithHdrMetadata) {
174 test::FunctionVideoEncoderFactory encoder_factory(
175 []() { return VP9Encoder::Create(); });
176 test::FunctionVideoDecoderFactory decoder_factory(
177 []() { return VP9Decoder::Create(); });
178 CodecObserver test(5, kVideoRotation_90,
179 CreateTestColorSpace(/*with_hdr_metadata=*/true), "VP9",
180 &encoder_factory, &decoder_factory);
181 RunBaseTest(&test);
182 }
183
184 // Mutiplex tests are using VP9 as the underlying implementation.
TEST_F(CodecEndToEndTest,SendsAndReceivesMultiplex)185 TEST_F(CodecEndToEndTest, SendsAndReceivesMultiplex) {
186 InternalEncoderFactory internal_encoder_factory;
187 InternalDecoderFactory internal_decoder_factory;
188 test::FunctionVideoEncoderFactory encoder_factory(
189 [&internal_encoder_factory]() {
190 return std::make_unique<MultiplexEncoderAdapter>(
191 &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
192 });
193 test::FunctionVideoDecoderFactory decoder_factory(
194 [&internal_decoder_factory]() {
195 return std::make_unique<MultiplexDecoderAdapter>(
196 &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
197 });
198
199 CodecObserver test(5, kVideoRotation_0, absl::nullopt, "multiplex",
200 &encoder_factory, &decoder_factory);
201 RunBaseTest(&test);
202 }
203
TEST_F(CodecEndToEndTest,SendsAndReceivesMultiplexVideoRotation90)204 TEST_F(CodecEndToEndTest, SendsAndReceivesMultiplexVideoRotation90) {
205 InternalEncoderFactory internal_encoder_factory;
206 InternalDecoderFactory internal_decoder_factory;
207 test::FunctionVideoEncoderFactory encoder_factory(
208 [&internal_encoder_factory]() {
209 return std::make_unique<MultiplexEncoderAdapter>(
210 &internal_encoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
211 });
212 test::FunctionVideoDecoderFactory decoder_factory(
213 [&internal_decoder_factory]() {
214 return std::make_unique<MultiplexDecoderAdapter>(
215 &internal_decoder_factory, SdpVideoFormat(cricket::kVp9CodecName));
216 });
217 CodecObserver test(5, kVideoRotation_90, absl::nullopt, "multiplex",
218 &encoder_factory, &decoder_factory);
219 RunBaseTest(&test);
220 }
221
222 #endif // defined(RTC_ENABLE_VP9)
223
224 #if defined(WEBRTC_USE_H264)
225 class EndToEndTestH264 : public test::CallTest,
226 public ::testing::WithParamInterface<std::string> {
227 public:
EndToEndTestH264()228 EndToEndTestH264() : field_trial_(GetParam()) {
229 RegisterRtpExtension(RtpExtension(RtpExtension::kVideoRotationUri,
230 kVideoRotationExtensionId));
231 }
232
233 private:
234 test::ScopedFieldTrials field_trial_;
235 };
236
237 INSTANTIATE_TEST_SUITE_P(
238 SpsPpsIdrIsKeyframe,
239 EndToEndTestH264,
240 ::testing::Values("WebRTC-SpsPpsIdrIsH264Keyframe/Disabled/",
241 "WebRTC-SpsPpsIdrIsH264Keyframe/Enabled/"));
242
TEST_P(EndToEndTestH264,SendsAndReceivesH264)243 TEST_P(EndToEndTestH264, SendsAndReceivesH264) {
244 test::FunctionVideoEncoderFactory encoder_factory(
245 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
246 test::FunctionVideoDecoderFactory decoder_factory(
247 []() { return H264Decoder::Create(); });
248 CodecObserver test(500, kVideoRotation_0, absl::nullopt, "H264",
249 &encoder_factory, &decoder_factory);
250 RunBaseTest(&test);
251 }
252
TEST_P(EndToEndTestH264,SendsAndReceivesH264VideoRotation90)253 TEST_P(EndToEndTestH264, SendsAndReceivesH264VideoRotation90) {
254 test::FunctionVideoEncoderFactory encoder_factory(
255 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
256 test::FunctionVideoDecoderFactory decoder_factory(
257 []() { return H264Decoder::Create(); });
258 CodecObserver test(5, kVideoRotation_90, absl::nullopt, "H264",
259 &encoder_factory, &decoder_factory);
260 RunBaseTest(&test);
261 }
262
TEST_P(EndToEndTestH264,SendsAndReceivesH264PacketizationMode0)263 TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode0) {
264 cricket::VideoCodec codec = cricket::VideoCodec("H264");
265 codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
266 test::FunctionVideoEncoderFactory encoder_factory(
267 [codec]() { return H264Encoder::Create(codec); });
268 test::FunctionVideoDecoderFactory decoder_factory(
269 []() { return H264Decoder::Create(); });
270 CodecObserver test(500, kVideoRotation_0, absl::nullopt, "H264",
271 &encoder_factory, &decoder_factory);
272 RunBaseTest(&test);
273 }
274
TEST_P(EndToEndTestH264,SendsAndReceivesH264PacketizationMode1)275 TEST_P(EndToEndTestH264, SendsAndReceivesH264PacketizationMode1) {
276 cricket::VideoCodec codec = cricket::VideoCodec("H264");
277 codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
278 test::FunctionVideoEncoderFactory encoder_factory(
279 [codec]() { return H264Encoder::Create(codec); });
280 test::FunctionVideoDecoderFactory decoder_factory(
281 []() { return H264Decoder::Create(); });
282 CodecObserver test(500, kVideoRotation_0, absl::nullopt, "H264",
283 &encoder_factory, &decoder_factory);
284 RunBaseTest(&test);
285 }
286 #endif // defined(WEBRTC_USE_H264)
287
288 } // namespace webrtc
289