blob: 3e4d3244c6d11d39da2814b92978613ba5e44e43 [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
Henrik Kjellander2557b862015-11-18 22:00:21 +010014#include "webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h"
kwibergac9f8762016-09-30 22:29:43 -070015#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010016#include "webrtc/modules/video_coding/include/video_coding.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010017#include "webrtc/modules/video_coding/test/test_util.h"
philipel721d4022016-12-15 07:10:57 -080018#include "webrtc/modules/video_coding/timing.h"
kwibergac9f8762016-09-30 22:29:43 -070019#include "webrtc/modules/video_coding/video_coding_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010020#include "webrtc/system_wrappers/include/clock.h"
kwibergac9f8762016-09-30 22:29:43 -070021#include "webrtc/test/gtest.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000022
23using ::testing::_;
tommid0a71ba2017-03-14 04:16:20 -070024using ::testing::AnyNumber;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000025using ::testing::NiceMock;
26
27namespace webrtc {
28namespace vcm {
29namespace {
30
31class TestVideoReceiver : public ::testing::Test {
32 protected:
33 static const int kUnusedPayloadType = 10;
34
35 TestVideoReceiver() : clock_(0) {}
36
37 virtual void SetUp() {
philipel721d4022016-12-15 07:10:57 -080038 timing_.reset(new VCMTiming(&clock_));
39 receiver_.reset(
40 new VideoReceiver(&clock_, &event_factory_, nullptr, timing_.get()));
perkj796cfaf2015-12-10 09:27:38 -080041 receiver_->RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000042 const size_t kMaxNackListSize = 250;
43 const int kMaxPacketAgeToNack = 450;
44 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
45
Peter Boström7776e782016-01-07 15:42:47 +010046 VideoCodingModule::Codec(kVideoCodecVP8, &settings_);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000047 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
48 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
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());
55 receiver_->RegisterReceiveCallback(&receive_callback_);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000056 }
57
58 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000059 WebRtcRTPHeader* header) {
60 ASSERT_TRUE(header != NULL);
61 for (int j = 0; j < 5; ++j) {
62 // Padding only packets are passed to the VCM with payload size 0.
63 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
64 ++header->header.sequenceNumber;
65 }
pbosa26ac922016-02-25 04:50:01 -080066 receiver_->Process();
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000067 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
perkj796cfaf2015-12-10 09:27:38 -080068 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000069 }
70
71 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000072 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000073 WebRtcRTPHeader* header) {
74 ASSERT_TRUE(header != NULL);
75 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
76 ++header->header.sequenceNumber;
77 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pbosa26ac922016-02-25 04:50:01 -080078 receiver_->Process();;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000079 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
perkj796cfaf2015-12-10 09:27:38 -080080 EXPECT_EQ(0, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000081 }
82
83 SimulatedClock clock_;
84 NullEventFactory event_factory_;
85 VideoCodec settings_;
86 NiceMock<MockVideoDecoder> decoder_;
87 NiceMock<MockPacketRequestCallback> packet_request_callback_;
88
philipel721d4022016-12-15 07:10:57 -080089 std::unique_ptr<VCMTiming> timing_;
tommid0a71ba2017-03-14 04:16:20 -070090 MockVCMReceiveCallback receive_callback_;
kwiberg3f55dea2016-02-29 05:51:59 -080091 std::unique_ptr<VideoReceiver> receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000092};
93
94TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
95 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
96 EXPECT_EQ(
97 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000098 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000099 const uint8_t payload[kPaddingSize] = {0};
100 WebRtcRTPHeader header;
101 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700102 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000103 header.header.markerBit = false;
104 header.header.paddingLength = kPaddingSize;
105 header.header.payloadType = kUnusedPayloadType;
106 header.header.ssrc = 1;
107 header.header.headerLength = 12;
108 header.type.Video.codec = kRtpVideoVp8;
109 for (int i = 0; i < 10; ++i) {
110 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000111 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000112 clock_.AdvanceTimeMilliseconds(33);
113 header.header.timestamp += 3000;
114 }
115}
116
117TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
118 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
119 EXPECT_EQ(
120 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000121 const size_t kFrameSize = 1200;
122 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000123 const uint8_t payload[kFrameSize] = {0};
124 WebRtcRTPHeader header;
125 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700126 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000127 header.header.markerBit = false;
128 header.header.paddingLength = kPaddingSize;
129 header.header.payloadType = kUnusedPayloadType;
130 header.header.ssrc = 1;
131 header.header.headerLength = 12;
132 header.type.Video.codec = kRtpVideoVp8;
133 // Insert one video frame to get one frame decoded.
134 header.frameType = kVideoFrameKey;
johan0d1b2b62017-01-10 04:21:35 -0800135 header.type.Video.is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000136 header.header.markerBit = true;
137 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
138 clock_.AdvanceTimeMilliseconds(33);
139 header.header.timestamp += 3000;
140
pbos22993e12015-10-19 02:39:06 -0700141 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800142 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000143 header.header.markerBit = false;
144 // Insert padding frames.
145 for (int i = 0; i < 10; ++i) {
146 // Lose one packet from the 6th frame.
147 if (i == 5) {
148 ++header.header.sequenceNumber;
149 }
150 // Lose the 4th frame.
151 if (i == 3) {
152 header.header.sequenceNumber += 5;
153 } 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 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000161 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000162 }
163 clock_.AdvanceTimeMilliseconds(33);
164 header.header.timestamp += 3000;
165 }
166}
167
168TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
169 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
170 EXPECT_EQ(
171 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000172 const size_t kFrameSize = 1200;
173 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000174 const uint8_t payload[kFrameSize] = {0};
175 WebRtcRTPHeader header;
176 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700177 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800178 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000179 header.header.markerBit = false;
180 header.header.paddingLength = kPaddingSize;
181 header.header.payloadType = kUnusedPayloadType;
182 header.header.ssrc = 1;
183 header.header.headerLength = 12;
184 header.type.Video.codec = kRtpVideoVp8;
185 header.type.Video.codecHeader.VP8.pictureId = -1;
186 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
187 for (int i = 0; i < 3; ++i) {
188 // Insert 2 video frames.
189 for (int j = 0; j < 2; ++j) {
190 if (i == 0 && j == 0) // First frame should be a key frame.
191 header.frameType = kVideoFrameKey;
192 else
193 header.frameType = kVideoFrameDelta;
johan0d1b2b62017-01-10 04:21:35 -0800194 header.type.Video.is_first_packet_in_frame = true;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000195 header.header.markerBit = true;
196 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
197 clock_.AdvanceTimeMilliseconds(33);
198 header.header.timestamp += 3000;
199 }
200
201 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700202 header.frameType = kEmptyFrame;
johan0d1b2b62017-01-10 04:21:35 -0800203 header.type.Video.is_first_packet_in_frame = false;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000204 header.header.markerBit = false;
205 for (int j = 0; j < 2; ++j) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000206 // InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000207 clock_.AdvanceTimeMilliseconds(33);
208 header.header.timestamp += 3000;
209 }
210 }
211}
212
213TEST_F(TestVideoReceiver, ReceiverDelay) {
214 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
215 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
216 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
217 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
218}
219
220} // namespace
221} // namespace vcm
222} // namespace webrtc