2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h"
15 #include "webrtc/modules/video_coding/main/interface/mock/mock_vcm_callbacks.h"
16 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
17 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
18 #include "webrtc/modules/video_coding/main/test/test_util.h"
19 #include "webrtc/system_wrappers/interface/clock.h"
20 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
23 using ::testing::NiceMock;
29 class TestVideoReceiver : public ::testing::Test {
31 static const int kUnusedPayloadType = 10;
33 TestVideoReceiver() : clock_(0) {}
35 virtual void SetUp() {
36 receiver_.reset(new VideoReceiver(&clock_, &event_factory_));
37 EXPECT_EQ(0, receiver_->InitializeReceiver());
39 receiver_->RegisterExternalDecoder(
40 &decoder_, kUnusedPayloadType, true));
41 const size_t kMaxNackListSize = 250;
42 const int kMaxPacketAgeToNack = 450;
43 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
45 memset(&settings_, 0, sizeof(settings_));
46 EXPECT_EQ(0, VideoCodingModule::Codec(kVideoCodecVP8, &settings_));
47 settings_.plType = kUnusedPayloadType; // Use the mocked encoder.
48 EXPECT_EQ(0, receiver_->RegisterReceiveCodec(&settings_, 1, true));
51 void InsertAndVerifyPaddingFrame(const uint8_t* payload,
53 WebRtcRTPHeader* header) {
54 ASSERT_TRUE(header != NULL);
55 for (int j = 0; j < 5; ++j) {
56 // Padding only packets are passed to the VCM with payload size 0.
57 EXPECT_EQ(0, receiver_->IncomingPacket(payload, 0, *header));
58 ++header->header.sequenceNumber;
60 EXPECT_EQ(0, receiver_->Process());
61 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0);
62 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0));
65 void InsertAndVerifyDecodableFrame(const uint8_t* payload,
67 WebRtcRTPHeader* header) {
68 ASSERT_TRUE(header != NULL);
69 EXPECT_EQ(0, receiver_->IncomingPacket(payload, length, *header));
70 ++header->header.sequenceNumber;
71 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
72 EXPECT_EQ(0, receiver_->Process());
73 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(1);
74 EXPECT_EQ(0, receiver_->Decode(0));
77 SimulatedClock clock_;
78 NullEventFactory event_factory_;
80 NiceMock<MockVideoDecoder> decoder_;
81 NiceMock<MockPacketRequestCallback> packet_request_callback_;
83 scoped_ptr<VideoReceiver> receiver_;
86 TEST_F(TestVideoReceiver, PaddingOnlyFrames) {
87 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
89 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
90 const unsigned int kPaddingSize = 220;
91 const uint8_t payload[kPaddingSize] = {0};
92 WebRtcRTPHeader header;
93 memset(&header, 0, sizeof(header));
94 header.frameType = kFrameEmpty;
95 header.header.markerBit = false;
96 header.header.paddingLength = kPaddingSize;
97 header.header.payloadType = kUnusedPayloadType;
98 header.header.ssrc = 1;
99 header.header.headerLength = 12;
100 header.type.Video.codec = kRtpVideoVp8;
101 for (int i = 0; i < 10; ++i) {
102 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
103 InsertAndVerifyPaddingFrame(payload, 0, &header);
104 clock_.AdvanceTimeMilliseconds(33);
105 header.header.timestamp += 3000;
109 TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) {
110 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
112 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
113 const unsigned int kFrameSize = 1200;
114 const unsigned int kPaddingSize = 220;
115 const uint8_t payload[kFrameSize] = {0};
116 WebRtcRTPHeader header;
117 memset(&header, 0, sizeof(header));
118 header.frameType = kFrameEmpty;
119 header.header.markerBit = false;
120 header.header.paddingLength = kPaddingSize;
121 header.header.payloadType = kUnusedPayloadType;
122 header.header.ssrc = 1;
123 header.header.headerLength = 12;
124 header.type.Video.codec = kRtpVideoVp8;
125 // Insert one video frame to get one frame decoded.
126 header.frameType = kVideoFrameKey;
127 header.type.Video.isFirstPacket = true;
128 header.header.markerBit = true;
129 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
130 clock_.AdvanceTimeMilliseconds(33);
131 header.header.timestamp += 3000;
133 header.frameType = kFrameEmpty;
134 header.type.Video.isFirstPacket = false;
135 header.header.markerBit = false;
136 // Insert padding frames.
137 for (int i = 0; i < 10; ++i) {
138 // Lose one packet from the 6th frame.
140 ++header.header.sequenceNumber;
142 // Lose the 4th frame.
144 header.header.sequenceNumber += 5;
146 if (i > 3 && i < 5) {
147 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1);
149 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1);
151 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0);
153 InsertAndVerifyPaddingFrame(payload, 0, &header);
155 clock_.AdvanceTimeMilliseconds(33);
156 header.header.timestamp += 3000;
160 TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) {
161 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true));
163 0, receiver_->RegisterPacketRequestCallback(&packet_request_callback_));
164 const unsigned int kFrameSize = 1200;
165 const unsigned int kPaddingSize = 220;
166 const uint8_t payload[kFrameSize] = {0};
167 WebRtcRTPHeader header;
168 memset(&header, 0, sizeof(header));
169 header.frameType = kFrameEmpty;
170 header.type.Video.isFirstPacket = false;
171 header.header.markerBit = false;
172 header.header.paddingLength = kPaddingSize;
173 header.header.payloadType = kUnusedPayloadType;
174 header.header.ssrc = 1;
175 header.header.headerLength = 12;
176 header.type.Video.codec = kRtpVideoVp8;
177 header.type.Video.codecHeader.VP8.pictureId = -1;
178 header.type.Video.codecHeader.VP8.tl0PicIdx = -1;
179 for (int i = 0; i < 3; ++i) {
180 // Insert 2 video frames.
181 for (int j = 0; j < 2; ++j) {
182 if (i == 0 && j == 0) // First frame should be a key frame.
183 header.frameType = kVideoFrameKey;
185 header.frameType = kVideoFrameDelta;
186 header.type.Video.isFirstPacket = true;
187 header.header.markerBit = true;
188 InsertAndVerifyDecodableFrame(payload, kFrameSize, &header);
189 clock_.AdvanceTimeMilliseconds(33);
190 header.header.timestamp += 3000;
193 // Insert 2 padding only frames.
194 header.frameType = kFrameEmpty;
195 header.type.Video.isFirstPacket = false;
196 header.header.markerBit = false;
197 for (int j = 0; j < 2; ++j) {
198 // InsertAndVerifyPaddingFrame(payload, 0, &header);
199 clock_.AdvanceTimeMilliseconds(33);
200 header.header.timestamp += 3000;
205 TEST_F(TestVideoReceiver, ReceiverDelay) {
206 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(0));
207 EXPECT_EQ(0, receiver_->SetMinReceiverDelay(5000));
208 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(-100));
209 EXPECT_EQ(-1, receiver_->SetMinReceiverDelay(10010));
214 } // namespace webrtc