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::kDefaultTimeoutMs),
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<VideoReceiveStream::Config> * receive_configs,VideoEncoderConfig * encoder_config)72   void ModifyVideoConfigs(
73       VideoSendStream::Config* send_config,
74       std::vector<VideoReceiveStream::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].decoders[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