blob: 8004bc375be234835f4c88c801a01a08fc919af0 [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"
Danil Chapovalov9cd4d492021-08-03 14:59:00 +020020#include "api/test/mock_video_decoder.h"
21#include "api/test/mock_video_decoder_factory.h"
Tommiae4d0972020-05-18 08:45:38 +020022#include "api/test/video/function_video_decoder_factory.h"
Markus Handell588f9b32021-04-08 19:19:50 +020023#include "api/video/video_frame.h"
Tommiae4d0972020-05-18 08:45:38 +020024#include "api/video_codecs/video_decoder.h"
25#include "call/rtp_stream_receiver_controller.h"
26#include "common_video/test/utilities.h"
27#include "media/base/fake_video_renderer.h"
Tommi90738dd2021-05-31 17:36:47 +020028#include "media/engine/fake_webrtc_call.h"
Tommiae4d0972020-05-18 08:45:38 +020029#include "modules/pacing/packet_router.h"
30#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
31#include "modules/utility/include/process_thread.h"
32#include "modules/video_coding/encoded_frame.h"
Tommiae4d0972020-05-18 08:45:38 +020033#include "rtc_base/event.h"
34#include "system_wrappers/include/clock.h"
35#include "test/fake_decoder.h"
36#include "test/field_trial.h"
37#include "test/gmock.h"
38#include "test/gtest.h"
Danil Chapovalov9cd4d492021-08-03 14:59:00 +020039#include "test/mock_transport.h"
Tommiae4d0972020-05-18 08:45:38 +020040#include "test/run_loop.h"
41#include "test/time_controller/simulated_time_controller.h"
42#include "test/video_decoder_proxy_factory.h"
43#include "video/call_stats2.h"
44
45namespace webrtc {
46namespace {
47
48using ::testing::_;
Markus Handell588f9b32021-04-08 19:19:50 +020049using ::testing::AllOf;
Tommiae4d0972020-05-18 08:45:38 +020050using ::testing::ElementsAreArray;
Markus Handell588f9b32021-04-08 19:19:50 +020051using ::testing::Field;
52using ::testing::InSequence;
Tommiae4d0972020-05-18 08:45:38 +020053using ::testing::Invoke;
54using ::testing::IsEmpty;
Markus Handell588f9b32021-04-08 19:19:50 +020055using ::testing::Property;
Tommiae4d0972020-05-18 08:45:38 +020056using ::testing::SizeIs;
Danil Chapovalovd08930d2021-08-12 13:26:55 +020057using ::testing::WithoutArgs;
Tommiae4d0972020-05-18 08:45:38 +020058
59constexpr int kDefaultTimeOutMs = 50;
60
philipelca188092021-03-23 12:00:49 +010061class FrameObjectFake : public EncodedFrame {
Tommiae4d0972020-05-18 08:45:38 +020062 public:
63 void SetPayloadType(uint8_t payload_type) { _payloadType = payload_type; }
64
65 void SetRotation(const VideoRotation& rotation) { rotation_ = rotation; }
66
67 void SetNtpTime(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; }
68
69 int64_t ReceivedTime() const override { return 0; }
70
71 int64_t RenderTime() const override { return _renderTimeMs; }
72};
73
74} // namespace
75
76class VideoReceiveStream2Test : public ::testing::Test {
77 public:
78 VideoReceiveStream2Test()
Markus Handelleb61b7f2021-06-22 10:46:48 +020079 : task_queue_factory_(CreateDefaultTaskQueueFactory()),
Tommi9e2b3152021-06-21 22:15:39 +020080 h264_decoder_factory_(&mock_h264_video_decoder_),
81 config_(&mock_transport_, &h264_decoder_factory_),
82 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {}
Tommi90738dd2021-05-31 17:36:47 +020083 ~VideoReceiveStream2Test() override {
84 if (video_receive_stream_)
85 video_receive_stream_->UnregisterFromTransport();
86 }
Tommiae4d0972020-05-18 08:45:38 +020087
Tommi90738dd2021-05-31 17:36:47 +020088 void SetUp() override {
Tommiae4d0972020-05-18 08:45:38 +020089 constexpr int kDefaultNumCpuCores = 2;
90 config_.rtp.remote_ssrc = 1111;
91 config_.rtp.local_ssrc = 2222;
92 config_.renderer = &fake_renderer_;
93 VideoReceiveStream::Decoder h264_decoder;
94 h264_decoder.payload_type = 99;
95 h264_decoder.video_format = SdpVideoFormat("H264");
96 h264_decoder.video_format.parameters.insert(
97 {"sprop-parameter-sets", "Z0IACpZTBYmI,aMljiA=="});
Johannes Kron16359f62021-02-18 23:37:22 +010098 config_.decoders.clear();
Tommiae4d0972020-05-18 08:45:38 +020099 config_.decoders.push_back(h264_decoder);
Tommiae4d0972020-05-18 08:45:38 +0200100
101 clock_ = Clock::GetRealTimeClock();
102 timing_ = new VCMTiming(clock_);
103
104 video_receive_stream_ =
105 std::make_unique<webrtc::internal::VideoReceiveStream2>(
Tommi90738dd2021-05-31 17:36:47 +0200106 task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores,
Markus Handell0e62f7a2021-07-20 13:32:02 +0200107 &packet_router_, config_.Copy(), &call_stats_, clock_, timing_,
108 &nack_periodic_processor_);
Tommi90738dd2021-05-31 17:36:47 +0200109 video_receive_stream_->RegisterWithTransport(
110 &rtp_stream_receiver_controller_);
Tommiae4d0972020-05-18 08:45:38 +0200111 }
112
113 protected:
114 test::RunLoop loop_;
Tommiae4d0972020-05-18 08:45:38 +0200115 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
Tommi9e2b3152021-06-21 22:15:39 +0200116 test::VideoDecoderProxyFactory h264_decoder_factory_;
Markus Handell0e62f7a2021-07-20 13:32:02 +0200117 NackPeriodicProcessor nack_periodic_processor_;
Tommiae4d0972020-05-18 08:45:38 +0200118 VideoReceiveStream::Config config_;
119 internal::CallStats call_stats_;
120 MockVideoDecoder mock_h264_video_decoder_;
Tommiae4d0972020-05-18 08:45:38 +0200121 cricket::FakeVideoRenderer fake_renderer_;
Tommi90738dd2021-05-31 17:36:47 +0200122 cricket::FakeCall fake_call_;
Tommiae4d0972020-05-18 08:45:38 +0200123 MockTransport mock_transport_;
124 PacketRouter packet_router_;
125 RtpStreamReceiverController rtp_stream_receiver_controller_;
126 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
127 Clock* clock_;
128 VCMTiming* timing_;
129};
130
131TEST_F(VideoReceiveStream2Test, CreateFrameFromH264FmtpSpropAndIdr) {
132 constexpr uint8_t idr_nalu[] = {0x05, 0xFF, 0xFF, 0xFF};
133 RtpPacketToSend rtppacket(nullptr);
134 uint8_t* payload = rtppacket.AllocatePayload(sizeof(idr_nalu));
135 memcpy(payload, idr_nalu, sizeof(idr_nalu));
136 rtppacket.SetMarker(true);
137 rtppacket.SetSsrc(1111);
138 rtppacket.SetPayloadType(99);
139 rtppacket.SetSequenceNumber(1);
140 rtppacket.SetTimestamp(0);
Danil Chapovalovd08930d2021-08-12 13:26:55 +0200141 rtc::Event init_decode_event;
142 EXPECT_CALL(mock_h264_video_decoder_, Configure).WillOnce(WithoutArgs([&] {
143 init_decode_event.Set();
144 return true;
145 }));
Tommiae4d0972020-05-18 08:45:38 +0200146 EXPECT_CALL(mock_h264_video_decoder_, RegisterDecodeCompleteCallback(_));
147 video_receive_stream_->Start();
148 EXPECT_CALL(mock_h264_video_decoder_, Decode(_, false, _));
149 RtpPacketReceived parsed_packet;
150 ASSERT_TRUE(parsed_packet.Parse(rtppacket.data(), rtppacket.size()));
151 rtp_stream_receiver_controller_.OnRtpPacket(parsed_packet);
152 EXPECT_CALL(mock_h264_video_decoder_, Release());
153 // Make sure the decoder thread had a chance to run.
Danil Chapovalovd08930d2021-08-12 13:26:55 +0200154 init_decode_event.Wait(kDefaultTimeOutMs);
Tommiae4d0972020-05-18 08:45:38 +0200155}
156
157TEST_F(VideoReceiveStream2Test, PlayoutDelay) {
Niels Möllerd381eed2020-09-02 15:34:40 +0200158 const VideoPlayoutDelay kPlayoutDelayMs = {123, 321};
Tommiae4d0972020-05-18 08:45:38 +0200159 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100160 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200161 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
162
163 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
164 EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
165 EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
166
167 // Check that the biggest minimum delay is chosen.
168 video_receive_stream_->SetMinimumPlayoutDelay(400);
169 EXPECT_EQ(400, timing_->min_playout_delay());
170
171 // Check base minimum delay validation.
172 EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(12345));
173 EXPECT_FALSE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(-1));
174 EXPECT_TRUE(video_receive_stream_->SetBaseMinimumPlayoutDelayMs(500));
175 EXPECT_EQ(500, timing_->min_playout_delay());
176
177 // Check that intermidiate values are remembered and the biggest remembered
178 // is chosen.
179 video_receive_stream_->SetBaseMinimumPlayoutDelayMs(0);
180 EXPECT_EQ(400, timing_->min_playout_delay());
181
182 video_receive_stream_->SetMinimumPlayoutDelay(0);
183 EXPECT_EQ(123, timing_->min_playout_delay());
184}
185
186TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMaxValue) {
187 const int default_max_playout_latency = timing_->max_playout_delay();
Niels Möllerd381eed2020-09-02 15:34:40 +0200188 const VideoPlayoutDelay kPlayoutDelayMs = {123, -1};
Tommiae4d0972020-05-18 08:45:38 +0200189
190 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100191 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200192 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
193
194 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
195
Artem Titovab30d722021-07-27 16:22:11 +0200196 // Ensure that -1 preserves default maximum value from `timing_`.
Tommiae4d0972020-05-18 08:45:38 +0200197 EXPECT_EQ(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
198 EXPECT_NE(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
199 EXPECT_EQ(default_max_playout_latency, timing_->max_playout_delay());
200}
201
202TEST_F(VideoReceiveStream2Test, PlayoutDelayPreservesDefaultMinValue) {
203 const int default_min_playout_latency = timing_->min_playout_delay();
Niels Möllerd381eed2020-09-02 15:34:40 +0200204 const VideoPlayoutDelay kPlayoutDelayMs = {-1, 321};
Tommiae4d0972020-05-18 08:45:38 +0200205
206 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100207 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200208 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
209
210 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
211
Artem Titovab30d722021-07-27 16:22:11 +0200212 // Ensure that -1 preserves default minimum value from `timing_`.
Tommiae4d0972020-05-18 08:45:38 +0200213 EXPECT_NE(kPlayoutDelayMs.min_ms, timing_->min_playout_delay());
214 EXPECT_EQ(kPlayoutDelayMs.max_ms, timing_->max_playout_delay());
215 EXPECT_EQ(default_min_playout_latency, timing_->min_playout_delay());
216}
217
Johannes Kron111e9812020-10-26 13:54:40 +0100218TEST_F(VideoReceiveStream2Test, MaxCompositionDelayNotSetByDefault) {
219 // Default with no playout delay set.
220 std::unique_ptr<FrameObjectFake> test_frame0(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100221 test_frame0->SetId(0);
Johannes Kron111e9812020-10-26 13:54:40 +0100222 video_receive_stream_->OnCompleteFrame(std::move(test_frame0));
223 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
224
225 // Max composition delay not set for playout delay 0,0.
226 std::unique_ptr<FrameObjectFake> test_frame1(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100227 test_frame1->SetId(1);
Johannes Kron111e9812020-10-26 13:54:40 +0100228 test_frame1->SetPlayoutDelay({0, 0});
229 video_receive_stream_->OnCompleteFrame(std::move(test_frame1));
230 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
231
232 // Max composition delay not set for playout delay X,Y, where X,Y>0.
233 std::unique_ptr<FrameObjectFake> test_frame2(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100234 test_frame2->SetId(2);
Johannes Kron111e9812020-10-26 13:54:40 +0100235 test_frame2->SetPlayoutDelay({10, 30});
236 video_receive_stream_->OnCompleteFrame(std::move(test_frame2));
237 EXPECT_FALSE(timing_->MaxCompositionDelayInFrames());
238}
239
240TEST_F(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
241 // Max composition delay set if playout delay X,Y, where X=0,Y>0.
242 const VideoPlayoutDelay kPlayoutDelayMs = {0, 50};
243 const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
244 std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
philipel9aa9b8d2021-02-15 13:31:29 +0100245 test_frame->SetId(0);
Johannes Kron111e9812020-10-26 13:54:40 +0100246 test_frame->SetPlayoutDelay(kPlayoutDelayMs);
247 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
248 EXPECT_EQ(kExpectedMaxCompositionDelayInFrames,
249 timing_->MaxCompositionDelayInFrames());
250}
251
Tommiae4d0972020-05-18 08:45:38 +0200252class VideoReceiveStream2TestWithFakeDecoder : public ::testing::Test {
253 public:
254 VideoReceiveStream2TestWithFakeDecoder()
255 : fake_decoder_factory_(
256 []() { return std::make_unique<test::FakeDecoder>(); }),
Tommiae4d0972020-05-18 08:45:38 +0200257 task_queue_factory_(CreateDefaultTaskQueueFactory()),
Tommi9e2b3152021-06-21 22:15:39 +0200258 config_(&mock_transport_, &fake_decoder_factory_),
Tommiae4d0972020-05-18 08:45:38 +0200259 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {}
Tommi90738dd2021-05-31 17:36:47 +0200260 ~VideoReceiveStream2TestWithFakeDecoder() override {
261 if (video_receive_stream_)
262 video_receive_stream_->UnregisterFromTransport();
263 }
Tommiae4d0972020-05-18 08:45:38 +0200264
Tommi90738dd2021-05-31 17:36:47 +0200265 void SetUp() override {
Tommiae4d0972020-05-18 08:45:38 +0200266 config_.rtp.remote_ssrc = 1111;
267 config_.rtp.local_ssrc = 2222;
268 config_.renderer = &fake_renderer_;
269 VideoReceiveStream::Decoder fake_decoder;
270 fake_decoder.payload_type = 99;
271 fake_decoder.video_format = SdpVideoFormat("VP8");
Tommiae4d0972020-05-18 08:45:38 +0200272 config_.decoders.push_back(fake_decoder);
273 clock_ = Clock::GetRealTimeClock();
274 ReCreateReceiveStream(VideoReceiveStream::RecordingState());
275 }
276
277 void ReCreateReceiveStream(VideoReceiveStream::RecordingState state) {
278 constexpr int kDefaultNumCpuCores = 2;
Tommi90738dd2021-05-31 17:36:47 +0200279 if (video_receive_stream_) {
280 video_receive_stream_->UnregisterFromTransport();
281 video_receive_stream_ = nullptr;
282 }
Tommiae4d0972020-05-18 08:45:38 +0200283 timing_ = new VCMTiming(clock_);
284 video_receive_stream_.reset(new webrtc::internal::VideoReceiveStream2(
Tommi90738dd2021-05-31 17:36:47 +0200285 task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores,
Markus Handell0e62f7a2021-07-20 13:32:02 +0200286 &packet_router_, config_.Copy(), &call_stats_, clock_, timing_,
287 &nack_periodic_processor_));
Tommi90738dd2021-05-31 17:36:47 +0200288 video_receive_stream_->RegisterWithTransport(
289 &rtp_stream_receiver_controller_);
Tommiae4d0972020-05-18 08:45:38 +0200290 video_receive_stream_->SetAndGetRecordingState(std::move(state), false);
291 }
292
293 protected:
294 test::RunLoop loop_;
295 test::FunctionVideoDecoderFactory fake_decoder_factory_;
Tommiae4d0972020-05-18 08:45:38 +0200296 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
Markus Handell0e62f7a2021-07-20 13:32:02 +0200297 NackPeriodicProcessor nack_periodic_processor_;
Tommiae4d0972020-05-18 08:45:38 +0200298 VideoReceiveStream::Config config_;
299 internal::CallStats call_stats_;
300 cricket::FakeVideoRenderer fake_renderer_;
301 MockTransport mock_transport_;
302 PacketRouter packet_router_;
303 RtpStreamReceiverController rtp_stream_receiver_controller_;
Tommi90738dd2021-05-31 17:36:47 +0200304 cricket::FakeCall fake_call_;
Tommiae4d0972020-05-18 08:45:38 +0200305 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
306 Clock* clock_;
307 VCMTiming* timing_;
308};
309
310TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesNtpTime) {
311 const int64_t kNtpTimestamp = 12345;
312 auto test_frame = std::make_unique<FrameObjectFake>();
313 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100314 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200315 test_frame->SetNtpTime(kNtpTimestamp);
316
317 video_receive_stream_->Start();
318 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
319 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
320 EXPECT_EQ(kNtpTimestamp, fake_renderer_.ntp_time_ms());
321}
322
323TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesRotation) {
324 const webrtc::VideoRotation kRotation = webrtc::kVideoRotation_180;
325 auto test_frame = std::make_unique<FrameObjectFake>();
326 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100327 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200328 test_frame->SetRotation(kRotation);
329
330 video_receive_stream_->Start();
331 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
332 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
333
334 EXPECT_EQ(kRotation, fake_renderer_.rotation());
335}
336
337TEST_F(VideoReceiveStream2TestWithFakeDecoder, PassesPacketInfos) {
338 auto test_frame = std::make_unique<FrameObjectFake>();
339 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100340 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200341 RtpPacketInfos packet_infos = CreatePacketInfos(3);
342 test_frame->SetPacketInfos(packet_infos);
343
344 video_receive_stream_->Start();
345 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
346 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
347
348 EXPECT_THAT(fake_renderer_.packet_infos(), ElementsAreArray(packet_infos));
349}
350
351TEST_F(VideoReceiveStream2TestWithFakeDecoder, RenderedFrameUpdatesGetSources) {
352 constexpr uint32_t kSsrc = 1111;
353 constexpr uint32_t kCsrc = 9001;
354 constexpr uint32_t kRtpTimestamp = 12345;
355
356 // Prepare one video frame with per-packet information.
357 auto test_frame = std::make_unique<FrameObjectFake>();
358 test_frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100359 test_frame->SetId(0);
Tommiae4d0972020-05-18 08:45:38 +0200360 RtpPacketInfos packet_infos;
361 {
362 RtpPacketInfos::vector_type infos;
363
364 RtpPacketInfo info;
365 info.set_ssrc(kSsrc);
366 info.set_csrcs({kCsrc});
367 info.set_rtp_timestamp(kRtpTimestamp);
368
Johannes Kronf7de74c2021-04-30 13:10:56 +0200369 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(5000));
Tommiae4d0972020-05-18 08:45:38 +0200370 infos.push_back(info);
371
Johannes Kronf7de74c2021-04-30 13:10:56 +0200372 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(3000));
Tommiae4d0972020-05-18 08:45:38 +0200373 infos.push_back(info);
374
Johannes Kronf7de74c2021-04-30 13:10:56 +0200375 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(2000));
Tommiae4d0972020-05-18 08:45:38 +0200376 infos.push_back(info);
377
Johannes Kronf7de74c2021-04-30 13:10:56 +0200378 info.set_receive_time(clock_->CurrentTime() - TimeDelta::Millis(1000));
Tommiae4d0972020-05-18 08:45:38 +0200379 infos.push_back(info);
380
381 packet_infos = RtpPacketInfos(std::move(infos));
382 }
383 test_frame->SetPacketInfos(packet_infos);
384
385 // Start receive stream.
386 video_receive_stream_->Start();
387 EXPECT_THAT(video_receive_stream_->GetSources(), IsEmpty());
388
389 // Render one video frame.
390 int64_t timestamp_ms_min = clock_->TimeInMilliseconds();
391 video_receive_stream_->OnCompleteFrame(std::move(test_frame));
392 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
393 int64_t timestamp_ms_max = clock_->TimeInMilliseconds();
394
395 // Verify that the per-packet information is passed to the renderer.
396 EXPECT_THAT(fake_renderer_.packet_infos(), ElementsAreArray(packet_infos));
397
Artem Titovab30d722021-07-27 16:22:11 +0200398 // Verify that the per-packet information also updates `GetSources()`.
Tommiae4d0972020-05-18 08:45:38 +0200399 std::vector<RtpSource> sources = video_receive_stream_->GetSources();
400 ASSERT_THAT(sources, SizeIs(2));
401 {
402 auto it = std::find_if(sources.begin(), sources.end(),
403 [](const RtpSource& source) {
404 return source.source_type() == RtpSourceType::SSRC;
405 });
406 ASSERT_NE(it, sources.end());
407
408 EXPECT_EQ(it->source_id(), kSsrc);
409 EXPECT_EQ(it->source_type(), RtpSourceType::SSRC);
410 EXPECT_EQ(it->rtp_timestamp(), kRtpTimestamp);
411 EXPECT_GE(it->timestamp_ms(), timestamp_ms_min);
412 EXPECT_LE(it->timestamp_ms(), timestamp_ms_max);
413 }
414 {
415 auto it = std::find_if(sources.begin(), sources.end(),
416 [](const RtpSource& source) {
417 return source.source_type() == RtpSourceType::CSRC;
418 });
419 ASSERT_NE(it, sources.end());
420
421 EXPECT_EQ(it->source_id(), kCsrc);
422 EXPECT_EQ(it->source_type(), RtpSourceType::CSRC);
423 EXPECT_EQ(it->rtp_timestamp(), kRtpTimestamp);
424 EXPECT_GE(it->timestamp_ms(), timestamp_ms_min);
425 EXPECT_LE(it->timestamp_ms(), timestamp_ms_max);
426 }
427}
428
Markus Handell588f9b32021-04-08 19:19:50 +0200429std::unique_ptr<FrameObjectFake> MakeFrameWithResolution(
430 VideoFrameType frame_type,
431 int picture_id,
432 int width,
433 int height) {
Tommiae4d0972020-05-18 08:45:38 +0200434 auto frame = std::make_unique<FrameObjectFake>();
435 frame->SetPayloadType(99);
philipel9aa9b8d2021-02-15 13:31:29 +0100436 frame->SetId(picture_id);
Tommiae4d0972020-05-18 08:45:38 +0200437 frame->SetFrameType(frame_type);
Markus Handell588f9b32021-04-08 19:19:50 +0200438 frame->_encodedWidth = width;
439 frame->_encodedHeight = height;
Tommiae4d0972020-05-18 08:45:38 +0200440 return frame;
441}
442
Markus Handell588f9b32021-04-08 19:19:50 +0200443std::unique_ptr<FrameObjectFake> MakeFrame(VideoFrameType frame_type,
444 int picture_id) {
445 return MakeFrameWithResolution(frame_type, picture_id, 320, 240);
446}
447
Tommiae4d0972020-05-18 08:45:38 +0200448TEST_F(VideoReceiveStream2TestWithFakeDecoder,
449 PassesFrameWhenEncodedFramesCallbackSet) {
450 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
451 video_receive_stream_->Start();
452 // Expect a keyframe request to be generated
453 EXPECT_CALL(mock_transport_, SendRtcp);
454 EXPECT_CALL(callback, Call);
455 video_receive_stream_->SetAndGetRecordingState(
456 VideoReceiveStream::RecordingState(callback.AsStdFunction()), true);
457 video_receive_stream_->OnCompleteFrame(
458 MakeFrame(VideoFrameType::kVideoFrameKey, 0));
459 EXPECT_TRUE(fake_renderer_.WaitForRenderedFrame(kDefaultTimeOutMs));
460 video_receive_stream_->Stop();
461}
462
463TEST_F(VideoReceiveStream2TestWithFakeDecoder,
464 MovesEncodedFrameDispatchStateWhenReCreating) {
465 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
466 video_receive_stream_->Start();
467 // Expect a key frame request over RTCP.
468 EXPECT_CALL(mock_transport_, SendRtcp).Times(1);
469 video_receive_stream_->SetAndGetRecordingState(
470 VideoReceiveStream::RecordingState(callback.AsStdFunction()), true);
471 video_receive_stream_->Stop();
472 VideoReceiveStream::RecordingState old_state =
473 video_receive_stream_->SetAndGetRecordingState(
474 VideoReceiveStream::RecordingState(), false);
475 ReCreateReceiveStream(std::move(old_state));
476 video_receive_stream_->Stop();
477}
478
Philipp Hancke006206d2021-03-24 17:49:02 +0100479class VideoReceiveStream2TestWithSimulatedClock
480 : public ::testing::TestWithParam<int> {
Tommiae4d0972020-05-18 08:45:38 +0200481 public:
Markus Handell588f9b32021-04-08 19:19:50 +0200482 class FakeRenderer : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
483 public:
484 void SignalDoneAfterFrames(int num_frames_received) {
485 signal_after_frame_count_ = num_frames_received;
486 if (frame_count_ == signal_after_frame_count_)
487 event_.Set();
488 }
489
490 void OnFrame(const webrtc::VideoFrame& frame) override {
491 if (++frame_count_ == signal_after_frame_count_)
492 event_.Set();
493 }
494
495 void WaitUntilDone() { event_.Wait(rtc::Event::kForever); }
496
497 private:
498 int signal_after_frame_count_ = std::numeric_limits<int>::max();
499 int frame_count_ = 0;
500 rtc::Event event_;
501 };
502
Tommiae4d0972020-05-18 08:45:38 +0200503 class FakeDecoder2 : public test::FakeDecoder {
504 public:
505 explicit FakeDecoder2(std::function<void()> decode_callback)
506 : callback_(decode_callback) {}
507
508 int32_t Decode(const EncodedImage& input,
509 bool missing_frames,
510 int64_t render_time_ms) override {
511 int32_t result =
512 FakeDecoder::Decode(input, missing_frames, render_time_ms);
513 callback_();
514 return result;
515 }
516
517 private:
518 std::function<void()> callback_;
519 };
520
521 static VideoReceiveStream::Config GetConfig(
522 Transport* transport,
523 VideoDecoderFactory* decoder_factory,
524 rtc::VideoSinkInterface<webrtc::VideoFrame>* renderer) {
Tommi9e2b3152021-06-21 22:15:39 +0200525 VideoReceiveStream::Config config(transport, decoder_factory);
Tommiae4d0972020-05-18 08:45:38 +0200526 config.rtp.remote_ssrc = 1111;
527 config.rtp.local_ssrc = 2222;
Philipp Hancke006206d2021-03-24 17:49:02 +0100528 config.rtp.nack.rtp_history_ms = GetParam(); // rtx-time.
Tommiae4d0972020-05-18 08:45:38 +0200529 config.renderer = renderer;
530 VideoReceiveStream::Decoder fake_decoder;
531 fake_decoder.payload_type = 99;
532 fake_decoder.video_format = SdpVideoFormat("VP8");
Tommiae4d0972020-05-18 08:45:38 +0200533 config.decoders.push_back(fake_decoder);
534 return config;
535 }
536
537 VideoReceiveStream2TestWithSimulatedClock()
538 : time_controller_(Timestamp::Millis(4711)),
539 fake_decoder_factory_([this] {
540 return std::make_unique<FakeDecoder2>([this] { OnFrameDecoded(); });
541 }),
Tommiae4d0972020-05-18 08:45:38 +0200542 config_(GetConfig(&mock_transport_,
543 &fake_decoder_factory_,
544 &fake_renderer_)),
545 call_stats_(time_controller_.GetClock(), loop_.task_queue()),
546 video_receive_stream_(time_controller_.GetTaskQueueFactory(),
Tommi90738dd2021-05-31 17:36:47 +0200547 &fake_call_,
Tommiae4d0972020-05-18 08:45:38 +0200548 /*num_cores=*/2,
549 &packet_router_,
550 config_.Copy(),
Tommiae4d0972020-05-18 08:45:38 +0200551 &call_stats_,
552 time_controller_.GetClock(),
Markus Handell0e62f7a2021-07-20 13:32:02 +0200553 new VCMTiming(time_controller_.GetClock()),
554 &nack_periodic_processor_) {
Tommi90738dd2021-05-31 17:36:47 +0200555 video_receive_stream_.RegisterWithTransport(
556 &rtp_stream_receiver_controller_);
Tommiae4d0972020-05-18 08:45:38 +0200557 video_receive_stream_.Start();
558 }
559
Tommi90738dd2021-05-31 17:36:47 +0200560 ~VideoReceiveStream2TestWithSimulatedClock() override {
561 video_receive_stream_.UnregisterFromTransport();
562 }
563
Tommiae4d0972020-05-18 08:45:38 +0200564 void OnFrameDecoded() { event_->Set(); }
565
philipelca188092021-03-23 12:00:49 +0100566 void PassEncodedFrameAndWait(std::unique_ptr<EncodedFrame> frame) {
Tommiae4d0972020-05-18 08:45:38 +0200567 event_ = std::make_unique<rtc::Event>();
568 // This call will eventually end up in the Decoded method where the
569 // event is set.
570 video_receive_stream_.OnCompleteFrame(std::move(frame));
571 event_->Wait(rtc::Event::kForever);
572 }
573
574 protected:
575 GlobalSimulatedTimeController time_controller_;
576 test::RunLoop loop_;
577 test::FunctionVideoDecoderFactory fake_decoder_factory_;
Tommiae4d0972020-05-18 08:45:38 +0200578 MockTransport mock_transport_;
Markus Handell588f9b32021-04-08 19:19:50 +0200579 FakeRenderer fake_renderer_;
Tommi90738dd2021-05-31 17:36:47 +0200580 cricket::FakeCall fake_call_;
Markus Handell0e62f7a2021-07-20 13:32:02 +0200581 NackPeriodicProcessor nack_periodic_processor_;
Tommiae4d0972020-05-18 08:45:38 +0200582 VideoReceiveStream::Config config_;
583 internal::CallStats call_stats_;
584 PacketRouter packet_router_;
585 RtpStreamReceiverController rtp_stream_receiver_controller_;
586 webrtc::internal::VideoReceiveStream2 video_receive_stream_;
587 std::unique_ptr<rtc::Event> event_;
588};
589
Philipp Hancke006206d2021-03-24 17:49:02 +0100590TEST_P(VideoReceiveStream2TestWithSimulatedClock,
Tommiae4d0972020-05-18 08:45:38 +0200591 RequestsKeyFramesUntilKeyFrameReceived) {
Philipp Hancke006206d2021-03-24 17:49:02 +0100592 auto tick = TimeDelta::Millis(GetParam() / 2);
Tommiae4d0972020-05-18 08:45:38 +0200593 EXPECT_CALL(mock_transport_, SendRtcp).Times(1).WillOnce(Invoke([this]() {
594 loop_.Quit();
595 return 0;
596 }));
597 video_receive_stream_.GenerateKeyFrame();
598 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 0));
599 time_controller_.AdvanceTime(tick);
600 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 1));
601 loop_.Run();
602 testing::Mock::VerifyAndClearExpectations(&mock_transport_);
603
Philipp Hancke006206d2021-03-24 17:49:02 +0100604 // T+keyframetimeout: still no key frame received, expect key frame request
605 // sent again.
Tommiae4d0972020-05-18 08:45:38 +0200606 EXPECT_CALL(mock_transport_, SendRtcp).Times(1).WillOnce(Invoke([this]() {
607 loop_.Quit();
608 return 0;
609 }));
610 time_controller_.AdvanceTime(tick);
611 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 2));
612 loop_.Run();
613 testing::Mock::VerifyAndClearExpectations(&mock_transport_);
614
Philipp Hancke006206d2021-03-24 17:49:02 +0100615 // T+keyframetimeout: now send a key frame - we should not observe new key
616 // frame requests after this.
Tommiae4d0972020-05-18 08:45:38 +0200617 EXPECT_CALL(mock_transport_, SendRtcp).Times(0);
618 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameKey, 3));
619 time_controller_.AdvanceTime(2 * tick);
620 PassEncodedFrameAndWait(MakeFrame(VideoFrameType::kVideoFrameDelta, 4));
621 loop_.PostTask([this]() { loop_.Quit(); });
622 loop_.Run();
623}
624
Markus Handell588f9b32021-04-08 19:19:50 +0200625TEST_P(VideoReceiveStream2TestWithSimulatedClock,
626 DispatchesEncodedFrameSequenceStartingWithKeyframeWithoutResolution) {
627 video_receive_stream_.Start();
628 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
629 video_receive_stream_.SetAndGetRecordingState(
630 VideoReceiveStream::RecordingState(callback.AsStdFunction()),
631 /*generate_key_frame=*/false);
632
633 InSequence s;
634 EXPECT_CALL(
635 callback,
636 Call(AllOf(
637 Property(&RecordableEncodedFrame::resolution,
638 Field(&RecordableEncodedFrame::EncodedResolution::width,
639 test::FakeDecoder::kDefaultWidth)),
640 Property(&RecordableEncodedFrame::resolution,
641 Field(&RecordableEncodedFrame::EncodedResolution::height,
642 test::FakeDecoder::kDefaultHeight)))));
643 EXPECT_CALL(callback, Call);
644
645 fake_renderer_.SignalDoneAfterFrames(2);
646 PassEncodedFrameAndWait(
647 MakeFrameWithResolution(VideoFrameType::kVideoFrameKey, 0, 0, 0));
648 PassEncodedFrameAndWait(
649 MakeFrameWithResolution(VideoFrameType::kVideoFrameDelta, 1, 0, 0));
650 fake_renderer_.WaitUntilDone();
651
652 video_receive_stream_.Stop();
653}
654
655TEST_P(VideoReceiveStream2TestWithSimulatedClock,
656 DispatchesEncodedFrameSequenceStartingWithKeyframeWithResolution) {
657 video_receive_stream_.Start();
658 testing::MockFunction<void(const RecordableEncodedFrame&)> callback;
659 video_receive_stream_.SetAndGetRecordingState(
660 VideoReceiveStream::RecordingState(callback.AsStdFunction()),
661 /*generate_key_frame=*/false);
662
663 InSequence s;
664 EXPECT_CALL(
665 callback,
666 Call(AllOf(
667 Property(
668 &RecordableEncodedFrame::resolution,
669 Field(&RecordableEncodedFrame::EncodedResolution::width, 1080)),
670 Property(&RecordableEncodedFrame::resolution,
671 Field(&RecordableEncodedFrame::EncodedResolution::height,
672 720)))));
673 EXPECT_CALL(callback, Call);
674
675 fake_renderer_.SignalDoneAfterFrames(2);
676 PassEncodedFrameAndWait(
677 MakeFrameWithResolution(VideoFrameType::kVideoFrameKey, 0, 1080, 720));
678 PassEncodedFrameAndWait(
679 MakeFrameWithResolution(VideoFrameType::kVideoFrameDelta, 1, 0, 0));
680 fake_renderer_.WaitUntilDone();
681
682 video_receive_stream_.Stop();
683}
684
Philipp Hancke006206d2021-03-24 17:49:02 +0100685INSTANTIATE_TEST_SUITE_P(
686 RtxTime,
687 VideoReceiveStream2TestWithSimulatedClock,
688 ::testing::Values(internal::VideoReceiveStream2::kMaxWaitForKeyFrameMs,
689 50 /*ms*/));
690
Johannes Kron16359f62021-02-18 23:37:22 +0100691class VideoReceiveStream2TestWithLazyDecoderCreation : public ::testing::Test {
692 public:
693 VideoReceiveStream2TestWithLazyDecoderCreation()
Markus Handelleb61b7f2021-06-22 10:46:48 +0200694 : task_queue_factory_(CreateDefaultTaskQueueFactory()),
Tommi9e2b3152021-06-21 22:15:39 +0200695 config_(&mock_transport_, &mock_h264_decoder_factory_),
Johannes Kron16359f62021-02-18 23:37:22 +0100696 call_stats_(Clock::GetRealTimeClock(), loop_.task_queue()) {}
697
Tommi90738dd2021-05-31 17:36:47 +0200698 ~VideoReceiveStream2TestWithLazyDecoderCreation() override {
699 video_receive_stream_->UnregisterFromTransport();
700 }
701
702 void SetUp() override {
Johannes Kron16359f62021-02-18 23:37:22 +0100703 webrtc::test::ScopedFieldTrials field_trials(
704 "WebRTC-PreStreamDecoders/max:0/");
705 constexpr int kDefaultNumCpuCores = 2;
706 config_.rtp.remote_ssrc = 1111;
707 config_.rtp.local_ssrc = 2222;
708 config_.renderer = &fake_renderer_;
Johannes Kron16359f62021-02-18 23:37:22 +0100709 VideoReceiveStream::Decoder h264_decoder;
710 h264_decoder.payload_type = 99;
711 h264_decoder.video_format = SdpVideoFormat("H264");
712 h264_decoder.video_format.parameters.insert(
713 {"sprop-parameter-sets", "Z0IACpZTBYmI,aMljiA=="});
714 config_.decoders.clear();
715 config_.decoders.push_back(h264_decoder);
716
717 clock_ = Clock::GetRealTimeClock();
718 timing_ = new VCMTiming(clock_);
719
720 video_receive_stream_ =
721 std::make_unique<webrtc::internal::VideoReceiveStream2>(
Tommi90738dd2021-05-31 17:36:47 +0200722 task_queue_factory_.get(), &fake_call_, kDefaultNumCpuCores,
Markus Handell0e62f7a2021-07-20 13:32:02 +0200723 &packet_router_, config_.Copy(), &call_stats_, clock_, timing_,
724 &nack_periodic_processor_);
Tommi90738dd2021-05-31 17:36:47 +0200725 video_receive_stream_->RegisterWithTransport(
726 &rtp_stream_receiver_controller_);
Johannes Kron16359f62021-02-18 23:37:22 +0100727 }
728
729 protected:
730 test::RunLoop loop_;
Johannes Kron16359f62021-02-18 23:37:22 +0100731 const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
Tommi9e2b3152021-06-21 22:15:39 +0200732 MockVideoDecoderFactory mock_h264_decoder_factory_;
Markus Handell0e62f7a2021-07-20 13:32:02 +0200733 NackPeriodicProcessor nack_periodic_processor_;
Johannes Kron16359f62021-02-18 23:37:22 +0100734 VideoReceiveStream::Config config_;
735 internal::CallStats call_stats_;
736 MockVideoDecoder mock_h264_video_decoder_;
Johannes Kron16359f62021-02-18 23:37:22 +0100737 cricket::FakeVideoRenderer fake_renderer_;
Tommi90738dd2021-05-31 17:36:47 +0200738 cricket::FakeCall fake_call_;
Johannes Kron16359f62021-02-18 23:37:22 +0100739 MockTransport mock_transport_;
740 PacketRouter packet_router_;
741 RtpStreamReceiverController rtp_stream_receiver_controller_;
742 std::unique_ptr<webrtc::internal::VideoReceiveStream2> video_receive_stream_;
743 Clock* clock_;
744 VCMTiming* timing_;
745};
746
747TEST_F(VideoReceiveStream2TestWithLazyDecoderCreation, LazyDecoderCreation) {
748 constexpr uint8_t idr_nalu[] = {0x05, 0xFF, 0xFF, 0xFF};
749 RtpPacketToSend rtppacket(nullptr);
750 uint8_t* payload = rtppacket.AllocatePayload(sizeof(idr_nalu));
751 memcpy(payload, idr_nalu, sizeof(idr_nalu));
752 rtppacket.SetMarker(true);
753 rtppacket.SetSsrc(1111);
754 rtppacket.SetPayloadType(99);
755 rtppacket.SetSequenceNumber(1);
756 rtppacket.SetTimestamp(0);
757
758 // No decoder is created here.
759 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_)).Times(0);
760 video_receive_stream_->Start();
761
762 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_))
763 .WillOnce(Invoke([this](const SdpVideoFormat& format) {
764 test::VideoDecoderProxyFactory h264_decoder_factory(
765 &mock_h264_video_decoder_);
766 return h264_decoder_factory.CreateVideoDecoder(format);
767 }));
Danil Chapovalovd08930d2021-08-12 13:26:55 +0200768 rtc::Event init_decode_event;
769 EXPECT_CALL(mock_h264_video_decoder_, Configure).WillOnce(WithoutArgs([&] {
770 init_decode_event.Set();
771 return true;
772 }));
Johannes Kron16359f62021-02-18 23:37:22 +0100773 EXPECT_CALL(mock_h264_video_decoder_, RegisterDecodeCompleteCallback(_));
774 EXPECT_CALL(mock_h264_video_decoder_, Decode(_, false, _));
775 RtpPacketReceived parsed_packet;
776 ASSERT_TRUE(parsed_packet.Parse(rtppacket.data(), rtppacket.size()));
777 rtp_stream_receiver_controller_.OnRtpPacket(parsed_packet);
778 EXPECT_CALL(mock_h264_video_decoder_, Release());
779
780 // Make sure the decoder thread had a chance to run.
Danil Chapovalovd08930d2021-08-12 13:26:55 +0200781 init_decode_event.Wait(kDefaultTimeOutMs);
Johannes Kron16359f62021-02-18 23:37:22 +0100782}
783
784TEST_F(VideoReceiveStream2TestWithLazyDecoderCreation,
785 DeregisterDecoderThatsNotCreated) {
786 // No decoder is created here.
787 EXPECT_CALL(mock_h264_decoder_factory_, CreateVideoDecoder(_)).Times(0);
788 video_receive_stream_->Start();
789 video_receive_stream_->Stop();
790}
791
Tommiae4d0972020-05-18 08:45:38 +0200792} // namespace webrtc