blob: 338e7a1bf291aa53379c766633502564699c7906 [file] [log] [blame]
Åsa Persson96c9fc42018-05-23 10:47:201/*
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
Artem Titov46c4e602018-08-17 12:26:5411#include "api/test/simulated_network.h"
Artem Titov4e199e92018-08-20 11:30:3912#include "call/fake_network_pipe.h"
13#include "call/simulated_network.h"
Åsa Persson96c9fc42018-05-23 10:47:2014#include "modules/video_coding/codecs/h264/include/h264.h"
15#include "modules/video_coding/codecs/vp8/include/vp8.h"
16#include "modules/video_coding/codecs/vp9/include/vp9.h"
17#include "test/call_test.h"
18#include "test/function_video_encoder_factory.h"
19#include "test/gtest.h"
20
21namespace webrtc {
22namespace {
23constexpr int kWidth = 1280;
24constexpr int kHeight = 720;
25constexpr int kFps = 30;
26constexpr int kFramesToObserve = 10;
27
28uint8_t PayloadNameToPayloadType(const std::string& payload_name) {
29 if (payload_name == "VP8") {
30 return test::CallTest::kPayloadTypeVP8;
31 } else if (payload_name == "VP9") {
32 return test::CallTest::kPayloadTypeVP9;
33 } else if (payload_name == "H264") {
34 return test::CallTest::kPayloadTypeH264;
35 } else {
36 RTC_NOTREACHED();
37 return 0;
38 }
39}
40
41int RemoveOlderOrEqual(uint32_t timestamp, std::vector<uint32_t>* timestamps) {
42 int num_removed = 0;
43 while (!timestamps->empty()) {
44 auto it = timestamps->begin();
45 if (IsNewerTimestamp(*it, timestamp))
46 break;
47
48 timestamps->erase(it);
49 ++num_removed;
50 }
51 return num_removed;
52}
53
Åsa Persson96c9fc42018-05-23 10:47:2054class FrameObserver : public test::RtpRtcpObserver,
55 public rtc::VideoSinkInterface<VideoFrame> {
56 public:
57 FrameObserver() : test::RtpRtcpObserver(test::CallTest::kDefaultTimeoutMs) {}
58
59 void Reset() {
60 rtc::CritScope lock(&crit_);
61 num_sent_frames_ = 0;
62 num_rendered_frames_ = 0;
63 }
64
65 private:
66 // Sends kFramesToObserve.
67 Action OnSendRtp(const uint8_t* packet, size_t length) override {
68 rtc::CritScope lock(&crit_);
69
70 RTPHeader header;
71 EXPECT_TRUE(parser_->Parse(packet, length, &header));
72 EXPECT_EQ(header.ssrc, test::CallTest::kVideoSendSsrcs[0]);
73 EXPECT_GE(length, header.headerLength + header.paddingLength);
74 if ((length - header.headerLength) == header.paddingLength)
75 return SEND_PACKET; // Skip padding, may be sent after OnFrame is called.
76
77 if (!last_timestamp_ || header.timestamp != *last_timestamp_) {
78 // New frame.
79 if (last_payload_type_) {
80 bool new_payload_type = header.payloadType != *last_payload_type_;
81 EXPECT_EQ(num_sent_frames_ == 0, new_payload_type)
82 << "Payload type should change after reset.";
83 }
84 // Sent enough frames?
85 if (num_sent_frames_ >= kFramesToObserve)
86 return DROP_PACKET;
87
88 ++num_sent_frames_;
89 sent_timestamps_.push_back(header.timestamp);
90 }
91
92 last_timestamp_ = header.timestamp;
93 last_payload_type_ = header.payloadType;
94 return SEND_PACKET;
95 }
96
97 // Verifies that all sent frames are decoded and rendered.
98 void OnFrame(const VideoFrame& rendered_frame) override {
99 rtc::CritScope lock(&crit_);
100 EXPECT_NE(std::find(sent_timestamps_.begin(), sent_timestamps_.end(),
101 rendered_frame.timestamp()),
102 sent_timestamps_.end());
103
104 // Remove old timestamps too, only the newest decoded frame is rendered.
105 num_rendered_frames_ +=
106 RemoveOlderOrEqual(rendered_frame.timestamp(), &sent_timestamps_);
107
108 if (num_rendered_frames_ >= kFramesToObserve) {
109 EXPECT_TRUE(sent_timestamps_.empty()) << "All sent frames not decoded.";
110 observation_complete_.Set();
111 }
112 }
113
114 rtc::CriticalSection crit_;
Danil Chapovalovb9b146c2018-06-15 10:28:07115 absl::optional<uint32_t> last_timestamp_;
116 absl::optional<uint8_t> last_payload_type_;
Åsa Persson96c9fc42018-05-23 10:47:20117 int num_sent_frames_ RTC_GUARDED_BY(crit_) = 0;
118 int num_rendered_frames_ RTC_GUARDED_BY(crit_) = 0;
119 std::vector<uint32_t> sent_timestamps_ RTC_GUARDED_BY(crit_);
120};
121} // namespace
122
123class MultiCodecReceiveTest : public test::CallTest {
124 public:
125 MultiCodecReceiveTest() {
126 task_queue_.SendTask([this]() {
Sebastian Jansson8e6602f2018-07-13 08:43:20127 CreateCalls();
Åsa Persson96c9fc42018-05-23 10:47:20128
129 send_transport_.reset(new test::PacketTransport(
130 &task_queue_, sender_call_.get(), &observer_,
131 test::PacketTransport::kSender, kPayloadTypeMap,
Artem Titov4e199e92018-08-20 11:30:39132 absl::make_unique<FakeNetworkPipe>(
Artem Titov75e36472018-10-08 10:28:56133 Clock::GetRealTimeClock(), absl::make_unique<SimulatedNetwork>(
134 BuiltInNetworkBehaviorConfig()))));
Åsa Persson96c9fc42018-05-23 10:47:20135 send_transport_->SetReceiver(receiver_call_->Receiver());
136
137 receive_transport_.reset(new test::PacketTransport(
138 &task_queue_, receiver_call_.get(), &observer_,
139 test::PacketTransport::kReceiver, kPayloadTypeMap,
Artem Titov4e199e92018-08-20 11:30:39140 absl::make_unique<FakeNetworkPipe>(
Artem Titov75e36472018-10-08 10:28:56141 Clock::GetRealTimeClock(), absl::make_unique<SimulatedNetwork>(
142 BuiltInNetworkBehaviorConfig()))));
Åsa Persson96c9fc42018-05-23 10:47:20143 receive_transport_->SetReceiver(sender_call_->Receiver());
144 });
145 }
146
147 virtual ~MultiCodecReceiveTest() {
Åsa Persson96c9fc42018-05-23 10:47:20148 task_queue_.SendTask([this]() {
149 send_transport_.reset();
150 receive_transport_.reset();
151 DestroyCalls();
152 });
153 }
154
155 struct CodecConfig {
156 std::string payload_name;
157 VideoEncoderFactory* encoder_factory;
Niels Möllercbcbc222018-09-28 07:07:24158 VideoDecoderFactory* decoder_factory;
Åsa Persson96c9fc42018-05-23 10:47:20159 size_t num_temporal_layers;
160 };
161
162 void ConfigureEncoder(const CodecConfig& config);
163 void ConfigureDecoders(const std::vector<CodecConfig>& configs);
164 void RunTestWithCodecs(const std::vector<CodecConfig>& configs);
165
166 private:
167 const std::map<uint8_t, MediaType> kPayloadTypeMap = {
168 {CallTest::kPayloadTypeVP8, MediaType::VIDEO},
169 {CallTest::kPayloadTypeVP9, MediaType::VIDEO},
170 {CallTest::kPayloadTypeH264, MediaType::VIDEO}};
171 FrameObserver observer_;
172};
173
174void MultiCodecReceiveTest::ConfigureDecoders(
175 const std::vector<CodecConfig>& configs) {
Niels Möllercbcbc222018-09-28 07:07:24176 video_receive_configs_[0].decoders.clear();
Åsa Persson96c9fc42018-05-23 10:47:20177 // Placing the payload names in a std::set retains the unique names only.
178 std::set<std::string> unique_payload_names;
179 for (const auto& config : configs)
Niels Möllercbcbc222018-09-28 07:07:24180 if (unique_payload_names.insert(config.payload_name).second) {
181 VideoReceiveStream::Decoder decoder = test::CreateMatchingDecoder(
182 PayloadNameToPayloadType(config.payload_name), config.payload_name);
183 decoder.decoder_factory = config.decoder_factory;
Åsa Persson96c9fc42018-05-23 10:47:20184
Niels Möllercbcbc222018-09-28 07:07:24185 video_receive_configs_[0].decoders.push_back(decoder);
Åsa Persson96c9fc42018-05-23 10:47:20186 }
187}
188
189void MultiCodecReceiveTest::ConfigureEncoder(const CodecConfig& config) {
Sebastian Janssonf33905d2018-07-13 07:49:00190 GetVideoSendConfig()->encoder_settings.encoder_factory =
191 config.encoder_factory;
192 GetVideoSendConfig()->rtp.payload_name = config.payload_name;
193 GetVideoSendConfig()->rtp.payload_type =
Åsa Persson96c9fc42018-05-23 10:47:20194 PayloadNameToPayloadType(config.payload_name);
Sebastian Janssonf33905d2018-07-13 07:49:00195 GetVideoEncoderConfig()->codec_type =
Åsa Persson96c9fc42018-05-23 10:47:20196 PayloadStringToCodecType(config.payload_name);
Åsa Perssond34597c2018-10-22 15:34:02197 EXPECT_EQ(1u, GetVideoEncoderConfig()->simulcast_layers.size());
198 GetVideoEncoderConfig()->simulcast_layers[0].num_temporal_layers =
199 config.num_temporal_layers;
Åsa Persson96c9fc42018-05-23 10:47:20200}
201
202void MultiCodecReceiveTest::RunTestWithCodecs(
203 const std::vector<CodecConfig>& configs) {
204 EXPECT_TRUE(!configs.empty());
205
206 // Create and start call.
207 task_queue_.SendTask([this, &configs]() {
208 CreateSendConfig(1, 0, 0, send_transport_.get());
209 ConfigureEncoder(configs[0]);
210 CreateMatchingReceiveConfigs(receive_transport_.get());
211 video_receive_configs_[0].renderer = &observer_;
212 ConfigureDecoders(configs);
213 CreateVideoStreams();
214 CreateFrameGeneratorCapturer(kFps, kWidth, kHeight);
215 Start();
216 });
217 EXPECT_TRUE(observer_.Wait()) << "Timed out waiting for frames.";
218
219 for (size_t i = 1; i < configs.size(); ++i) {
220 // Recreate VideoSendStream with new config (codec, temporal layers).
221 task_queue_.SendTask([this, i, &configs]() {
222 frame_generator_capturer_->Stop();
Sebastian Janssonf33905d2018-07-13 07:49:00223 DestroyVideoSendStreams();
Åsa Persson96c9fc42018-05-23 10:47:20224 observer_.Reset();
225
226 ConfigureEncoder(configs[i]);
Sebastian Janssonf33905d2018-07-13 07:49:00227 CreateVideoSendStreams();
228 GetVideoSendStream()->Start();
Åsa Persson96c9fc42018-05-23 10:47:20229 CreateFrameGeneratorCapturer(kFps, kWidth / 2, kHeight / 2);
Sebastian Janssonf33905d2018-07-13 07:49:00230 ConnectVideoSourcesToStreams();
Åsa Persson96c9fc42018-05-23 10:47:20231 frame_generator_capturer_->Start();
232 });
233 EXPECT_TRUE(observer_.Wait()) << "Timed out waiting for frames.";
234 }
235
236 task_queue_.SendTask([this]() {
237 Stop();
238 DestroyStreams();
239 });
240}
241
242TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9) {
243 test::FunctionVideoEncoderFactory vp8_encoder_factory(
244 []() { return VP8Encoder::Create(); });
245 test::FunctionVideoEncoderFactory vp9_encoder_factory(
246 []() { return VP9Encoder::Create(); });
Niels Möllercbcbc222018-09-28 07:07:24247 test::FunctionVideoDecoderFactory vp8_decoder_factory(
248 []() { return VP8Decoder::Create(); });
249 test::FunctionVideoDecoderFactory vp9_decoder_factory(
250 []() { return VP9Decoder::Create(); });
251 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
252 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
253 {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
Åsa Persson96c9fc42018-05-23 10:47:20254}
255
256TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9WithTl) {
257 test::FunctionVideoEncoderFactory vp8_encoder_factory(
258 []() { return VP8Encoder::Create(); });
259 test::FunctionVideoEncoderFactory vp9_encoder_factory(
260 []() { return VP9Encoder::Create(); });
Niels Möllercbcbc222018-09-28 07:07:24261 test::FunctionVideoDecoderFactory vp8_decoder_factory(
262 []() { return VP8Decoder::Create(); });
263 test::FunctionVideoDecoderFactory vp9_decoder_factory(
264 []() { return VP9Decoder::Create(); });
265 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2},
266 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
267 {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 2}});
Åsa Persson96c9fc42018-05-23 10:47:20268}
269
270#if defined(WEBRTC_USE_H264)
271TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8H264) {
272 test::FunctionVideoEncoderFactory vp8_encoder_factory(
273 []() { return VP8Encoder::Create(); });
274 test::FunctionVideoEncoderFactory h264_encoder_factory(
275 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
Niels Möllercbcbc222018-09-28 07:07:24276 test::FunctionVideoDecoderFactory vp8_decoder_factory(
277 []() { return VP8Decoder::Create(); });
278 test::FunctionVideoDecoderFactory h264_decoder_factory(
279 []() { return H264Decoder::Create(); });
280 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
281 {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
282 {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1}});
Åsa Persson96c9fc42018-05-23 10:47:20283}
284
285TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8H264WithTl) {
286 test::FunctionVideoEncoderFactory vp8_encoder_factory(
287 []() { return VP8Encoder::Create(); });
288 test::FunctionVideoEncoderFactory h264_encoder_factory(
289 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
Niels Möllercbcbc222018-09-28 07:07:24290 test::FunctionVideoDecoderFactory vp8_decoder_factory(
291 []() { return VP8Decoder::Create(); });
292 test::FunctionVideoDecoderFactory h264_decoder_factory(
293 []() { return H264Decoder::Create(); });
294 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
295 {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
296 {"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3}});
Åsa Persson96c9fc42018-05-23 10:47:20297}
298
299TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264) {
300 test::FunctionVideoEncoderFactory vp8_encoder_factory(
301 []() { return VP8Encoder::Create(); });
302 test::FunctionVideoEncoderFactory vp9_encoder_factory(
303 []() { return VP9Encoder::Create(); });
304 test::FunctionVideoEncoderFactory h264_encoder_factory(
305 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
Niels Möllercbcbc222018-09-28 07:07:24306 test::FunctionVideoDecoderFactory vp8_decoder_factory(
307 []() { return VP8Decoder::Create(); });
308 test::FunctionVideoDecoderFactory vp9_decoder_factory(
309 []() { return VP9Decoder::Create(); });
310 test::FunctionVideoDecoderFactory h264_decoder_factory(
311 []() { return H264Decoder::Create(); });
312 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 1},
313 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1},
314 {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
315 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 1}});
Åsa Persson96c9fc42018-05-23 10:47:20316}
317
318TEST_F(MultiCodecReceiveTest, SingleStreamReceivesVp8Vp9H264WithTl) {
319 test::FunctionVideoEncoderFactory vp8_encoder_factory(
320 []() { return VP8Encoder::Create(); });
321 test::FunctionVideoEncoderFactory vp9_encoder_factory(
322 []() { return VP9Encoder::Create(); });
323 test::FunctionVideoEncoderFactory h264_encoder_factory(
324 []() { return H264Encoder::Create(cricket::VideoCodec("H264")); });
Niels Möllercbcbc222018-09-28 07:07:24325 test::FunctionVideoDecoderFactory vp8_decoder_factory(
326 []() { return VP8Decoder::Create(); });
327 test::FunctionVideoDecoderFactory vp9_decoder_factory(
328 []() { return VP9Decoder::Create(); });
329 test::FunctionVideoDecoderFactory h264_decoder_factory(
330 []() { return H264Decoder::Create(); });
331 RunTestWithCodecs({{"VP8", &vp8_encoder_factory, &vp8_decoder_factory, 3},
332 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 2},
333 {"H264", &h264_encoder_factory, &h264_decoder_factory, 1},
334 {"VP9", &vp9_encoder_factory, &vp9_decoder_factory, 3}});
Åsa Persson96c9fc42018-05-23 10:47:20335}
336#endif // defined(WEBRTC_USE_H264)
337
338} // namespace webrtc