blob: 3bbc0704b9a7dfe9a4c7ff59050ce4fb21f140df [file] [log] [blame]
Tommiae4d0972020-05-18 08:45:38 +02001/*
2 * Copyright 2017 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 "video/video_receive_stream2.h"
12
13#include <algorithm>
Markus Handell588f9b32021-04-08 19:19:50 +020014#include <limits>
Tommiae4d0972020-05-18 08:45:38 +020015#include <memory>
16#include <utility>
17#include <vector>
18
19#include "api/task_queue/default_task_queue_factory.h"
20#include "api/test/video/function_video_decoder_factory.h"
Markus Handell588f9b32021-04-08 19:19:50 +020021#include "api/video/video_frame.h"
Tommiae4d0972020-05-18 08:45:38 +020022#include "api/video_codecs/video_decoder.h"
23#include "call/rtp_stream_receiver_controller.h"
24#include "common_video/test/utilities.h"
25#include "media/base/fake_video_renderer.h"
26#include "modules/pacing/packet_router.h"
27#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
28#include "modules/utility/include/process_thread.h"
29#include "modules/video_coding/encoded_frame.h"
Tommiae4d0972020-05-18 08:45:38 +020030#include "rtc_base/event.h"
31#include "system_wrappers/include/clock.h"
32#include "test/fake_decoder.h"
33#include "test/field_trial.h"
34#include "test/gmock.h"
35#include "test/gtest.h"
36#include "test/run_loop.h"
37#include "test/time_controller/simulated_time_controller.h"
38#include "test/video_decoder_proxy_factory.h"
39#include "video/call_stats2.h"
40
41namespace webrtc {
42namespace {
43
44using ::testing::_;
Markus Handell588f9b32021-04-08 19:19:50 +020045using ::testing::AllOf;
Tommiae4d0972020-05-18 08:45:38 +020046using ::testing::ElementsAreArray;
Markus Handell588f9b32021-04-08 19:19:50 +020047using ::testing::Field;
48using ::testing::InSequence;
Tommiae4d0972020-05-18 08:45:38 +020049using ::testing::Invoke;
50using ::testing::IsEmpty;
Markus Handell588f9b32021-04-08 19:19:50 +020051using ::testing::Property;
Tommiae4d0972020-05-18 08:45:38 +020052using ::testing::SizeIs;
53
54constexpr int kDefaultTimeOutMs = 50;
55
56class MockTransport : public Transport {
57 public:
58 MOCK_METHOD(bool,
59 SendRtp,
60 (const uint8_t*, size_t length, const PacketOptions& options),
61 (override));
62 MOCK_METHOD(bool, SendRtcp, (const uint8_t*, size_t length), (override));
63};
64
65class MockVideoDecoder : public VideoDecoder {
66 public:
67 MOCK_METHOD(int32_t,
68 InitDecode,
69 (const VideoCodec*, int32_t number_of_cores),
70 (override));
71 MOCK_METHOD(int32_t,
72 Decode,
73 (const EncodedImage& input,
74 bool missing_frames,
75 int64_t render_time_ms),
76 (override));
77 MOCK_METHOD(int32_t,
78 RegisterDecodeCompleteCallback,
79 (DecodedImageCallback*),
80 (override));
81 MOCK_METHOD(int32_t, Release, (), (override));
82 const char* ImplementationName() const { return "MockVideoDecoder"; }
83};
84
Johannes Kron16359f62021-02-18 23:37:22 +010085class MockVideoDecoderFactory : public VideoDecoderFactory {
86 public:
87 MOCK_CONST_METHOD0(GetSupportedFormats, std::vector<SdpVideoFormat>());
88
89 MOCK_METHOD1(CreateVideoDecoder,
90 std::unique_ptr<VideoDecoder>(const SdpVideoFormat& format));
91};
92
philipelca188092021-03-23 12:00:49 +010093class FrameObjectFake : public EncodedFrame {
Tommiae4d0972020-05-18 08:45:38 +020094 public:
95 void SetPayloadType(uint8_t payload_type) { _payloadType = payload_type; }
96
97 void SetRotation(const VideoRotation& rotation) { rotation_ = rotation; }
98
99 void SetNtpTime(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; }
100
101 int64_t ReceivedTime() const override { return 0; }
102
103 int64_t RenderTime() const override { return _renderTimeMs; }
104};
105
106} // namespace
107
108class VideoReceiveStream2Test : public ::testing::Test {
109 public:
110 VideoReceiveStream2Test()
111 : process_thread_(ProcessThread::Create("TestThread")),
112 task_queue_factory_(CreateDefaultTaskQueueFactory()),
113 config_(&mock_transport_),
114 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()),
philipel668b0532020-07-23 13:13:40 +0200115 h264_decoder_factory_(&mock_h264_video_decoder_) {}
Tommiae4d0972020-05-18 08:45:38 +0200116
117 void SetUp() {
118 constexpr int kDefaultNumCpuCores = 2;
119 config_.rtp.remote_ssrc = 1111;
120 config_.rtp.local_ssrc = 2222;
121 config_.renderer = &fake_renderer_;
Philip Eliasson2b068ce2020-08-03 15:55:10 +0000122 config_.decoder_factory = &h264_decoder_factory_;
Tommiae4d0972020-05-18 08:45:38 +0200123 VideoReceiveStream::Decoder h264_decoder;
124 h264_decoder.payload_type = 99;
125 h264_decoder.video_format = SdpVideoFormat("H264");
126 h264_decoder.video_format.parameters.insert(
127 {"sprop-parameter-sets", "Z0IACpZTBYmI,aMljiA=="});
Johannes Kron16359f62021-02-18 23:37:22 +0100128 config_.decoders.clear();
Tommiae4d0972020-05-18 08:45:38 +0200129 config_.decoders.push_back(h264_decoder);
Tommiae4d0972020-05-18 08:45:38 +0200130
131 clock_ = Clock::GetRealTimeClock();
132 timing_ = new VCMTiming(clock_);
133
134 video_receive_stream_ =
135 std::make_unique<webrtc::internal::VideoReceiveStream2>(
136 task_queue_factory_.get(), loop_.task_queue(),
137 &rtp_stream_receiver_controller_, kDefaultNumCpuCores,
138 &packet_router_, config_.Copy(), process_thread_.get(),
139 &call_stats_, clock_, timing_);
140 }
141
142 protected:
143 test::RunLoop loop_;
144 std::unique_ptr<ProcessThread> process_thread_;
145 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
146 VideoReceiveStream::Config config_;
147 internal::CallStats call_stats_;
148 MockVideoDecoder mock_h264_video_decoder_;
Tommiae4d0972020-05-18 08:45:38 +0200149 test::VideoDecoderProxyFactory h264_decoder_factory_;
Tommiae4d0972020-05-18 08:45:38 +0200150 cricket::FakeVideoRenderer fake_renderer_;
151 MockTransport mock_transport_;
152 PacketRouter packet_router_;
153 RtpStreamReceiverController rtp_stream_receiver_controller_;
154 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
155 Clock* clock_;
156 VCMTiming* timing_;
157};
158
159TEST_F(VideoReceiveStream2Test, CreateFrameFromH264FmtpSpropAndIdr) {
160 constexpr uint8_t idr_nalu[] = {0x05, 0xFF, 0xFF, 0xFF};
161 RtpPacketToSend rtppacket(nullptr);
162 uint8_t* payload = rtppacket.AllocatePayload(sizeof(idr_nalu));
163 memcpy(payload, idr_nalu, sizeof(idr_nalu));
164 rtppacket.SetMarker(true);
165 rtppacket.SetSsrc(1111);
166 rtppacket.SetPayloadType(99);
167 rtppacket.SetSequenceNumber(1);
168 rtppacket.SetTimestamp(0);
169 rtc::Event init_decode_event_;
170 EXPECT_CALL(mock_h264_video_decoder_, InitDecode(_, _))
171 .WillOnce(Invoke([&init_decode_event_](const VideoCodec* config,
172 int32_t number_of_cores) {
173 init_decode_event_.Set();
174 return 0;
175 }));
176 EXPECT_CALL(mock_h264_video_decoder_, RegisterDecodeCompleteCallback(_));
177 video_receive_stream_->Start();
178 EXPECT_CALL(mock_h264_video_decoder_, Decode(_, false, _));
179 RtpPacketReceived parsed_packet;
180 ASSERT_TRUE(parsed_packet.Parse(rtppacket.data(), rtppacket.size()));
181 rtp_stream_receiver_controller_.OnRtpPacket(parsed_packet);
182 EXPECT_CALL(mock_h264_video_decoder_, Release());
183 // Make sure the decoder thread had a chance to run.
184 init_decode_event_.Wait(kDefaultTimeOutMs);
185}
186
187TEST_F(VideoReceiveStream2Test, PlayoutDelay) {
Niels Möllerd381eed2020-09-02 15:34:40 +0200188 const VideoPlayoutDelay kPlayoutDelayMs = {123, 321};
Tommiae4d0972020-05-18 08:45:38 +0200189 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100190 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200191 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
192
193 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
194 EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
195 EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
196
197 // Check that the biggest minimum delay is chosen.
198 video_receive_stream_->SetMinimumPlayoutDelay(400);
199 EXPECT_EQ(400, timing_->min_playout_delay());
200
201 // Check base minimum delay validation.
202 EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(12345));
203 EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(-1));
204 EXPECT_TRUE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(500));
205 EXPECT_EQ(500, timing_->min_playout_delay());
206
207 // Check that intermidiate values are remembered and the biggest remembered
208 // is chosen.
209 video_receive_stream_->SetBaseMinimumPlayoutDelayMs(0);
210 EXPECT_EQ(400, timing_->min_playout_delay());
211
212 video_receive_stream_->SetMinimumPlayoutDelay(0);
213 EXPECT_EQ(123, timing_->min_playout_delay());
214}
215
216TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMaxValue) {
217 const int default_max_playout_latency = timing_->max_playout_delay();
Niels Möllerd381eed2020-09-02 15:34:40 +0200218 const VideoPlayoutDelay kPlayoutDelayMs = {123, -1};
Tommiae4d0972020-05-18 08:45:38 +0200219
220 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100221 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200222 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
223
224 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
225
226 // Ensure that -1 preserves default maximum value from |timing_|.
227 EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
228 EXPECT_NE(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
229 EXPECT_EQ(default_max_playout_latency, timing_->max_playout_delay());
230}
231
232TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
233 const int default_min_playout_latency = timing_->min_playout_delay();
Niels Möllerd381eed2020-09-02 15:34:40 +0200234 const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321};
Tommiae4d0972020-05-18 08:45:38 +0200235
236 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100237 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200238 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
239
240 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
241
242 // Ensure that -1 preserves default minimum value from |timing_|.
243 EXPECT_NE(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
244 EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
245 EXPECT_EQ(default_min_playout_latency, timing_->min_playout_delay());
246}
247
Johannes Kron111e9812020-10-26 13:54:40 +0100248TEST_F(VideoReceiveStream2Test, MaxCompositionDelayNotSetByDefault) {
249 // Default with no playout delay set.
250 std::unique_ptr<FrameObjectFake> test_frame0(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100251 test_frame0->SetId(0);
Johannes Kron111e9812020-10-26 13:54:40 +0100252 video_receive_stream_->OnCompleteFrame(std::move(test_frame0));
253 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
254
255 // Max composition delay not set for playout delay 0,0.
256 std::unique_ptr<FrameObjectFake> test_frame1(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100257 test_frame1->SetId(1);
Johannes Kron111e9812020-10-26 13:54:40 +0100258 test_frame1->SetPlayoutDelay({0, 0});
259 video_receive_stream_->OnCompleteFrame(std::move(test_frame1));
260 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
261
262 // Max composition delay not set for playout delay X,Y, where X,Y>0.
263 std::unique_ptr<FrameObjectFake> test_frame2(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100264 test_frame2->SetId(2);
Johannes Kron111e9812020-10-26 13:54:40 +0100265 test_frame2->SetPlayoutDelay({10, 30});
266 video_receive_stream_->OnCompleteFrame(std::move(test_frame2));
267 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
268}
269
270TEST_F(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
271 // Max composition delay set if playout delay X,Y, where X=0,Y>0.
272 const VideoPlayoutDelay kPlayoutDelayMs = {0, 50};
273 const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
274 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100275 test_frame->SetId(0);
Johannes Kron111e9812020-10-26 13:54:40 +0100276 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
277 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
278 EXPECT_EQ(kExpectedMaxCompositionDelayInFrames,
279 timing_->MaxCompositionDelayInFrames());
280}
281
Tommiae4d0972020-05-18 08:45:38 +0200282class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test {
283 public:
284 VideoReceiveStream2TestWithFakeDecoder()
285 : fake_decoder_factory_(
286 []() { return std::make_unique<test::FakeDecoder>(); }),
287 process_thread_(ProcessThread::Create("TestThread")),
288 task_queue_factory_(CreateDefaultTaskQueueFactory()),
289 config_(&mock_transport_),
290 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {}
291
292 void SetUp() {
293 config_.rtp.remote_ssrc = 1111;
294 config_.rtp.local_ssrc = 2222;
295 config_.renderer = &fake_renderer_;
Philip Eliasson2b068ce2020-08-03 15:55:10 +0000296 config_.decoder_factory = &fake_decoder_factory_;
Tommiae4d0972020-05-18 08:45:38 +0200297 VideoReceiveStream::Decoder fake_decoder;
298 fake_decoder.payload_type = 99;
299 fake_decoder.video_format = SdpVideoFormat("VP8");
Tommiae4d0972020-05-18 08:45:38 +0200300 config_.decoders.push_back(fake_decoder);
301 clock_ = Clock::GetRealTimeClock();
302 ReCreateReceiveStream(VideoReceiveStream::RecordingState());
303 }
304
305 void ReCreateReceiveStream(VideoReceiveStream::RecordingState state) {
306 constexpr int kDefaultNumCpuCores = 2;
307 video_receive_stream_ = nullptr;
308 timing_ = new VCMTiming(clock_);
309 video_receive_stream_.reset(new webrtc::internal::VideoReceiveStream2(
310 task_queue_factory_.get(), loop_.task_queue(),
311 &rtp_stream_receiver_controller_, kDefaultNumCpuCores, &packet_router_,
312 config_.Copy(), process_thread_.get(), &call_stats_, clock_, timing_));
313 video_receive_stream_->SetAndGetRecordingState(std::move(state), false);
314 }
315
316 protected:
317 test::RunLoop loop_;
318 test::FunctionVideoDecoderFactory fake_decoder_factory_;
319 std::unique_ptr<ProcessThread> process_thread_;
320 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
321 VideoReceiveStream::Config config_;
322 internal::CallStats call_stats_;
323 cricket::FakeVideoRenderer fake_renderer_;
324 MockTransport mock_transport_;
325 PacketRouter packet_router_;
326 RtpStreamReceiverController rtp_stream_receiver_controller_;
327 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
328 Clock* clock_;
329 VCMTiming* timing_;
330};
331
332TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesNtpTime) {
333 const int64_t kNtpTimestamp = 12345;
334 auto test_frame = std::make_unique<FrameObjectFake>();
335 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100336 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200337 test_frame->SetNtpTime(kNtpTimestamp);
338
339 video_receive_stream_->Start();
340 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
341 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
342 EXPECT_EQ(kNtpTimestamp, fake_renderer_.ntp_time_ms());
343}
344
345TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) {
346 const webrtc::VideoRotation kRotation = webrtc::kVideoRotation_180;
347 auto test_frame = std::make_unique<FrameObjectFake>();
348 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100349 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200350 test_frame->SetRotation(kRotation);
351
352 video_receive_stream_->Start();
353 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
354 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
355
356 EXPECT_EQ(kRotation, fake_renderer_.rotation());
357}
358
359TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesPacketInfos) {
360 auto test_frame = std::make_unique<FrameObjectFake>();
361 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100362 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200363 RtpPacketInfos packet_infos = CreatePacketInfos(3);
364 test_frame->SetPacketInfos(packet_infos);
365
366 video_receive_stream_->Start();
367 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
368 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
369
370 EXPECT_THAT(fake_renderer_.packet_infos(), ElementsAreArray(packet_infos));
371}
372
373TEST_F(VideoReceiveStream2TestWithFakeDecoder, RenderedFrameUpdatesGetSources) {
374 constexpr uint32_t kSsrc = 1111;
375 constexpr uint32_t kCsrc = 9001;
376 constexpr uint32_t kRtpTimestamp = 12345;
377
378 // Prepare one video frame with per-packet information.
379 auto test_frame = std::make_unique<FrameObjectFake>();
380 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100381 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200382 RtpPacketInfos packet_infos;
383 {
384 RtpPacketInfos::vector_type infos;
385
386 RtpPacketInfo info;
387 info.set_ssrc(kSsrc);
388 info.set_csrcs({kCsrc});
389 info.set_rtp_timestamp(kRtpTimestamp);
390
Johannes Kronf7de74c2021-04-30 13:10:56 +0200391 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(5000));
Tommiae4d0972020-05-18 08:45:38 +0200392 infos.push_back(info);
393
Johannes Kronf7de74c2021-04-30 13:10:56 +0200394 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(3000));
Tommiae4d0972020-05-18 08:45:38 +0200395 infos.push_back(info);
396
Johannes Kronf7de74c2021-04-30 13:10:56 +0200397 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(2000));
Tommiae4d0972020-05-18 08:45:38 +0200398 infos.push_back(info);
399
Johannes Kronf7de74c2021-04-30 13:10:56 +0200400 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(1000));
Tommiae4d0972020-05-18 08:45:38 +0200401 infos.push_back(info);
402
403 packet_infos = RtpPacketInfos(std::move(infos));
404 }
405 test_frame->SetPacketInfos(packet_infos);
406
407 // Start receive stream.
408 video_receive_stream_->Start();
409 EXPECT_THAT(video_receive_stream_->GetSources(), IsEmpty());
410
411 // Render one video frame.
412 int64_t timestamp_ms_min = clock_->TimeInMilliseconds();
413 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
414 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
415 int64_t timestamp_ms_max = clock_->TimeInMilliseconds();
416
417 // Verify that the per-packet information is passed to the renderer.
418 EXPECT_THAT(fake_renderer_.packet_infos(), ElementsAreArray(packet_infos));
419
420 // Verify that the per-packet information also updates |GetSources()|.
421 std::vector<RtpSource> sources = video_receive_stream_->GetSources();
422 ASSERT_THAT(sources, SizeIs(2));
423 {
424 auto it = std::find_if(sources.begin(), sources.end(),
425 [](const RtpSource& source) {
426 return source.source_type() == RtpSourceType::SSRC;
427 });
428 ASSERT_NE(it, sources.end());
429
430 EXPECT_EQ(it->source_id(), kSsrc);
431 EXPECT_EQ(it->source_type(), RtpSourceType::SSRC);
432 EXPECT_EQ(it->rtp_timestamp(), kRtpTimestamp);
433 EXPECT_GE(it->timestamp_ms(), timestamp_ms_min);
434 EXPECT_LE(it->timestamp_ms(), timestamp_ms_max);
435 }
436 {
437 auto it = std::find_if(sources.begin(), sources.end(),
438 [](const RtpSource& source) {
439 return source.source_type() == RtpSourceType::CSRC;
440 });
441 ASSERT_NE(it, sources.end());
442
443 EXPECT_EQ(it->source_id(), kCsrc);
444 EXPECT_EQ(it->source_type(), RtpSourceType::CSRC);
445 EXPECT_EQ(it->rtp_timestamp(), kRtpTimestamp);
446 EXPECT_GE(it->timestamp_ms(), timestamp_ms_min);
447 EXPECT_LE(it->timestamp_ms(), timestamp_ms_max);
448 }
449}
450
Markus Handell588f9b32021-04-08 19:19:50 +0200451std::unique_ptr<FrameObjectFake> MakeFrameWithResolution(
452 VideoFrameType frame_type,
453 int picture_id,
454 int width,
455 int height) {
Tommiae4d0972020-05-18 08:45:38 +0200456 auto frame = std::make_unique<FrameObjectFake>();
457 frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100458 frame->SetId(picture_id);
Tommiae4d0972020-05-18 08:45:38 +0200459 frame->SetFrameType(frame_type);
Markus Handell588f9b32021-04-08 19:19:50 +0200460 frame->_encodedWidth = width;
461 frame->_encodedHeight = height;
Tommiae4d0972020-05-18 08:45:38 +0200462 return frame;
463}
464
Markus Handell588f9b32021-04-08 19:19:50 +0200465std::unique_ptr<FrameObjectFake> MakeFrame(VideoFrameType frame_type,
466 int picture_id) {
467 return MakeFrameWithResolution(frame_type, picture_id, 320, 240);
468}
469
Tommiae4d0972020-05-18 08:45:38 +0200470TEST_F(VideoReceiveStream2TestWithFakeDecoder,
471 PassesFrameWhenEncodedFramesCallbackSet) {
472 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
473 video_receive_stream_->Start();
474 // Expect a keyframe request to be generated
475 EXPECT_CALL(mock_transport_, SendRtcp);
476 EXPECT_CALL(callback, Call);
477 video_receive_stream_->SetAndGetRecordingState(
478 VideoReceiveStream::RecordingState(callback.AsStdFunction()), true);
479 video_receive_stream_->OnCompleteFrame(
480 MakeFrame(VideoFrameType::kVideoFrameKey, 0));
481 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
482 video_receive_stream_->Stop();
483}
484
485TEST_F(VideoReceiveStream2TestWithFakeDecoder,
486 MovesEncodedFrameDispatchStateWhenReCreating) {
487 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
488 video_receive_stream_->Start();
489 // Expect a key frame request over RTCP.
490 EXPECT_CALL(mock_transport_, SendRtcp).Times(1);
491 video_receive_stream_->SetAndGetRecordingState(
492 VideoReceiveStream::RecordingState(callback.AsStdFunction()), true);
493 video_receive_stream_->Stop();
494 VideoReceiveStream::RecordingState old_state =
495 video_receive_stream_->SetAndGetRecordingState(
496 VideoReceiveStream::RecordingState(), false);
497 ReCreateReceiveStream(std::move(old_state));
498 video_receive_stream_->Stop();
499}
500
Philipp Hancke006206d2021-03-24 17:49:02 +0100501class VideoReceiveStream2TestWithSimulatedClock
502 : public ::testing::TestWithParam<int> {
Tommiae4d0972020-05-18 08:45:38 +0200503 public:
Markus Handell588f9b32021-04-08 19:19:50 +0200504 class FakeRenderer : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
505 public:
506 void SignalDoneAfterFrames(int num_frames_received) {
507 signal_after_frame_count_ = num_frames_received;
508 if (frame_count_ == signal_after_frame_count_)
509 event_.Set();
510 }
511
512 void OnFrame(const webrtc::VideoFrame& frame) override {
513 if (++frame_count_ == signal_after_frame_count_)
514 event_.Set();
515 }
516
517 void WaitUntilDone() { event_.Wait(rtc::Event::kForever); }
518
519 private:
520 int signal_after_frame_count_ = std::numeric_limits<int>::max();
521 int frame_count_ = 0;
522 rtc::Event event_;
523 };
524
Tommiae4d0972020-05-18 08:45:38 +0200525 class FakeDecoder2 : public test::FakeDecoder {
526 public:
527 explicit FakeDecoder2(std::function<void()> decode_callback)
528 : callback_(decode_callback) {}
529
530 int32_t Decode(const EncodedImage& input,
531 bool missing_frames,
532 int64_t render_time_ms) override {
533 int32_t result =
534 FakeDecoder::Decode(input, missing_frames, render_time_ms);
535 callback_();
536 return result;
537 }
538
539 private:
540 std::function<void()> callback_;
541 };
542
543 static VideoReceiveStream::Config GetConfig(
544 Transport* transport,
545 VideoDecoderFactory* decoder_factory,
546 rtc::VideoSinkInterface<webrtc::VideoFrame>* renderer) {
547 VideoReceiveStream::Config config(transport);
548 config.rtp.remote_ssrc = 1111;
549 config.rtp.local_ssrc = 2222;
Philipp Hancke006206d2021-03-24 17:49:02 +0100550 config.rtp.nack.rtp_history_ms = GetParam(); // rtx-time.
Tommiae4d0972020-05-18 08:45:38 +0200551 config.renderer = renderer;
Philip Eliasson2b068ce2020-08-03 15:55:10 +0000552 config.decoder_factory = decoder_factory;
Tommiae4d0972020-05-18 08:45:38 +0200553 VideoReceiveStream::Decoder fake_decoder;
554 fake_decoder.payload_type = 99;
555 fake_decoder.video_format = SdpVideoFormat("VP8");
Tommiae4d0972020-05-18 08:45:38 +0200556 config.decoders.push_back(fake_decoder);
557 return config;
558 }
559
560 VideoReceiveStream2TestWithSimulatedClock()
561 : time_controller_(Timestamp::Millis(4711)),
562 fake_decoder_factory_([this] {
563 return std::make_unique<FakeDecoder2>([this] { OnFrameDecoded(); });
564 }),
565 process_thread_(time_controller_.CreateProcessThread("ProcessThread")),
566 config_(GetConfig(&mock_transport_,
567 &fake_decoder_factory_,
568 &fake_renderer_)),
569 call_stats_(time_controller_.GetClock(), loop_.task_queue()),
570 video_receive_stream_(time_controller_.GetTaskQueueFactory(),
571 loop_.task_queue(),
572 &rtp_stream_receiver_controller_,
573 /*num_cores=*/2,
574 &packet_router_,
575 config_.Copy(),
576 process_thread_.get(),
577 &call_stats_,
578 time_controller_.GetClock(),
579 new VCMTiming(time_controller_.GetClock())) {
580 video_receive_stream_.Start();
581 }
582
583 void OnFrameDecoded() { event_->Set(); }
584
philipelca188092021-03-23 12:00:49 +0100585 void PassEncodedFrameAndWait(std::unique_ptr<EncodedFrame> frame) {
Tommiae4d0972020-05-18 08:45:38 +0200586 event_ = std::make_unique<rtc::Event>();
587 // This call will eventually end up in the Decoded method where the
588 // event is set.
589 video_receive_stream_.OnCompleteFrame(std::move(frame));
590 event_->Wait(rtc::Event::kForever);
591 }
592
593 protected:
594 GlobalSimulatedTimeController time_controller_;
595 test::RunLoop loop_;
596 test::FunctionVideoDecoderFactory fake_decoder_factory_;
597 std::unique_ptr<ProcessThread> process_thread_;
598 MockTransport mock_transport_;
Markus Handell588f9b32021-04-08 19:19:50 +0200599 FakeRenderer fake_renderer_;
Tommiae4d0972020-05-18 08:45:38 +0200600 VideoReceiveStream::Config config_;
601 internal::CallStats call_stats_;
602 PacketRouter packet_router_;
603 RtpStreamReceiverController rtp_stream_receiver_controller_;
604 webrtc::internal::VideoReceiveStream2 video_receive_stream_;
605 std::unique_ptr<rtc::Event> event_;
606};
607
Philipp Hancke006206d2021-03-24 17:49:02 +0100608TEST_P(VideoReceiveStream2TestWithSimulatedClock,
Tommiae4d0972020-05-18 08:45:38 +0200609 RequestsKeyFramesUntilKeyFrameReceived) {
Philipp Hancke006206d2021-03-24 17:49:02 +0100610 auto tick = TimeDelta::Millis(GetParam() / 2);
Tommiae4d0972020-05-18 08:45:38 +0200611 EXPECT_CALL(mock_transport_, SendRtcp).Times(1).WillOnce(Invoke([this]() {
612 loop_.Quit();
613 return 0;
614 }));
615 video_receive_stream_.GenerateKeyFrame();
616 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 0));
617 time_controller_.AdvanceTime(tick);
618 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 1));
619 loop_.Run();
620 testing::Mock::VerifyAndClearExpectations(&mock_transport_);
621
Philipp Hancke006206d2021-03-24 17:49:02 +0100622 // T+keyframetimeout: still no key frame received, expect key frame request
623 // sent again.
Tommiae4d0972020-05-18 08:45:38 +0200624 EXPECT_CALL(mock_transport_, SendRtcp).Times(1).WillOnce(Invoke([this]() {
625 loop_.Quit();
626 return 0;
627 }));
628 time_controller_.AdvanceTime(tick);
629 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 2));
630 loop_.Run();
631 testing::Mock::VerifyAndClearExpectations(&mock_transport_);
632
Philipp Hancke006206d2021-03-24 17:49:02 +0100633 // T+keyframetimeout: now send a key frame - we should not observe new key
634 // frame requests after this.
Tommiae4d0972020-05-18 08:45:38 +0200635 EXPECT_CALL(mock_transport_, SendRtcp).Times(0);
636 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameKey, 3));
637 time_controller_.AdvanceTime(2 * tick);
638 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 4));
639 loop_.PostTask([this]() { loop_.Quit(); });
640 loop_.Run();
641}
642
Markus Handell588f9b32021-04-08 19:19:50 +0200643TEST_P(VideoReceiveStream2TestWithSimulatedClock,
644 DispatchesEncodedFrameSequenceStartingWithKeyframeWithoutResolution) {
645 video_receive_stream_.Start();
646 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
647 video_receive_stream_.SetAndGetRecordingState(
648 VideoReceiveStream::RecordingState(callback.AsStdFunction()),
649 /*generate_key_frame=*/false);
650
651 InSequence s;
652 EXPECT_CALL(
653 callback,
654 Call(AllOf(
655 Property(&RecordableEncodedFrame::resolution,
656 Field(&RecordableEncodedFrame::EncodedResolution::width,
657 test::FakeDecoder::kDefaultWidth)),
658 Property(&RecordableEncodedFrame::resolution,
659 Field(&RecordableEncodedFrame::EncodedResolution::height,
660 test::FakeDecoder::kDefaultHeight)))));
661 EXPECT_CALL(callback, Call);
662
663 fake_renderer_.SignalDoneAfterFrames(2);
664 PassEncodedFrameAndWait(
665 MakeFrameWithResolution(VideoFrameType::kVideoFrameKey, 0, 0, 0));
666 PassEncodedFrameAndWait(
667 MakeFrameWithResolution(VideoFrameType::kVideoFrameDelta, 1, 0, 0));
668 fake_renderer_.WaitUntilDone();
669
670 video_receive_stream_.Stop();
671}
672
673TEST_P(VideoReceiveStream2TestWithSimulatedClock,
674 DispatchesEncodedFrameSequenceStartingWithKeyframeWithResolution) {
675 video_receive_stream_.Start();
676 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
677 video_receive_stream_.SetAndGetRecordingState(
678 VideoReceiveStream::RecordingState(callback.AsStdFunction()),
679 /*generate_key_frame=*/false);
680
681 InSequence s;
682 EXPECT_CALL(
683 callback,
684 Call(AllOf(
685 Property(
686 &RecordableEncodedFrame::resolution,
687 Field(&RecordableEncodedFrame::EncodedResolution::width, 1080)),
688 Property(&RecordableEncodedFrame::resolution,
689 Field(&RecordableEncodedFrame::EncodedResolution::height,
690 720)))));
691 EXPECT_CALL(callback, Call);
692
693 fake_renderer_.SignalDoneAfterFrames(2);
694 PassEncodedFrameAndWait(
695 MakeFrameWithResolution(VideoFrameType::kVideoFrameKey, 0, 1080, 720));
696 PassEncodedFrameAndWait(
697 MakeFrameWithResolution(VideoFrameType::kVideoFrameDelta, 1, 0, 0));
698 fake_renderer_.WaitUntilDone();
699
700 video_receive_stream_.Stop();
701}
702
Philipp Hancke006206d2021-03-24 17:49:02 +0100703INSTANTIATE_TEST_SUITE_P(
704 RtxTime,
705 VideoReceiveStream2TestWithSimulatedClock,
706 ::testing::Values(internal::VideoReceiveStream2::kMaxWaitForKeyFrameMs,
707 50 /*ms*/));
708
Johannes Kron16359f62021-02-18 23:37:22 +0100709class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test {
710 public:
711 VideoReceiveStream2TestWithLazyDecoderCreation()
712 : process_thread_(ProcessThread::Create("TestThread")),
713 task_queue_factory_(CreateDefaultTaskQueueFactory()),
714 config_(&mock_transport_),
715 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {}
716
717 void SetUp() {
718 webrtc::test::ScopedFieldTrials field_trials(
719 "WebRTC-PreStreamDecoders/max:0/");
720 constexpr int kDefaultNumCpuCores = 2;
721 config_.rtp.remote_ssrc = 1111;
722 config_.rtp.local_ssrc = 2222;
723 config_.renderer = &fake_renderer_;
724 config_.decoder_factory = &mock_h264_decoder_factory_;
725 VideoReceiveStream::Decoder h264_decoder;
726 h264_decoder.payload_type = 99;
727 h264_decoder.video_format = SdpVideoFormat("H264");
728 h264_decoder.video_format.parameters.insert(
729 {"sprop-parameter-sets", "Z0IACpZTBYmI,aMljiA=="});
730 config_.decoders.clear();
731 config_.decoders.push_back(h264_decoder);
732
733 clock_ = Clock::GetRealTimeClock();
734 timing_ = new VCMTiming(clock_);
735
736 video_receive_stream_ =
737 std::make_unique<webrtc::internal::VideoReceiveStream2>(
738 task_queue_factory_.get(), loop_.task_queue(),
739 &rtp_stream_receiver_controller_, kDefaultNumCpuCores,
740 &packet_router_, config_.Copy(), process_thread_.get(),
741 &call_stats_, clock_, timing_);
742 }
743
744 protected:
745 test::RunLoop loop_;
746 std::unique_ptr<ProcessThread> process_thread_;
747 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
748 VideoReceiveStream::Config config_;
749 internal::CallStats call_stats_;
750 MockVideoDecoder mock_h264_video_decoder_;
751 MockVideoDecoderFactory mock_h264_decoder_factory_;
752 cricket::FakeVideoRenderer fake_renderer_;
753 MockTransport mock_transport_;
754 PacketRouter packet_router_;
755 RtpStreamReceiverController rtp_stream_receiver_controller_;
756 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
757 Clock* clock_;
758 VCMTiming* timing_;
759};
760
761TEST_F(VideoReceiveStream2TestWithLazyDecoderCreation, LazyDecoderCreation) {
762 constexpr uint8_t idr_nalu[] = {0x05, 0xFF, 0xFF, 0xFF};
763 RtpPacketToSend rtppacket(nullptr);
764 uint8_t* payload = rtppacket.AllocatePayload(sizeof(idr_nalu));
765 memcpy(payload, idr_nalu, sizeof(idr_nalu));
766 rtppacket.SetMarker(true);
767 rtppacket.SetSsrc(1111);
768 rtppacket.SetPayloadType(99);
769 rtppacket.SetSequenceNumber(1);
770 rtppacket.SetTimestamp(0);
771
772 // No decoder is created here.
773 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_)).Times(0);
774 video_receive_stream_->Start();
775
776 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_))
777 .WillOnce(Invoke([this](const SdpVideoFormat& format) {
778 test::VideoDecoderProxyFactory h264_decoder_factory(
779 &mock_h264_video_decoder_);
780 return h264_decoder_factory.CreateVideoDecoder(format);
781 }));
782 rtc::Event init_decode_event_;
783 EXPECT_CALL(mock_h264_video_decoder_, InitDecode(_, _))
784 .WillOnce(Invoke([&init_decode_event_](const VideoCodec* config,
785 int32_t number_of_cores) {
786 init_decode_event_.Set();
787 return 0;
788 }));
789 EXPECT_CALL(mock_h264_video_decoder_, RegisterDecodeCompleteCallback(_));
790 EXPECT_CALL(mock_h264_video_decoder_, Decode(_, false, _));
791 RtpPacketReceived parsed_packet;
792 ASSERT_TRUE(parsed_packet.Parse(rtppacket.data(), rtppacket.size()));
793 rtp_stream_receiver_controller_.OnRtpPacket(parsed_packet);
794 EXPECT_CALL(mock_h264_video_decoder_, Release());
795
796 // Make sure the decoder thread had a chance to run.
797 init_decode_event_.Wait(kDefaultTimeOutMs);
798}
799
800TEST_F(VideoReceiveStream2TestWithLazyDecoderCreation,
801 DeregisterDecoderThatsNotCreated) {
802 // No decoder is created here.
803 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_)).Times(0);
804 video_receive_stream_->Start();
805 video_receive_stream_->Stop();
806}
807
Tommiae4d0972020-05-18 08:45:38 +0200808} // namespace webrtc