blob: 049f6007b4fb79727d0b9707110e3b847ace9b75 [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öm795dbe42015-11-27 14:09:07 +010037 receiver_->RegisterExternalDecoder(&decoder_, kUnusedPayloadType, true);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000038 const size_t kMaxNackListSize = 250;
39 const int kMaxPacketAgeToNack = 450;
40 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
41
42 memset(&settings_, 0, sizeof(settings_));
43 EXPECT_EQ(0, VideoCodingModule::Codec(kVideoCodecVP8, &settings_));
44 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
45 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
46 }
47
48 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000049 WebRtcRTPHeader* header) {
50 ASSERT_TRUE(header != NULL);
51 for (int j = 0; j < 5; ++j) {
52 // Padding only packets are passed to the VCM with payload size 0.
53 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
54 ++header->header.sequenceNumber;
55 }
56 EXPECT_EQ(0, receiver_->Process());
57 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
58 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0));
59 }
60
61 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000062 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000063 WebRtcRTPHeader* header) {
64 ASSERT_TRUE(header != NULL);
65 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
66 ++header->header.sequenceNumber;
67 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
68 EXPECT_EQ(0, receiver_->Process());
69 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
70 EXPECT_EQ(0, receiver_->Decode(0));
71 }
72
73 SimulatedClock clock_;
74 NullEventFactory event_factory_;
75 VideoCodec settings_;
76 NiceMock<MockVideoDecoder> decoder_;
77 NiceMock<MockPacketRequestCallback> packet_request_callback_;
78
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000079 rtc::scoped_ptr<VideoReceiver> receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000080};
81
82TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
83 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
84 EXPECT_EQ(
85 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000086 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000087 const uint8_t payload[kPaddingSize] = {0};
88 WebRtcRTPHeader header;
89 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -070090 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000091 header.header.markerBit = false;
92 header.header.paddingLength = kPaddingSize;
93 header.header.payloadType = kUnusedPayloadType;
94 header.header.ssrc = 1;
95 header.header.headerLength = 12;
96 header.type.Video.codec = kRtpVideoVp8;
97 for (int i = 0; i < 10; ++i) {
98 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000099 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000100 clock_.AdvanceTimeMilliseconds(33);
101 header.header.timestamp += 3000;
102 }
103}
104
105TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
106 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
107 EXPECT_EQ(
108 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000109 const size_t kFrameSize = 1200;
110 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000111 const uint8_t payload[kFrameSize] = {0};
112 WebRtcRTPHeader header;
113 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700114 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000115 header.header.markerBit = false;
116 header.header.paddingLength = kPaddingSize;
117 header.header.payloadType = kUnusedPayloadType;
118 header.header.ssrc = 1;
119 header.header.headerLength = 12;
120 header.type.Video.codec = kRtpVideoVp8;
121 // Insert one video frame to get one frame decoded.
122 header.frameType = kVideoFrameKey;
123 header.type.Video.isFirstPacket = true;
124 header.header.markerBit = true;
125 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
126 clock_.AdvanceTimeMilliseconds(33);
127 header.header.timestamp += 3000;
128
pbos22993e12015-10-19 02:39:06 -0700129 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000130 header.type.Video.isFirstPacket = false;
131 header.header.markerBit = false;
132 // Insert padding frames.
133 for (int i = 0; i < 10; ++i) {
134 // Lose one packet from the 6th frame.
135 if (i == 5) {
136 ++header.header.sequenceNumber;
137 }
138 // Lose the 4th frame.
139 if (i == 3) {
140 header.header.sequenceNumber += 5;
141 } else {
142 if (i > 3 && i < 5) {
143 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
144 } else if (i >= 5) {
145 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
146 } else {
147 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
148 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000149 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000150 }
151 clock_.AdvanceTimeMilliseconds(33);
152 header.header.timestamp += 3000;
153 }
154}
155
156TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
157 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
158 EXPECT_EQ(
159 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000160 const size_t kFrameSize = 1200;
161 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000162 const uint8_t payload[kFrameSize] = {0};
163 WebRtcRTPHeader header;
164 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700165 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000166 header.type.Video.isFirstPacket = false;
167 header.header.markerBit = false;
168 header.header.paddingLength = kPaddingSize;
169 header.header.payloadType = kUnusedPayloadType;
170 header.header.ssrc = 1;
171 header.header.headerLength = 12;
172 header.type.Video.codec = kRtpVideoVp8;
173 header.type.Video.codecHeader.VP8.pictureId = -1;
174 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
175 for (int i = 0; i < 3; ++i) {
176 // Insert 2 video frames.
177 for (int j = 0; j < 2; ++j) {
178 if (i == 0 && j == 0) // First frame should be a key frame.
179 header.frameType = kVideoFrameKey;
180 else
181 header.frameType = kVideoFrameDelta;
182 header.type.Video.isFirstPacket = true;
183 header.header.markerBit = true;
184 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
185 clock_.AdvanceTimeMilliseconds(33);
186 header.header.timestamp += 3000;
187 }
188
189 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700190 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000191 header.type.Video.isFirstPacket = false;
192 header.header.markerBit = false;
193 for (int j = 0; j < 2; ++j) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000194 // InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000195 clock_.AdvanceTimeMilliseconds(33);
196 header.header.timestamp += 3000;
197 }
198 }
199}
200
201TEST_F(TestVideoReceiver, ReceiverDelay) {
202 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
203 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
204 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
205 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
206}
207
208} // namespace
209} // namespace vcm
210} // namespace webrtc