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