aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/video_coding/video_coding_robustness_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/video_coding/video_coding_robustness_unittest.cc')
-rw-r--r--webrtc/modules/video_coding/video_coding_robustness_unittest.cc226
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