blob: 917cdc1113487c69a59bfd3d2ef65ce109e13848 [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
kwiberg3f55dea2016-02-29 05:51:59 -080011#include <memory>
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000012#include <vector>
13
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/video_coding/include/mock/mock_vcm_callbacks.h"
15#include "modules/video_coding/include/mock/mock_video_codec_interface.h"
16#include "modules/video_coding/include/video_coding.h"
17#include "modules/video_coding/test/test_util.h"
18#include "modules/video_coding/timing.h"
19#include "modules/video_coding/video_coding_impl.h"
20#include "system_wrappers/include/clock.h"
21#include "test/gtest.h"
22#include "test/video_codec_settings.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000023
24using ::testing::_;
tommid0a71ba2017-03-14 04:16:20 -070025using ::testing::AnyNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000026using ::testing::NiceMock;
27
28namespace webrtc {
29namespace vcm {
30namespace {
31
32class TestVideoReceiver : public ::testing::Test {
33 protected:
34 static const int kUnusedPayloadType = 10;
35
36 TestVideoReceiver() : clock_(0) {}
37
38 virtual void SetUp() {
philipel721d4022016-12-15 07:10:57 -080039 timing_.reset(new VCMTiming(&clock_));
40 receiver_.reset(
41 new VideoReceiver(&clock_, &event_factory_, nullptr, timing_.get()));
perkj796cfaf2015-12-10 09:27:38 -080042 receiver_->RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000043 const size_t kMaxNackListSize = 250;
44 const int kMaxPacketAgeToNack = 450;
45 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
46
mflodman351424e2017-08-10 02:43:14 -070047 webrtc::test::CodecSettings(kVideoCodecVP8, &settings_);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000048 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
49 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
tommid0a71ba2017-03-14 04:16:20 -070050
51 // Since we call Decode, we need to provide a valid receive callback.
52 // However, for the purposes of these tests, we ignore the callbacks.
53 EXPECT_CALL(receive_callback_, OnIncomingPayloadType(_)).Times(AnyNumber());
54 EXPECT_CALL(receive_callback_, OnDecoderImplementationName(_))
55 .Times(AnyNumber());
56 receiver_->RegisterReceiveCallback(&receive_callback_);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000057 }
58
59 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000060 WebRtcRTPHeader* header) {
61 ASSERT_TRUE(header != NULL);
62 for (int j = 0; j < 5; ++j) {
63 // Padding only packets are passed to the VCM with payload size 0.
64 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
65 ++header->header.sequenceNumber;
66 }
pbosa26ac922016-02-25 04:50:01 -080067 receiver_->Process();
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000068 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
perkj796cfaf2015-12-10 09:27:38 -080069 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000070 }
71
72 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000073 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000074 WebRtcRTPHeader* header) {
75 ASSERT_TRUE(header != NULL);
76 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
77 ++header->header.sequenceNumber;
78 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pbosa26ac922016-02-25 04:50:01 -080079 receiver_->Process();;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000080 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
perkj796cfaf2015-12-10 09:27:38 -080081 EXPECT_EQ(0, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000082 }
83
84 SimulatedClock clock_;
85 NullEventFactory event_factory_;
86 VideoCodec settings_;
87 NiceMock<MockVideoDecoder> decoder_;
88 NiceMock<MockPacketRequestCallback> packet_request_callback_;
89
philipel721d4022016-12-15 07:10:57 -080090 std::unique_ptr<VCMTiming> timing_;
tommid0a71ba2017-03-14 04:16:20 -070091 MockVCMReceiveCallback receive_callback_;
kwiberg3f55dea2016-02-29 05:51:59 -080092 std::unique_ptr<VideoReceiver> receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000093};
94
95TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
96 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
97 EXPECT_EQ(
98 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000099 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000100 const uint8_t payload[kPaddingSize] = {0};
101 WebRtcRTPHeader header;
102 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700103 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000104 header.header.markerBit = false;
105 header.header.paddingLength = kPaddingSize;
106 header.header.payloadType = kUnusedPayloadType;
107 header.header.ssrc = 1;
108 header.header.headerLength = 12;
109 header.type.Video.codec = kRtpVideoVp8;
110 for (int i = 0; i < 10; ++i) {
111 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000112 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000113 clock_.AdvanceTimeMilliseconds(33);
114 header.header.timestamp += 3000;
115 }
116}
117
118TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
119 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
120 EXPECT_EQ(
121 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000122 const size_t kFrameSize = 1200;
123 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000124 const uint8_t payload[kFrameSize] = {0};
125 WebRtcRTPHeader header;
126 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700127 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000128 header.header.markerBit = false;
129 header.header.paddingLength = kPaddingSize;
130 header.header.payloadType = kUnusedPayloadType;
131 header.header.ssrc = 1;
132 header.header.headerLength = 12;
133 header.type.Video.codec = kRtpVideoVp8;
134 // Insert one video frame to get one frame decoded.
135 header.frameType = kVideoFrameKey;
johan0d1b2b62017-01-10 04:21:35 -0800136 header.type.Video.is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000137 header.header.markerBit = true;
138 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
139 clock_.AdvanceTimeMilliseconds(33);
140 header.header.timestamp += 3000;
141
pbos22993e12015-10-19 02:39:06 -0700142 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800143 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000144 header.header.markerBit = false;
145 // Insert padding frames.
146 for (int i = 0; i < 10; ++i) {
147 // Lose one packet from the 6th frame.
148 if (i == 5) {
149 ++header.header.sequenceNumber;
150 }
151 // Lose the 4th frame.
152 if (i == 3) {
153 header.header.sequenceNumber += 5;
154 } else {
155 if (i > 3 && i < 5) {
156 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
157 } else if (i >= 5) {
158 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
159 } else {
160 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
161 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000162 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000163 }
164 clock_.AdvanceTimeMilliseconds(33);
165 header.header.timestamp += 3000;
166 }
167}
168
169TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
170 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
171 EXPECT_EQ(
172 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000173 const size_t kFrameSize = 1200;
174 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000175 const uint8_t payload[kFrameSize] = {0};
176 WebRtcRTPHeader header;
177 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700178 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800179 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000180 header.header.markerBit = false;
181 header.header.paddingLength = kPaddingSize;
182 header.header.payloadType = kUnusedPayloadType;
183 header.header.ssrc = 1;
184 header.header.headerLength = 12;
185 header.type.Video.codec = kRtpVideoVp8;
186 header.type.Video.codecHeader.VP8.pictureId = -1;
187 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
188 for (int i = 0; i < 3; ++i) {
189 // Insert 2 video frames.
190 for (int j = 0; j < 2; ++j) {
191 if (i == 0 && j == 0) // First frame should be a key frame.
192 header.frameType = kVideoFrameKey;
193 else
194 header.frameType = kVideoFrameDelta;
johan0d1b2b62017-01-10 04:21:35 -0800195 header.type.Video.is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000196 header.header.markerBit = true;
197 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
198 clock_.AdvanceTimeMilliseconds(33);
199 header.header.timestamp += 3000;
200 }
201
202 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700203 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800204 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000205 header.header.markerBit = false;
206 for (int j = 0; j < 2; ++j) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000207 // InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000208 clock_.AdvanceTimeMilliseconds(33);
209 header.header.timestamp += 3000;
210 }
211 }
212}
213
214TEST_F(TestVideoReceiver, ReceiverDelay) {
215 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
216 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
217 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
218 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
219}
220
221} // namespace
222} // namespace vcm
223} // namespace webrtc