
Trying to submit all changes at once proved impossible since there were too many changes in too many files. The changes to PRESUBMIT.py will be uploaded in the last CL. (original CL: https://codereview.webrtc.org/1528503003/) BUG=webrtc:5309 TBR=mflodman@webrtc.org Review URL: https://codereview.webrtc.org/1540243002 Cr-Commit-Position: refs/heads/master@{#11105}
227 lines
8.3 KiB
C++
227 lines
8.3 KiB
C++
/*
|
|
* 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_));
|
|
ASSERT_EQ(VCM_OK, vcm_->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
|