• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 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 
13 #include "api/test/simulated_network.h"
14 #include "api/test/video/function_video_encoder_factory.h"
15 #include "call/fake_network_pipe.h"
16 #include "call/simulated_network.h"
17 #include "modules/include/module_common_types_public.h"
18 #include "modules/rtp_rtcp/source/rtp_packet.h"
19 #include "modules/video_coding/codecs/h264/include/h264.h"
20 #include "modules/video_coding/codecs/vp8/include/vp8.h"
21 #include "modules/video_coding/codecs/vp9/include/vp9.h"
22 #include "rtc_base/synchronization/mutex.h"
23 #include "rtc_base/task_queue_for_test.h"
24 #include "test/call_test.h"
25 #include "test/gmock.h"
26 #include "test/gtest.h"
27 
28 using ::testing::Contains;
29 
30 namespace webrtc {
31 namespace {
32 constexpr int kWidth = 1280;
33 constexpr int kHeight = 720;
34 constexpr int kFps = 30;
35 constexpr int kFramesToObserve = 10;
36 
PayloadNameToPayloadType(const std::string & payload_name)37 uint8_t PayloadNameToPayloadType(const std::string& payload_name) {
38   if (payload_name == "VP8") {
39     return test::CallTest::kPayloadTypeVP8;
40   } else if (payload_name == "VP9") {
41     return test::CallTest::kPayloadTypeVP9;
42   } else if (payload_name == "H264") {
43     return test::CallTest::kPayloadTypeH264;
44   } else {
45     RTC_NOTREACHED();
46     return 0;
47   }
48 }
49 
RemoveOlderOrEqual(uint32_t timestamp,std::vector<uint32_t> * timestamps)50 int RemoveOlderOrEqual(uint32_t timestamp, std::vector<uint32_t>* timestamps) {
51   int num_removed = 0;
52   while (!timestamps->empty()) {
53     auto it = timestamps->begin();
54     if (IsNewerTimestamp(*it, timestamp))
55       break;
56 
57     timestamps->erase(it);
58     ++num_removed;
59   }
60   return num_removed;
61 }
62 
63 class FrameObserver : public test::RtpRtcpObserver,
64                       public rtc::VideoSinkInterface<VideoFrame> {
65  public:
FrameObserver()66   FrameObserver() : test::RtpRtcpObserver(test::CallTest::kDefaultTimeoutMs) {}
67 
Reset(uint8_t expected_payload_type)68   void Reset(uint8_t expected_payload_type) {
69     MutexLock lock(&mutex_);
70     num_sent_frames_ = 0;
71     num_rendered_frames_ = 0;
72     expected_payload_type_ = expected_payload_type;
73   }
74 
75  private:
76   // Sends kFramesToObserve.
OnSendRtp(const uint8_t * packet,size_t length)77   Action OnSendRtp(const uint8_t* packet, size_t length) override {
78     MutexLock lock(&mutex_);
79 
80     RtpPacket rtp_packet;
81     EXPECT_TRUE(rtp_packet.Parse(packet, length));
82     EXPECT_EQ(rtp_packet.Ssrc(), test::CallTest::kVideoSendSsrcs[0]);
83     if (rtp_packet.payload_size() == 0)
84       return SEND_PACKET;  // Skip padding, may be sent after OnFrame is called.
85 
86     if (expected_payload_type_ &&
87         rtp_packet.PayloadType() != expected_payload_type_.value()) {
88       return DROP_PACKET;  // All frames sent.
89     }
90 
91     if (!last_timestamp_ || rtp_packet.Timestamp() != *last_timestamp_) {
92       // New frame.
93       // Sent enough frames?
94       if (num_sent_frames_ >= kFramesToObserve)
95         return DROP_PACKET;
96 
97       ++num_sent_frames_;
98       sent_timestamps_.push_back(rtp_packet.Timestamp());
99     }
100 
101     last_timestamp_ = rtp_packet.Timestamp();
102     return SEND_PACKET;
103   }
104 
105   // Verifies that all sent frames are decoded and rendered.
OnFrame(const VideoFrame & rendered_frame)106   void OnFrame(const VideoFrame& rendered_frame) override {
107     MutexLock lock(&mutex_);
108     EXPECT_THAT(sent_timestamps_, Contains(rendered_frame.timestamp()));
109 
110     // Remove old timestamps too, only the newest decoded frame is rendered.
111     num_rendered_frames_ +=
112         RemoveOlderOrEqual(rendered_frame.timestamp(), &sent_timestamps_);
113 
114     if (num_rendered_frames_ >= kFramesToObserve) {
115       EXPECT_TRUE(sent_timestamps_.empty()) << "All sent frames not decoded.";
116       observation_complete_.Set();
117     }
118   }
119 
120   Mutex mutex_;
121   absl::optional<uint32_t> last_timestamp_;  // Only accessed from pacer thread.
122   absl::optional<uint8_t> expected_payload_type_ RTC_GUARDED_BY(mutex_);
123   int num_sent_frames_ RTC_GUARDED_BY(mutex_) = 0;
124   int num_rendered_frames_ RTC_GUARDED_BY(mutex_) = 0;
125   std::vector<uint32_t> sent_timestamps_ RTC_GUARDED_BY(mutex_);
126 };
127 }  // namespace
128 
129 class MultiCodecReceiveTest : public test::CallTest {
130  public:
MultiCodecReceiveTest()131   MultiCodecReceiveTest() {
132     SendTask(RTC_FROM_HERE, task_queue(), [this]() {
133       CreateCalls();
134 
135       send_transport_.reset(new test::PacketTransport(
136           task_queue(), sender_call_.get(), &observer_,
137           test::PacketTransport::kSender, kPayloadTypeMap,
138           std::make_unique<FakeNetworkPipe>(
139               Clock::GetRealTimeClock(), std::make_unique<SimulatedNetwork>(
140                                              BuiltInNetworkBehaviorConfig()))));
141       send_transport_->SetReceiver(receiver_call_->Receiver());
142 
143       receive_transport_.reset(new test::PacketTransport(
144           task_queue(), receiver_call_.get(), &observer_,
145           test::PacketTransport::kReceiver, kPayloadTypeMap,
146           std::make_unique<FakeNetworkPipe>(
147               Clock::GetRealTimeClock(), std::make_unique<SimulatedNetwork>(
148                                              BuiltInNetworkBehaviorConfig()))));
149       receive_transport_->SetReceiver(sender_call_->Receiver());
150     });
151   }
152 
~MultiCodecReceiveTest()153   virtual ~MultiCodecReceiveTest() {
154     SendTask(RTC_FROM_HERE, task_queue(), [this]() {
155       send_transport_.reset();
156       receive_transport_.reset();
157       DestroyCalls();
158     });
159   }
160 
161   struct CodecConfig {
162     std::string payload_name;
163     VideoEncoderFactory* encoder_factory;
164     VideoDecoderFactory* decoder_factory;
165     size_t num_temporal_layers;
166   };
167 
168   void ConfigureEncoder(const CodecConfig& config);
169   void ConfigureDecoders(const std::vector<CodecConfig>& configs);
170   void RunTestWithCodecs(const std::vector<CodecConfig>& configs);
171 
172  private:
173   const std::map<uint8_t, MediaType> kPayloadTypeMap = {
174       {CallTest::kPayloadTypeVP8, MediaType::VIDEO},
175       {CallTest::kPayloadTypeVP9, MediaType::VIDEO},
176       {CallTest::kPayloadTypeH264, MediaType::VIDEO}};
177   FrameObserver observer_;
178 };
179 
ConfigureDecoders(const std::vector<CodecConfig> & configs)180 void MultiCodecReceiveTest::ConfigureDecoders(
181     const std::vector<CodecConfig>& configs) {
182   video_receive_configs_[0].decoders.clear();
183   // Placing the payload names in a std::set retains the unique names only.
184   std::set<std::string> unique_payload_names;
185   for (const auto& config : configs)
186     if (unique_payload_names.insert(config.payload_name).second) {
187       VideoReceiveStream::Decoder decoder = test::CreateMatchingDecoder(
188           PayloadNameToPayloadType(config.payload_name), config.payload_name);
189       decoder.decoder_factory = config.decoder_factory;
190 
191       video_receive_configs_[0].decoders.push_back(decoder);
192     }
193 }
194 
ConfigureEncoder(const CodecConfig & config)195 void MultiCodecReceiveTest::ConfigureEncoder(const CodecConfig& config) {
196   GetVideoSendConfig()->encoder_settings.encoder_factory =
197       config.encoder_factory;
198   GetVideoSendConfig()->rtp.payload_name = config.payload_name;
199   GetVideoSendConfig()->rtp.payload_type =
200       PayloadNameToPayloadType(config.payload_name);
201   GetVideoEncoderConfig()->codec_type =
202       PayloadStringToCodecType(config.payload_name);
203   EXPECT_EQ(1u, GetVideoEncoderConfig()->simulcast_layers.size());
204   GetVideoEncoderConfig()->simulcast_layers[0].num_temporal_layers =
205       config.num_temporal_layers;
206 }
207 
RunTestWithCodecs(const std::vector<CodecConfig> & configs)208 void MultiCodecReceiveTest::RunTestWithCodecs(
209     const std::vector<CodecConfig>& configs) {
210   EXPECT_TRUE(!configs.empty());
211 
212   // Create and start call.
213   SendTask(RTC_FROM_HERE, task_queue(), [this, &configs]() {
214     CreateSendConfig(1, 0, 0, send_transport_.get());
215     ConfigureEncoder(configs[0]);
216     CreateMatchingReceiveConfigs(receive_transport_.get());
217     video_receive_configs_[0].renderer = &observer_;
218     // Disable to avoid post-decode frame dropping in VideoRenderFrames.
219     video_receive_configs_[0].enable_prerenderer_smoothing = false;
220     ConfigureDecoders(configs);
221     CreateVideoStreams();
222     CreateFrameGeneratorCapturer(kFps, kWidth, kHeight);
223     Start();
224   });
225   EXPECT_TRUE(observer_.Wait()) << "Timed out waiting for frames.";
226 
227   for (size_t i = 1; i < configs.size(); ++i) {
228     // Recreate VideoSendStream with new config (codec, temporal layers).
229     SendTask(RTC_FROM_HERE, task_queue(), [this, i, &configs]() {
230       DestroyVideoSendStreams();
231       observer_.Reset(PayloadNameToPayloadType(configs[i].payload_name));
232 
233       ConfigureEncoder(configs[i]);
234       CreateVideoSendStreams();
235       GetVideoSendStream()->Start();
236       CreateFrameGeneratorCapturer(kFps, kWidth / 2, kHeight / 2);
237       ConnectVideoSourcesToStreams();
238     });
239     EXPECT_TRUE(observer_.Wait()) << "Timed out waiting for frames.";
240   }
241 
242   SendTask(RTC_FROM_HERE, task_queue(), [this]() {
243     Stop();
244     DestroyStreams();
245   });
246 }
247 
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8Vp9)248 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9) {
249   test::FunctionVideoEncoderFactory vp8_encoder_factory(
250       []() { return VP8Encoder::Create(); });
251   test::FunctionVideoEncoderFactory vp9_encoder_factory(
252       []() { return VP9Encoder::Create(); });
253   test::FunctionVideoDecoderFactory vp8_decoder_factory(
254       []() { return VP8Decoder::Create(); });
255   test::FunctionVideoDecoderFactory vp9_decoder_factory(
256       []() { return VP9Decoder::Create(); });
257   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
258                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
259                      {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
260 }
261 
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8Vp9WithTl)262 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9WithTl) {
263   test::FunctionVideoEncoderFactory vp8_encoder_factory(
264       []() { return VP8Encoder::Create(); });
265   test::FunctionVideoEncoderFactory vp9_encoder_factory(
266       []() { return VP9Encoder::Create(); });
267   test::FunctionVideoDecoderFactory vp8_decoder_factory(
268       []() { return VP8Decoder::Create(); });
269   test::FunctionVideoDecoderFactory vp9_decoder_factory(
270       []() { return VP9Decoder::Create(); });
271   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2},
272                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
273                      {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2}});
274 }
275 
276 #if defined(WEBRTC_USE_H264)
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8H264)277 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8H264) {
278   test::FunctionVideoEncoderFactory vp8_encoder_factory(
279       []() { return VP8Encoder::Create(); });
280   test::FunctionVideoEncoderFactory h264_encoder_factory(
281       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
282   test::FunctionVideoDecoderFactory vp8_decoder_factory(
283       []() { return VP8Decoder::Create(); });
284   test::FunctionVideoDecoderFactory h264_decoder_factory(
285       []() { return H264Decoder::Create(); });
286   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
287                      {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
288                      {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
289 }
290 
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8H264WithTl)291 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8H264WithTl) {
292   test::FunctionVideoEncoderFactory vp8_encoder_factory(
293       []() { return VP8Encoder::Create(); });
294   test::FunctionVideoEncoderFactory h264_encoder_factory(
295       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
296   test::FunctionVideoDecoderFactory vp8_decoder_factory(
297       []() { return VP8Decoder::Create(); });
298   test::FunctionVideoDecoderFactory h264_decoder_factory(
299       []() { return H264Decoder::Create(); });
300   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
301                      {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
302                      {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3}});
303 }
304 
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8Vp9H264)305 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264) {
306   test::FunctionVideoEncoderFactory vp8_encoder_factory(
307       []() { return VP8Encoder::Create(); });
308   test::FunctionVideoEncoderFactory vp9_encoder_factory(
309       []() { return VP9Encoder::Create(); });
310   test::FunctionVideoEncoderFactory h264_encoder_factory(
311       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
312   test::FunctionVideoDecoderFactory vp8_decoder_factory(
313       []() { return VP8Decoder::Create(); });
314   test::FunctionVideoDecoderFactory vp9_decoder_factory(
315       []() { return VP9Decoder::Create(); });
316   test::FunctionVideoDecoderFactory h264_decoder_factory(
317       []() { return H264Decoder::Create(); });
318   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
319                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
320                      {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
321                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1}});
322 }
323 
TEST_F(MultiCodecReceiveTest,SingleStreamReceivesVp8Vp9H264WithTl)324 TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264WithTl) {
325   test::FunctionVideoEncoderFactory vp8_encoder_factory(
326       []() { return VP8Encoder::Create(); });
327   test::FunctionVideoEncoderFactory vp9_encoder_factory(
328       []() { return VP9Encoder::Create(); });
329   test::FunctionVideoEncoderFactory h264_encoder_factory(
330       []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
331   test::FunctionVideoDecoderFactory vp8_decoder_factory(
332       []() { return VP8Decoder::Create(); });
333   test::FunctionVideoDecoderFactory vp9_decoder_factory(
334       []() { return VP9Decoder::Create(); });
335   test::FunctionVideoDecoderFactory h264_decoder_factory(
336       []() { return H264Decoder::Create(); });
337   RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
338                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
339                      {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
340                      {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 3}});
341 }
342 #endif  // defined(WEBRTC_USE_H264)
343 
344 }  // namespace webrtc
345