blob: 4859c4164f56aeb00abe6051351d42c058bf5b18 [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
11#include <vector>
12
13#include "testing/gtest/include/gtest/gtest.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000014#include "webrtc/base/scoped_ptr.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010015#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h"
16#include "webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h"
17#include "webrtc/modules/video_coding/include/video_coding.h"
18#include "webrtc/modules/video_coding/video_coding_impl.h"
19#include "webrtc/modules/video_coding/test/test_util.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010020#include "webrtc/system_wrappers/include/clock.h"
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000021
22using ::testing::_;
23using ::testing::NiceMock;
24
25namespace webrtc {
26namespace vcm {
27namespace {
28
29class TestVideoReceiver : public ::testing::Test {
30 protected:
31 static const int kUnusedPayloadType = 10;
32
33 TestVideoReceiver() : clock_(0) {}
34
35 virtual void SetUp() {
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000036 receiver_.reset(new VideoReceiver(&clock_, &event_factory_));
Peter Boström5464a6e2015-04-21 16:35:50 +020037 EXPECT_EQ(0, receiver_->RegisterExternalDecoder(&decoder_,
38 kUnusedPayloadType, true));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000039 const size_t kMaxNackListSize = 250;
40 const int kMaxPacketAgeToNack = 450;
41 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
42
43 memset(&settings_, 0, sizeof(settings_));
44 EXPECT_EQ(0, VideoCodingModule::Codec(kVideoCodecVP8, &settings_));
45 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
46 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
47 }
48
49 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000050 WebRtcRTPHeader* header) {
51 ASSERT_TRUE(header != NULL);
52 for (int j = 0; j < 5; ++j) {
53 // Padding only packets are passed to the VCM with payload size 0.
54 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
55 ++header->header.sequenceNumber;
56 }
57 EXPECT_EQ(0, receiver_->Process());
58 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
59 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0));
60 }
61
62 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000063 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000064 WebRtcRTPHeader* header) {
65 ASSERT_TRUE(header != NULL);
66 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
67 ++header->header.sequenceNumber;
68 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
69 EXPECT_EQ(0, receiver_->Process());
70 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
71 EXPECT_EQ(0, receiver_->Decode(0));
72 }
73
74 SimulatedClock clock_;
75 NullEventFactory event_factory_;
76 VideoCodec settings_;
77 NiceMock<MockVideoDecoder> decoder_;
78 NiceMock<MockPacketRequestCallback> packet_request_callback_;
79
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000080 rtc::scoped_ptr<VideoReceiver> receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000081};
82
83TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
84 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
85 EXPECT_EQ(
86 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000087 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000088 const uint8_t payload[kPaddingSize] = {0};
89 WebRtcRTPHeader header;
90 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -070091 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000092 header.header.markerBit = false;
93 header.header.paddingLength = kPaddingSize;
94 header.header.payloadType = kUnusedPayloadType;
95 header.header.ssrc = 1;
96 header.header.headerLength = 12;
97 header.type.Video.codec = kRtpVideoVp8;
98 for (int i = 0; i < 10; ++i) {
99 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000100 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000101 clock_.AdvanceTimeMilliseconds(33);
102 header.header.timestamp += 3000;
103 }
104}
105
106TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
107 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
108 EXPECT_EQ(
109 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000110 const size_t kFrameSize = 1200;
111 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000112 const uint8_t payload[kFrameSize] = {0};
113 WebRtcRTPHeader header;
114 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700115 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000116 header.header.markerBit = false;
117 header.header.paddingLength = kPaddingSize;
118 header.header.payloadType = kUnusedPayloadType;
119 header.header.ssrc = 1;
120 header.header.headerLength = 12;
121 header.type.Video.codec = kRtpVideoVp8;
122 // Insert one video frame to get one frame decoded.
123 header.frameType = kVideoFrameKey;
124 header.type.Video.isFirstPacket = true;
125 header.header.markerBit = true;
126 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
127 clock_.AdvanceTimeMilliseconds(33);
128 header.header.timestamp += 3000;
129
pbos22993e12015-10-19 02:39:06 -0700130 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000131 header.type.Video.isFirstPacket = false;
132 header.header.markerBit = false;
133 // Insert padding frames.
134 for (int i = 0; i < 10; ++i) {
135 // Lose one packet from the 6th frame.
136 if (i == 5) {
137 ++header.header.sequenceNumber;
138 }
139 // Lose the 4th frame.
140 if (i == 3) {
141 header.header.sequenceNumber += 5;
142 } else {
143 if (i > 3 && i < 5) {
144 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
145 } else if (i >= 5) {
146 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
147 } else {
148 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
149 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000150 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000151 }
152 clock_.AdvanceTimeMilliseconds(33);
153 header.header.timestamp += 3000;
154 }
155}
156
157TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
158 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
159 EXPECT_EQ(
160 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000161 const size_t kFrameSize = 1200;
162 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000163 const uint8_t payload[kFrameSize] = {0};
164 WebRtcRTPHeader header;
165 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700166 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000167 header.type.Video.isFirstPacket = false;
168 header.header.markerBit = false;
169 header.header.paddingLength = kPaddingSize;
170 header.header.payloadType = kUnusedPayloadType;
171 header.header.ssrc = 1;
172 header.header.headerLength = 12;
173 header.type.Video.codec = kRtpVideoVp8;
174 header.type.Video.codecHeader.VP8.pictureId = -1;
175 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
176 for (int i = 0; i < 3; ++i) {
177 // Insert 2 video frames.
178 for (int j = 0; j < 2; ++j) {
179 if (i == 0 && j == 0) // First frame should be a key frame.
180 header.frameType = kVideoFrameKey;
181 else
182 header.frameType = kVideoFrameDelta;
183 header.type.Video.isFirstPacket = true;
184 header.header.markerBit = true;
185 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
186 clock_.AdvanceTimeMilliseconds(33);
187 header.header.timestamp += 3000;
188 }
189
190 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700191 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000192 header.type.Video.isFirstPacket = false;
193 header.header.markerBit = false;
194 for (int j = 0; j < 2; ++j) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000195 // InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000196 clock_.AdvanceTimeMilliseconds(33);
197 header.header.timestamp += 3000;
198 }
199 }
200}
201
202TEST_F(TestVideoReceiver, ReceiverDelay) {
203 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
204 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
205 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
206 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
207}
208
209} // namespace
210} // namespace vcm
211} // namespace webrtc