blob: 81f74fbc23a2679805b66f309cb253c84694994e [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"
kwibergac9f8762016-09-30 22:29:43 -070018#include "webrtc/modules/video_coding/video_coding_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010019#include "webrtc/system_wrappers/include/clock.h"
kwibergac9f8762016-09-30 22:29:43 -070020#include "webrtc/test/gtest.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() {
sprang3911c262016-04-15 01:24:14 -070036 receiver_.reset(new VideoReceiver(&clock_, &event_factory_, nullptr));
perkj796cfaf2015-12-10 09:27:38 -080037 receiver_->RegisterExternalDecoder(&decoder_, kUnusedPayloadType);
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
Peter Boström7776e782016-01-07 15:42:47 +010042 VideoCodingModule::Codec(kVideoCodecVP8, &settings_);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000043 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
44 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
45 }
46
47 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000048 WebRtcRTPHeader* header) {
49 ASSERT_TRUE(header != NULL);
50 for (int j = 0; j < 5; ++j) {
51 // Padding only packets are passed to the VCM with payload size 0.
52 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
53 ++header->header.sequenceNumber;
54 }
pbosa26ac922016-02-25 04:50:01 -080055 receiver_->Process();
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000056 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
perkj796cfaf2015-12-10 09:27:38 -080057 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000058 }
59
60 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000061 size_t length,
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000062 WebRtcRTPHeader* header) {
63 ASSERT_TRUE(header != NULL);
64 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
65 ++header->header.sequenceNumber;
66 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pbosa26ac922016-02-25 04:50:01 -080067 receiver_->Process();;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000068 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
perkj796cfaf2015-12-10 09:27:38 -080069 EXPECT_EQ(0, receiver_->Decode(100));
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000070 }
71
72 SimulatedClock clock_;
73 NullEventFactory event_factory_;
74 VideoCodec settings_;
75 NiceMock<MockVideoDecoder> decoder_;
76 NiceMock<MockPacketRequestCallback> packet_request_callback_;
77
kwiberg3f55dea2016-02-29 05:51:59 -080078 std::unique_ptr<VideoReceiver> receiver_;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000079};
80
81TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
82 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
83 EXPECT_EQ(
84 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000085 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000086 const uint8_t payload[kPaddingSize] = {0};
87 WebRtcRTPHeader header;
88 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -070089 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000090 header.header.markerBit = false;
91 header.header.paddingLength = kPaddingSize;
92 header.header.payloadType = kUnusedPayloadType;
93 header.header.ssrc = 1;
94 header.header.headerLength = 12;
95 header.type.Video.codec = kRtpVideoVp8;
96 for (int i = 0; i < 10; ++i) {
97 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000098 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +000099 clock_.AdvanceTimeMilliseconds(33);
100 header.header.timestamp += 3000;
101 }
102}
103
104TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
105 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
106 EXPECT_EQ(
107 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000108 const size_t kFrameSize = 1200;
109 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000110 const uint8_t payload[kFrameSize] = {0};
111 WebRtcRTPHeader header;
112 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700113 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000114 header.header.markerBit = false;
115 header.header.paddingLength = kPaddingSize;
116 header.header.payloadType = kUnusedPayloadType;
117 header.header.ssrc = 1;
118 header.header.headerLength = 12;
119 header.type.Video.codec = kRtpVideoVp8;
120 // Insert one video frame to get one frame decoded.
121 header.frameType = kVideoFrameKey;
122 header.type.Video.isFirstPacket = true;
123 header.header.markerBit = true;
124 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
125 clock_.AdvanceTimeMilliseconds(33);
126 header.header.timestamp += 3000;
127
pbos22993e12015-10-19 02:39:06 -0700128 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000129 header.type.Video.isFirstPacket = false;
130 header.header.markerBit = false;
131 // Insert padding frames.
132 for (int i = 0; i < 10; ++i) {
133 // Lose one packet from the 6th frame.
134 if (i == 5) {
135 ++header.header.sequenceNumber;
136 }
137 // Lose the 4th frame.
138 if (i == 3) {
139 header.header.sequenceNumber += 5;
140 } else {
141 if (i > 3 && i < 5) {
142 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
143 } else if (i >= 5) {
144 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
145 } else {
146 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
147 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000148 InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000149 }
150 clock_.AdvanceTimeMilliseconds(33);
151 header.header.timestamp += 3000;
152 }
153}
154
155TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
156 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
157 EXPECT_EQ(
158 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000159 const size_t kFrameSize = 1200;
160 const size_t kPaddingSize = 220;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000161 const uint8_t payload[kFrameSize] = {0};
162 WebRtcRTPHeader header;
163 memset(&header, 0, sizeof(header));
pbos22993e12015-10-19 02:39:06 -0700164 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000165 header.type.Video.isFirstPacket = false;
166 header.header.markerBit = false;
167 header.header.paddingLength = kPaddingSize;
168 header.header.payloadType = kUnusedPayloadType;
169 header.header.ssrc = 1;
170 header.header.headerLength = 12;
171 header.type.Video.codec = kRtpVideoVp8;
172 header.type.Video.codecHeader.VP8.pictureId = -1;
173 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
174 for (int i = 0; i < 3; ++i) {
175 // Insert 2 video frames.
176 for (int j = 0; j < 2; ++j) {
177 if (i == 0 && j == 0) // First frame should be a key frame.
178 header.frameType = kVideoFrameKey;
179 else
180 header.frameType = kVideoFrameDelta;
181 header.type.Video.isFirstPacket = true;
182 header.header.markerBit = true;
183 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
184 clock_.AdvanceTimeMilliseconds(33);
185 header.header.timestamp += 3000;
186 }
187
188 // Insert 2 padding only frames.
pbos22993e12015-10-19 02:39:06 -0700189 header.frameType = kEmptyFrame;
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000190 header.type.Video.isFirstPacket = false;
191 header.header.markerBit = false;
192 for (int j = 0; j < 2; ++j) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000193 // InsertAndVerifyPaddingFrame(payload, &header);
andresp@webrtc.orge401c2e2013-09-16 20:29:13 +0000194 clock_.AdvanceTimeMilliseconds(33);
195 header.header.timestamp += 3000;
196 }
197 }
198}
199
200TEST_F(TestVideoReceiver, ReceiverDelay) {
201 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
202 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
203 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
204 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
205}
206
207} // namespace
208} // namespace vcm
209} // namespace webrtc