blob: fc83141380725e65d7cff5a0ed84139e4340a058 [file] [log] [blame]
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +00001/*
2 * Copyright (c) 2013 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
Erik Språngc84cd952018-10-15 11:55:13 +020011#include "api/test/mock_video_decoder.h"
Danil Chapovalov355b8d22021-08-13 16:50:37 +020012#include "api/video_codecs/video_decoder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/video_coding/include/video_coding.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/video_coding/timing.h"
15#include "modules/video_coding/video_coding_impl.h"
16#include "system_wrappers/include/clock.h"
17#include "test/gtest.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000018
19using ::testing::_;
tommid0a71ba2017-03-14 04:16:20 -070020using ::testing::AnyNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000021using ::testing::NiceMock;
22
23namespace webrtc {
24namespace vcm {
25namespace {
26
Niels Möller2fca9712020-02-04 10:46:37 +010027class MockPacketRequestCallback : public VCMPacketRequestCallback {
28 public:
Danil Chapovalovf2c0f152020-05-19 13:20:27 +020029 MOCK_METHOD(int32_t,
30 ResendPackets,
31 (const uint16_t* sequenceNumbers, uint16_t length),
32 (override));
Niels Möller2fca9712020-02-04 10:46:37 +010033};
34
35class MockVCMReceiveCallback : public VCMReceiveCallback {
36 public:
37 MockVCMReceiveCallback() {}
38 virtual ~MockVCMReceiveCallback() {}
39
Danil Chapovalovf2c0f152020-05-19 13:20:27 +020040 MOCK_METHOD(int32_t,
41 FrameToRender,
42 (VideoFrame&, absl::optional<uint8_t>, int32_t, VideoContentType),
43 (override));
44 MOCK_METHOD(void, OnIncomingPayloadType, (int), (override));
45 MOCK_METHOD(void, OnDecoderImplementationName, (const char*), (override));
Niels Möller2fca9712020-02-04 10:46:37 +010046};
47
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000048class TestVideoReceiver : public ::testing::Test {
49 protected:
50 static const int kUnusedPayloadType = 10;
Åsa Persson86202532019-01-09 14:03:59 +010051 static const uint16_t kMaxWaitTimeMs = 100;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000052
Åsa Persson86202532019-01-09 14:03:59 +010053 TestVideoReceiver()
54 : clock_(0), timing_(&clock_), receiver_(&clock_, &timing_) {}
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000055
56 virtual void SetUp() {
Åsa Persson86202532019-01-09 14:03:59 +010057 // Register decoder.
58 receiver_.RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
Danil Chapovalov355b8d22021-08-13 16:50:37 +020059 VideoDecoder::Settings settings;
60 settings.set_codec_type(kVideoCodecVP8);
Danil Chapovalovba0a3062021-08-13 18:15:55 +020061 receiver_.RegisterReceiveCodec(kUnusedPayloadType, settings);
Åsa Persson86202532019-01-09 14:03:59 +010062
63 // Set protection mode.
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000064 const size_t kMaxNackListSize = 250;
65 const int kMaxPacketAgeToNack = 450;
Åsa Persson86202532019-01-09 14:03:59 +010066 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
Åsa Persson86202532019-01-09 14:03:59 +010067 EXPECT_EQ(
68 0, receiver_.RegisterPacketRequestCallback(&packet_request_callback_));
tommid0a71ba2017-03-14 04:16:20 -070069
70 // Since we call Decode, we need to provide a valid receive callback.
71 // However, for the purposes of these tests, we ignore the callbacks.
72 EXPECT_CALL(receive_callback_, OnIncomingPayloadType(_)).Times(AnyNumber());
73 EXPECT_CALL(receive_callback_, OnDecoderImplementationName(_))
74 .Times(AnyNumber());
Åsa Persson86202532019-01-09 14:03:59 +010075 receiver_.RegisterReceiveCallback(&receive_callback_);
76 }
77
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020078 RTPHeader GetDefaultRTPHeader() const {
79 RTPHeader header;
80 header.markerBit = false;
81 header.payloadType = kUnusedPayloadType;
82 header.ssrc = 1;
83 header.headerLength = 12;
Åsa Persson86202532019-01-09 14:03:59 +010084 return header;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000085 }
86
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020087 RTPVideoHeader GetDefaultVp8Header() const {
88 RTPVideoHeader video_header = {};
89 video_header.frame_type = VideoFrameType::kEmptyFrame;
90 video_header.codec = kVideoCodecVP8;
91 return video_header;
92 }
93
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000094 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020095 RTPHeader* header,
96 const RTPVideoHeader& video_header) {
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000097 for (int j = 0; j < 5; ++j) {
98 // Padding only packets are passed to the VCM with payload size 0.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020099 EXPECT_EQ(0, receiver_.IncomingPacket(payload, 0, *header, video_header));
100 ++header->sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000101 }
Åsa Persson86202532019-01-09 14:03:59 +0100102 receiver_.Process();
Niels Möller7aacdd92019-03-25 09:11:40 +0100103 EXPECT_CALL(decoder_, Decode(_, _, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +0100104 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000105 }
106
107 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000108 size_t length,
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200109 RTPHeader* header,
110 const RTPVideoHeader& video_header) {
111 EXPECT_EQ(0,
112 receiver_.IncomingPacket(payload, length, *header, video_header));
113 ++header->sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000114 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +0100115
116 receiver_.Process();
Niels Möller7aacdd92019-03-25 09:11:40 +0100117 EXPECT_CALL(decoder_, Decode(_, _, _)).Times(1);
Åsa Persson86202532019-01-09 14:03:59 +0100118 EXPECT_EQ(0, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000119 }
120
121 SimulatedClock clock_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000122 NiceMock<MockVideoDecoder> decoder_;
123 NiceMock<MockPacketRequestCallback> packet_request_callback_;
Åsa Persson86202532019-01-09 14:03:59 +0100124 VCMTiming timing_;
tommid0a71ba2017-03-14 04:16:20 -0700125 MockVCMReceiveCallback receive_callback_;
Åsa Persson86202532019-01-09 14:03:59 +0100126 VideoReceiver receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000127};
128
129TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000130 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100131 const uint8_t kPayload[kPaddingSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200132 RTPHeader header = GetDefaultRTPHeader();
133 RTPVideoHeader video_header = GetDefaultVp8Header();
134 header.paddingLength = kPaddingSize;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000135 for (int i = 0; i < 10; ++i) {
136 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200137 InsertAndVerifyPaddingFrame(kPayload, &header, video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000138 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200139 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000140 }
141}
142
143TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000144 const size_t kFrameSize = 1200;
145 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100146 const uint8_t kPayload[kFrameSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200147 RTPHeader header = GetDefaultRTPHeader();
148 RTPVideoHeader video_header = GetDefaultVp8Header();
149 header.paddingLength = kPaddingSize;
150 video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
Åsa Persson86202532019-01-09 14:03:59 +0100151
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000152 // Insert one video frame to get one frame decoded.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200153 video_header.frame_type = VideoFrameType::kVideoFrameKey;
154 video_header.is_first_packet_in_frame = true;
155 header.markerBit = true;
156 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header, video_header);
Åsa Persson86202532019-01-09 14:03:59 +0100157
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000158 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200159 header.timestamp += 3000;
160 video_header.frame_type = VideoFrameType::kEmptyFrame;
161 video_header.is_first_packet_in_frame = false;
162 header.markerBit = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000163 // Insert padding frames.
164 for (int i = 0; i < 10; ++i) {
165 // Lose one packet from the 6th frame.
166 if (i == 5) {
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200167 ++header.sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000168 }
169 // Lose the 4th frame.
170 if (i == 3) {
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200171 header.sequenceNumber += 5;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000172 } else {
173 if (i > 3 && i < 5) {
174 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
175 } else if (i >= 5) {
176 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
177 } else {
178 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
179 }
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200180 InsertAndVerifyPaddingFrame(kPayload, &header, video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000181 }
182 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200183 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000184 }
185}
186
187TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000188 const size_t kFrameSize = 1200;
189 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100190 const uint8_t kPayload[kFrameSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200191 RTPHeader header = GetDefaultRTPHeader();
192 RTPVideoHeader video_header = GetDefaultVp8Header();
193 video_header.is_first_packet_in_frame = false;
194 header.paddingLength = kPaddingSize;
Philip Eliassond52a1a62018-09-07 13:03:55 +0000195 auto& vp8_header =
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200196 video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
Philip Eliassond52a1a62018-09-07 13:03:55 +0000197 vp8_header.pictureId = -1;
198 vp8_header.tl0PicIdx = -1;
Åsa Persson86202532019-01-09 14:03:59 +0100199
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000200 for (int i = 0; i < 3; ++i) {
201 // Insert 2 video frames.
202 for (int j = 0; j < 2; ++j) {
203 if (i == 0 && j == 0) // First frame should be a key frame.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200204 video_header.frame_type = VideoFrameType::kVideoFrameKey;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000205 else
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200206 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
207 video_header.is_first_packet_in_frame = true;
208 header.markerBit = true;
209 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header,
210 video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000211 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200212 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000213 }
214
215 // Insert 2 padding only frames.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200216 video_header.frame_type = VideoFrameType::kEmptyFrame;
217 video_header.is_first_packet_in_frame = false;
218 header.markerBit = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000219 for (int j = 0; j < 2; ++j) {
Åsa Persson86202532019-01-09 14:03:59 +0100220 // InsertAndVerifyPaddingFrame(kPayload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000221 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200222 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000223 }
224 }
225}
226
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000227} // namespace
228} // namespace vcm
229} // namespace webrtc