blob: 75266915878de9dc524d4285c4faeb5a62a29639 [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020012#include "modules/video_coding/include/mock/mock_vcm_callbacks.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"
18#include "test/video_codec_settings.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000019
20using ::testing::_;
tommid0a71ba2017-03-14 04:16:20 -070021using ::testing::AnyNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000022using ::testing::NiceMock;
23
24namespace webrtc {
25namespace vcm {
26namespace {
27
28class TestVideoReceiver : public ::testing::Test {
29 protected:
30 static const int kUnusedPayloadType = 10;
Åsa Persson86202532019-01-09 14:03:59 +010031 static const uint16_t kMaxWaitTimeMs = 100;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000032
Åsa Persson86202532019-01-09 14:03:59 +010033 TestVideoReceiver()
34 : clock_(0), timing_(&clock_), receiver_(&clock_, &timing_) {}
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000035
36 virtual void SetUp() {
Åsa Persson86202532019-01-09 14:03:59 +010037 // Register decoder.
38 receiver_.RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
39 webrtc::test::CodecSettings(kVideoCodecVP8, &settings_);
40 settings_.plType = kUnusedPayloadType;
41 EXPECT_EQ(0, receiver_.RegisterReceiveCodec(&settings_, 1, true));
42
43 // Set protection mode.
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000044 const size_t kMaxNackListSize = 250;
45 const int kMaxPacketAgeToNack = 450;
Åsa Persson86202532019-01-09 14:03:59 +010046 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
Åsa Persson86202532019-01-09 14:03:59 +010047 EXPECT_EQ(
48 0, receiver_.RegisterPacketRequestCallback(&packet_request_callback_));
tommid0a71ba2017-03-14 04:16:20 -070049
50 // Since we call Decode, we need to provide a valid receive callback.
51 // However, for the purposes of these tests, we ignore the callbacks.
52 EXPECT_CALL(receive_callback_, OnIncomingPayloadType(_)).Times(AnyNumber());
53 EXPECT_CALL(receive_callback_, OnDecoderImplementationName(_))
54 .Times(AnyNumber());
Åsa Persson86202532019-01-09 14:03:59 +010055 receiver_.RegisterReceiveCallback(&receive_callback_);
56 }
57
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020058 RTPHeader GetDefaultRTPHeader() const {
59 RTPHeader header;
60 header.markerBit = false;
61 header.payloadType = kUnusedPayloadType;
62 header.ssrc = 1;
63 header.headerLength = 12;
Åsa Persson86202532019-01-09 14:03:59 +010064 return header;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000065 }
66
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020067 RTPVideoHeader GetDefaultVp8Header() const {
68 RTPVideoHeader video_header = {};
69 video_header.frame_type = VideoFrameType::kEmptyFrame;
70 video_header.codec = kVideoCodecVP8;
71 return video_header;
72 }
73
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000074 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020075 RTPHeader* header,
76 const RTPVideoHeader& video_header) {
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000077 for (int j = 0; j < 5; ++j) {
78 // Padding only packets are passed to the VCM with payload size 0.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020079 EXPECT_EQ(0, receiver_.IncomingPacket(payload, 0, *header, video_header));
80 ++header->sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000081 }
Åsa Persson86202532019-01-09 14:03:59 +010082 receiver_.Process();
Niels Möller7aacdd92019-03-25 09:11:40 +010083 EXPECT_CALL(decoder_, Decode(_, _, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +010084 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000085 }
86
87 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000088 size_t length,
Niels Möllerbe7a0ec2019-04-25 10:02:52 +020089 RTPHeader* header,
90 const RTPVideoHeader& video_header) {
91 EXPECT_EQ(0,
92 receiver_.IncomingPacket(payload, length, *header, video_header));
93 ++header->sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000094 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Åsa Persson86202532019-01-09 14:03:59 +010095
96 receiver_.Process();
Niels Möller7aacdd92019-03-25 09:11:40 +010097 EXPECT_CALL(decoder_, Decode(_, _, _)).Times(1);
Åsa Persson86202532019-01-09 14:03:59 +010098 EXPECT_EQ(0, receiver_.Decode(kMaxWaitTimeMs));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000099 }
100
101 SimulatedClock clock_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000102 VideoCodec settings_;
103 NiceMock<MockVideoDecoder> decoder_;
104 NiceMock<MockPacketRequestCallback> packet_request_callback_;
Åsa Persson86202532019-01-09 14:03:59 +0100105 VCMTiming timing_;
tommid0a71ba2017-03-14 04:16:20 -0700106 MockVCMReceiveCallback receive_callback_;
Åsa Persson86202532019-01-09 14:03:59 +0100107 VideoReceiver receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000108};
109
110TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000111 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100112 const uint8_t kPayload[kPaddingSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200113 RTPHeader header = GetDefaultRTPHeader();
114 RTPVideoHeader video_header = GetDefaultVp8Header();
115 header.paddingLength = kPaddingSize;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000116 for (int i = 0; i < 10; ++i) {
117 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200118 InsertAndVerifyPaddingFrame(kPayload, &header, video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000119 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200120 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000121 }
122}
123
124TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000125 const size_t kFrameSize = 1200;
126 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100127 const uint8_t kPayload[kFrameSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200128 RTPHeader header = GetDefaultRTPHeader();
129 RTPVideoHeader video_header = GetDefaultVp8Header();
130 header.paddingLength = kPaddingSize;
131 video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
Åsa Persson86202532019-01-09 14:03:59 +0100132
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000133 // Insert one video frame to get one frame decoded.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200134 video_header.frame_type = VideoFrameType::kVideoFrameKey;
135 video_header.is_first_packet_in_frame = true;
136 header.markerBit = true;
137 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header, video_header);
Åsa Persson86202532019-01-09 14:03:59 +0100138
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000139 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200140 header.timestamp += 3000;
141 video_header.frame_type = VideoFrameType::kEmptyFrame;
142 video_header.is_first_packet_in_frame = false;
143 header.markerBit = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000144 // Insert padding frames.
145 for (int i = 0; i < 10; ++i) {
146 // Lose one packet from the 6th frame.
147 if (i == 5) {
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200148 ++header.sequenceNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000149 }
150 // Lose the 4th frame.
151 if (i == 3) {
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200152 header.sequenceNumber += 5;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000153 } else {
154 if (i > 3 && i < 5) {
155 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
156 } else if (i >= 5) {
157 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
158 } else {
159 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
160 }
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200161 InsertAndVerifyPaddingFrame(kPayload, &header, video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000162 }
163 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200164 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000165 }
166}
167
168TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000169 const size_t kFrameSize = 1200;
170 const size_t kPaddingSize = 220;
Åsa Persson86202532019-01-09 14:03:59 +0100171 const uint8_t kPayload[kFrameSize] = {0};
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200172 RTPHeader header = GetDefaultRTPHeader();
173 RTPVideoHeader video_header = GetDefaultVp8Header();
174 video_header.is_first_packet_in_frame = false;
175 header.paddingLength = kPaddingSize;
Philip Eliassond52a1a62018-09-07 13:03:55 +0000176 auto& vp8_header =
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200177 video_header.video_type_header.emplace<RTPVideoHeaderVP8>();
Philip Eliassond52a1a62018-09-07 13:03:55 +0000178 vp8_header.pictureId = -1;
179 vp8_header.tl0PicIdx = -1;
Åsa Persson86202532019-01-09 14:03:59 +0100180
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000181 for (int i = 0; i < 3; ++i) {
182 // Insert 2 video frames.
183 for (int j = 0; j < 2; ++j) {
184 if (i == 0 && j == 0) // First frame should be a key frame.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200185 video_header.frame_type = VideoFrameType::kVideoFrameKey;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000186 else
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200187 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
188 video_header.is_first_packet_in_frame = true;
189 header.markerBit = true;
190 InsertAndVerifyDecodableFrame(kPayload, kFrameSize, &header,
191 video_header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000192 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200193 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000194 }
195
196 // Insert 2 padding only frames.
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200197 video_header.frame_type = VideoFrameType::kEmptyFrame;
198 video_header.is_first_packet_in_frame = false;
199 header.markerBit = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000200 for (int j = 0; j < 2; ++j) {
Åsa Persson86202532019-01-09 14:03:59 +0100201 // InsertAndVerifyPaddingFrame(kPayload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000202 clock_.AdvanceTimeMilliseconds(33);
Niels Möllerbe7a0ec2019-04-25 10:02:52 +0200203 header.timestamp += 3000;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000204 }
205 }
206}
207
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000208} // namespace
209} // namespace vcm
210} // namespace webrtc