1 /* 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" 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" 21 22 using ::testing::_; 23 using ::testing::NiceMock; 24 25 namespace webrtc { 26 namespace vcm { 27 namespace { 28 29 class TestVideoReceiver : public ::testing::Test { 30 protected: 31 static const int kUnusedPayloadType = 10; 32 33 TestVideoReceiver() : clock_(0) {} 34 35 virtual void SetUp() { 36 receiver_.reset(new VideoReceiver(&clock_, &event_factory_)); 37 EXPECT_EQ(0, receiver_->InitializeReceiver()); 38 EXPECT_EQ(0, 39 receiver_->RegisterExternalDecoder( 40 &decoder_, kUnusedPayloadType, true)); 41 const size_t kMaxNackListSize = 250; 42 const int kMaxPacketAgeToNack = 450; 43 receiver_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0); 44 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)); 49 } 50 51 void InsertAndVerifyPaddingFrame(const uint8_t* payload, 52 int length, 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; 59 } 60 EXPECT_EQ(0, receiver_->Process()); 61 EXPECT_CALL(decoder_, Decode(_, _, _, _, _)).Times(0); 62 EXPECT_EQ(VCM_FRAME_NOT_READY, receiver_->Decode(0)); 63 } 64 65 void InsertAndVerifyDecodableFrame(const uint8_t* payload, 66 int length, 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)); 75 } 76 77 SimulatedClock clock_; 78 NullEventFactory event_factory_; 79 VideoCodec settings_; 80 NiceMock<MockVideoDecoder> decoder_; 81 NiceMock<MockPacketRequestCallback> packet_request_callback_; 82 83 scoped_ptr<VideoReceiver> receiver_; 84 }; 85 86 TEST_F(TestVideoReceiver, PaddingOnlyFrames) { 87 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true)); 88 EXPECT_EQ( 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; 106 } 107 } 108 109 TEST_F(TestVideoReceiver, PaddingOnlyFramesWithLosses) { 110 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true)); 111 EXPECT_EQ( 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; 132 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. 139 if (i == 5) { 140 ++header.header.sequenceNumber; 141 } 142 // Lose the 4th frame. 143 if (i == 3) { 144 header.header.sequenceNumber += 5; 145 } else { 146 if (i > 3 && i < 5) { 147 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 5)).Times(1); 148 } else if (i >= 5) { 149 EXPECT_CALL(packet_request_callback_, ResendPackets(_, 6)).Times(1); 150 } else { 151 EXPECT_CALL(packet_request_callback_, ResendPackets(_, _)).Times(0); 152 } 153 InsertAndVerifyPaddingFrame(payload, 0, &header); 154 } 155 clock_.AdvanceTimeMilliseconds(33); 156 header.header.timestamp += 3000; 157 } 158 } 159 160 TEST_F(TestVideoReceiver, PaddingOnlyAndVideo) { 161 EXPECT_EQ(0, receiver_->SetVideoProtection(kProtectionNack, true)); 162 EXPECT_EQ( 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; 184 else 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; 191 } 192 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; 201 } 202 } 203 } 204 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)); 210 } 211 212 } // namespace 213 } // namespace vcm 214 } // namespace webrtc 215