diff options
Diffstat (limited to 'webrtc/modules/video_coding/video_coding_robustness_unittest.cc')
-rw-r--r-- | webrtc/modules/video_coding/video_coding_robustness_unittest.cc | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/webrtc/modules/video_coding/video_coding_robustness_unittest.cc b/webrtc/modules/video_coding/video_coding_robustness_unittest.cc new file mode 100644 index 0000000000..dd6565d505 --- /dev/null +++ b/webrtc/modules/video_coding/video_coding_robustness_unittest.cc @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h" +#include "webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h" +#include "webrtc/modules/video_coding/include/video_coding.h" +#include "webrtc/modules/video_coding/test/test_util.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { + +using ::testing::Return; +using ::testing::_; +using ::testing::ElementsAre; +using ::testing::AllOf; +using ::testing::Args; +using ::testing::Field; +using ::testing::Pointee; +using ::testing::NiceMock; +using ::testing::Sequence; + +class VCMRobustnessTest : public ::testing::Test { + protected: + static const size_t kPayloadLen = 10; + + virtual void SetUp() { + clock_.reset(new SimulatedClock(0)); + ASSERT_TRUE(clock_.get() != NULL); + vcm_ = VideoCodingModule::Create(clock_.get(), &event_factory_); + ASSERT_TRUE(vcm_ != NULL); + const size_t kMaxNackListSize = 250; + const int kMaxPacketAgeToNack = 450; + vcm_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0); + ASSERT_EQ(0, vcm_->RegisterFrameTypeCallback(&frame_type_callback_)); + ASSERT_EQ(0, vcm_->RegisterPacketRequestCallback(&request_callback_)); + VideoCodingModule::Codec(kVideoCodecVP8, &video_codec_); + ASSERT_EQ(VCM_OK, vcm_->RegisterReceiveCodec(&video_codec_, 1)); + vcm_->RegisterExternalDecoder(&decoder_, video_codec_.plType); + } + + virtual void TearDown() { VideoCodingModule::Destroy(vcm_); } + + void InsertPacket(uint32_t timestamp, + uint16_t seq_no, + bool first, + bool marker_bit, + FrameType frame_type) { + const uint8_t payload[kPayloadLen] = {0}; + WebRtcRTPHeader rtp_info; + memset(&rtp_info, 0, sizeof(rtp_info)); + rtp_info.frameType = frame_type; + rtp_info.header.timestamp = timestamp; + rtp_info.header.sequenceNumber = seq_no; + rtp_info.header.markerBit = marker_bit; + rtp_info.header.payloadType = video_codec_.plType; + rtp_info.type.Video.codec = kRtpVideoVp8; + rtp_info.type.Video.codecHeader.VP8.InitRTPVideoHeaderVP8(); + rtp_info.type.Video.isFirstPacket = first; + + ASSERT_EQ(VCM_OK, vcm_->IncomingPacket(payload, kPayloadLen, rtp_info)); + } + + VideoCodingModule* vcm_; + VideoCodec video_codec_; + MockVCMFrameTypeCallback frame_type_callback_; + MockPacketRequestCallback request_callback_; + NiceMock<MockVideoDecoder> decoder_; + NiceMock<MockVideoDecoder> decoderCopy_; + rtc::scoped_ptr<SimulatedClock> clock_; + NullEventFactory event_factory_; +}; + +TEST_F(VCMRobustnessTest, TestHardNack) { + Sequence s; + EXPECT_CALL(request_callback_, ResendPackets(_, 2)) + .With(Args<0, 1>(ElementsAre(6, 7))) + .Times(1); + for (int ts = 0; ts <= 6000; ts += 3000) { + EXPECT_CALL(decoder_, + Decode(AllOf(Field(&EncodedImage::_timeStamp, ts), + Field(&EncodedImage::_length, kPayloadLen * 3), + Field(&EncodedImage::_completeFrame, true)), + false, _, _, _)) + .Times(1) + .InSequence(s); + } + + ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode( + VideoCodingModule::kHardNack, kNoErrors)); + + InsertPacket(0, 0, true, false, kVideoFrameKey); + InsertPacket(0, 1, false, false, kVideoFrameKey); + InsertPacket(0, 2, false, true, kVideoFrameKey); + clock_->AdvanceTimeMilliseconds(1000 / 30); + + InsertPacket(3000, 3, true, false, kVideoFrameDelta); + InsertPacket(3000, 4, false, false, kVideoFrameDelta); + InsertPacket(3000, 5, false, true, kVideoFrameDelta); + clock_->AdvanceTimeMilliseconds(1000 / 30); + + ASSERT_EQ(VCM_OK, vcm_->Decode(0)); + ASSERT_EQ(VCM_OK, vcm_->Decode(0)); + ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + + clock_->AdvanceTimeMilliseconds(10); + + ASSERT_EQ(VCM_OK, vcm_->Process()); + + ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + + InsertPacket(6000, 8, false, true, kVideoFrameDelta); + clock_->AdvanceTimeMilliseconds(10); + ASSERT_EQ(VCM_OK, vcm_->Process()); + + ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + + InsertPacket(6000, 6, true, false, kVideoFrameDelta); + InsertPacket(6000, 7, false, false, kVideoFrameDelta); + clock_->AdvanceTimeMilliseconds(10); + ASSERT_EQ(VCM_OK, vcm_->Process()); + + ASSERT_EQ(VCM_OK, vcm_->Decode(0)); +} + +TEST_F(VCMRobustnessTest, TestHardNackNoneDecoded) { + EXPECT_CALL(request_callback_, ResendPackets(_, _)).Times(0); + EXPECT_CALL(frame_type_callback_, RequestKeyFrame()).Times(1); + + ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode( + VideoCodingModule::kHardNack, kNoErrors)); + + InsertPacket(3000, 3, true, false, kVideoFrameDelta); + InsertPacket(3000, 4, false, false, kVideoFrameDelta); + InsertPacket(3000, 5, false, true, kVideoFrameDelta); + + EXPECT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + ASSERT_EQ(VCM_OK, vcm_->Process()); + + clock_->AdvanceTimeMilliseconds(10); + + EXPECT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + ASSERT_EQ(VCM_OK, vcm_->Process()); +} + +TEST_F(VCMRobustnessTest, TestModeNoneWithErrors) { + EXPECT_CALL(decoder_, InitDecode(_, _)).Times(1); + EXPECT_CALL(decoder_, Release()).Times(1); + Sequence s1; + EXPECT_CALL(request_callback_, ResendPackets(_, 1)) + .With(Args<0, 1>(ElementsAre(4))) + .Times(0); + + EXPECT_CALL(decoder_, Copy()).Times(0); + EXPECT_CALL(decoderCopy_, Copy()).Times(0); + + // Decode operations + EXPECT_CALL(decoder_, + Decode(AllOf(Field(&EncodedImage::_timeStamp, 0), + Field(&EncodedImage::_completeFrame, true)), + false, _, _, _)) + .Times(1) + .InSequence(s1); + EXPECT_CALL(decoder_, + Decode(AllOf(Field(&EncodedImage::_timeStamp, 3000), + Field(&EncodedImage::_completeFrame, false)), + false, _, _, _)) + .Times(1) + .InSequence(s1); + EXPECT_CALL(decoder_, + Decode(AllOf(Field(&EncodedImage::_timeStamp, 6000), + Field(&EncodedImage::_completeFrame, true)), + false, _, _, _)) + .Times(1) + .InSequence(s1); + EXPECT_CALL(decoder_, + Decode(AllOf(Field(&EncodedImage::_timeStamp, 9000), + Field(&EncodedImage::_completeFrame, true)), + false, _, _, _)) + .Times(1) + .InSequence(s1); + + ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode(VideoCodingModule::kNone, + kWithErrors)); + + InsertPacket(0, 0, true, false, kVideoFrameKey); + InsertPacket(0, 1, false, false, kVideoFrameKey); + InsertPacket(0, 2, false, true, kVideoFrameKey); + EXPECT_EQ(VCM_OK, vcm_->Decode(33)); // Decode timestamp 0. + EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list. + + clock_->AdvanceTimeMilliseconds(33); + InsertPacket(3000, 3, true, false, kVideoFrameDelta); + // Packet 4 missing + InsertPacket(3000, 5, false, true, kVideoFrameDelta); + EXPECT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0)); + EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list. + + clock_->AdvanceTimeMilliseconds(33); + InsertPacket(6000, 6, true, false, kVideoFrameDelta); + InsertPacket(6000, 7, false, false, kVideoFrameDelta); + InsertPacket(6000, 8, false, true, kVideoFrameDelta); + EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 3000 incomplete. + EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list. + + clock_->AdvanceTimeMilliseconds(10); + EXPECT_EQ(VCM_OK, vcm_->Decode(23)); // Decode timestamp 6000 complete. + EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list. + + clock_->AdvanceTimeMilliseconds(23); + InsertPacket(3000, 4, false, false, kVideoFrameDelta); + + InsertPacket(9000, 9, true, false, kVideoFrameDelta); + InsertPacket(9000, 10, false, false, kVideoFrameDelta); + InsertPacket(9000, 11, false, true, kVideoFrameDelta); + EXPECT_EQ(VCM_OK, vcm_->Decode(33)); // Decode timestamp 9000 complete. +} +} // namespace webrtc |