2011-12-21 20:38:37 +00:00
|
|
|
/*
|
2012-02-10 12:13:12 +00:00
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
2011-12-21 20:38:37 +00:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-03-13 08:46:25 +00:00
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
2015-11-18 22:00:21 +01:00
|
|
|
#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"
|
2015-10-28 18:17:40 +01:00
|
|
|
#include "webrtc/system_wrappers/include/clock.h"
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
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() {
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_.reset(new SimulatedClock(0));
|
|
|
|
|
ASSERT_TRUE(clock_.get() != NULL);
|
2016-02-05 11:25:46 +01:00
|
|
|
vcm_.reset(VideoCodingModule::Create(clock_.get(), &event_factory_));
|
2011-12-21 20:38:37 +00:00
|
|
|
ASSERT_TRUE(vcm_ != NULL);
|
2013-02-01 15:09:57 +00:00
|
|
|
const size_t kMaxNackListSize = 250;
|
|
|
|
|
const int kMaxPacketAgeToNack = 450;
|
2013-05-07 19:16:33 +00:00
|
|
|
vcm_->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
|
2011-12-21 20:38:37 +00:00
|
|
|
ASSERT_EQ(0, vcm_->RegisterFrameTypeCallback(&frame_type_callback_));
|
|
|
|
|
ASSERT_EQ(0, vcm_->RegisterPacketRequestCallback(&request_callback_));
|
2016-01-07 15:42:47 +01:00
|
|
|
VideoCodingModule::Codec(kVideoCodecVP8, &video_codec_);
|
2011-12-21 20:38:37 +00:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->RegisterReceiveCodec(&video_codec_, 1));
|
2015-12-10 09:27:38 -08:00
|
|
|
vcm_->RegisterExternalDecoder(&decoder_, video_codec_.plType);
|
2011-12-21 20:38:37 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-05 11:25:46 +01:00
|
|
|
virtual void TearDown() { vcm_.reset(); }
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
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;
|
2013-08-15 23:38:54 +00:00
|
|
|
rtp_info.type.Video.codec = kRtpVideoVp8;
|
2011-12-21 20:38:37 +00:00
|
|
|
rtp_info.type.Video.codecHeader.VP8.InitRTPVideoHeaderVP8();
|
|
|
|
|
rtp_info.type.Video.isFirstPacket = first;
|
|
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->IncomingPacket(payload, kPayloadLen, rtp_info));
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-05 11:25:46 +01:00
|
|
|
rtc::scoped_ptr<VideoCodingModule> vcm_;
|
2011-12-21 20:38:37 +00:00
|
|
|
VideoCodec video_codec_;
|
|
|
|
|
MockVCMFrameTypeCallback frame_type_callback_;
|
|
|
|
|
MockPacketRequestCallback request_callback_;
|
|
|
|
|
NiceMock<MockVideoDecoder> decoder_;
|
|
|
|
|
NiceMock<MockVideoDecoder> decoderCopy_;
|
2015-02-26 14:34:55 +00:00
|
|
|
rtc::scoped_ptr<SimulatedClock> clock_;
|
2013-03-13 08:46:25 +00:00
|
|
|
NullEventFactory event_factory_;
|
2011-12-21 20:38:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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) {
|
2015-12-21 08:23:20 -08:00
|
|
|
EXPECT_CALL(decoder_,
|
|
|
|
|
Decode(AllOf(Field(&EncodedImage::_timeStamp, ts),
|
|
|
|
|
Field(&EncodedImage::_length, kPayloadLen * 3),
|
|
|
|
|
Field(&EncodedImage::_completeFrame, true)),
|
|
|
|
|
false, _, _, _))
|
2011-12-21 20:38:37 +00:00
|
|
|
.Times(1)
|
|
|
|
|
.InSequence(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode(
|
2015-12-21 08:23:20 -08:00
|
|
|
VideoCodingModule::kHardNack, kNoErrors));
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
InsertPacket(0, 0, true, false, kVideoFrameKey);
|
|
|
|
|
InsertPacket(0, 1, false, false, kVideoFrameKey);
|
|
|
|
|
InsertPacket(0, 2, false, true, kVideoFrameKey);
|
2013-05-07 16:36:00 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(1000 / 30);
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
InsertPacket(3000, 3, true, false, kVideoFrameDelta);
|
|
|
|
|
InsertPacket(3000, 4, false, false, kVideoFrameDelta);
|
|
|
|
|
InsertPacket(3000, 5, false, true, kVideoFrameDelta);
|
2013-05-07 16:36:00 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(1000 / 30);
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
|
|
|
|
|
ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
|
|
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(10);
|
2011-12-21 20:38:37 +00:00
|
|
|
|
2016-02-25 04:34:03 -08:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Process());
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
|
|
|
|
|
|
|
|
|
|
InsertPacket(6000, 8, false, true, kVideoFrameDelta);
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(10);
|
2016-02-25 04:34:03 -08:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Process());
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
|
|
|
|
|
|
|
|
|
|
InsertPacket(6000, 6, true, false, kVideoFrameDelta);
|
|
|
|
|
InsertPacket(6000, 7, false, false, kVideoFrameDelta);
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(10);
|
2016-02-25 04:34:03 -08:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Process());
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-12 15:16:49 +00:00
|
|
|
TEST_F(VCMRobustnessTest, TestHardNackNoneDecoded) {
|
2015-12-21 08:23:20 -08:00
|
|
|
EXPECT_CALL(request_callback_, ResendPackets(_, _)).Times(0);
|
|
|
|
|
EXPECT_CALL(frame_type_callback_, RequestKeyFrame()).Times(1);
|
2012-01-12 15:16:49 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode(
|
2015-12-21 08:23:20 -08:00
|
|
|
VideoCodingModule::kHardNack, kNoErrors));
|
2012-01-12 15:16:49 +00:00
|
|
|
|
|
|
|
|
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));
|
2016-02-25 04:34:03 -08:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Process());
|
2012-01-12 15:16:49 +00:00
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(10);
|
2012-01-12 15:16:49 +00:00
|
|
|
|
|
|
|
|
EXPECT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
|
2016-02-25 04:34:03 -08:00
|
|
|
ASSERT_EQ(VCM_OK, vcm_->Process());
|
2012-01-12 15:16:49 +00:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 20:38:37 +00:00
|
|
|
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);
|
|
|
|
|
|
2015-12-21 08:23:20 -08:00
|
|
|
EXPECT_CALL(decoder_, Copy()).Times(0);
|
|
|
|
|
EXPECT_CALL(decoderCopy_, Copy()).Times(0);
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
// Decode operations
|
2015-12-21 08:23:20 -08:00
|
|
|
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));
|
2011-12-21 20:38:37 +00:00
|
|
|
|
|
|
|
|
InsertPacket(0, 0, true, false, kVideoFrameKey);
|
|
|
|
|
InsertPacket(0, 1, false, false, kVideoFrameKey);
|
|
|
|
|
InsertPacket(0, 2, false, true, kVideoFrameKey);
|
2015-12-10 09:27:38 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Decode(33)); // Decode timestamp 0.
|
2016-02-25 04:34:03 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
|
2011-12-21 20:38:37 +00:00
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(33);
|
2011-12-21 20:38:37 +00:00
|
|
|
InsertPacket(3000, 3, true, false, kVideoFrameDelta);
|
|
|
|
|
// Packet 4 missing
|
|
|
|
|
InsertPacket(3000, 5, false, true, kVideoFrameDelta);
|
|
|
|
|
EXPECT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
|
2016-02-25 04:34:03 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
|
2011-12-21 20:38:37 +00:00
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(33);
|
2011-12-21 20:38:37 +00:00
|
|
|
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.
|
2016-02-25 04:34:03 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
|
2011-12-21 20:38:37 +00:00
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(10);
|
2015-12-10 09:27:38 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Decode(23)); // Decode timestamp 6000 complete.
|
2016-02-25 04:34:03 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
|
2011-12-21 20:38:37 +00:00
|
|
|
|
2013-01-21 07:42:11 +00:00
|
|
|
clock_->AdvanceTimeMilliseconds(23);
|
2011-12-21 20:38:37 +00:00
|
|
|
InsertPacket(3000, 4, false, false, kVideoFrameDelta);
|
|
|
|
|
|
|
|
|
|
InsertPacket(9000, 9, true, false, kVideoFrameDelta);
|
|
|
|
|
InsertPacket(9000, 10, false, false, kVideoFrameDelta);
|
|
|
|
|
InsertPacket(9000, 11, false, true, kVideoFrameDelta);
|
2015-12-10 09:27:38 -08:00
|
|
|
EXPECT_EQ(VCM_OK, vcm_->Decode(33)); // Decode timestamp 9000 complete.
|
2011-12-21 20:38:37 +00:00
|
|
|
}
|
|
|
|
|
} // namespace webrtc
|