New VCM robustness API

This CL defines and starts to implement a new robustness API for
video coding module. The API is partly implemented. Some of the
modes and methods are still TBD.

Also including a new unittest with mocking of decoder and callbacks,
and faking of system clock.

Review URL: http://webrtc-codereview.appspot.com/333006

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1276 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrik.lundin@webrtc.org 2011-12-21 20:38:37 +00:00
parent 697bc43b67
commit 4a19030131
7 changed files with 582 additions and 0 deletions

View File

@ -14,6 +14,7 @@
#include <string>
#include "gmock/gmock.h"
#include "modules/video_coding/codecs/interface/video_codec_interface.h"
#include "typedefs.h"
namespace webrtc {

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2011 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.
*/
#ifndef WEBRTC_MODULES_VIDEO_CODING_MAIN_INTERFACE_MOCK_MOCK_VCM_CALLBACKS_H_
#define WEBRTC_MODULES_VIDEO_CODING_MAIN_INTERFACE_MOCK_MOCK_VCM_CALLBACKS_H_
#include "gmock/gmock.h"
#include "typedefs.h"
namespace webrtc {
class MockVCMFrameTypeCallback : public VCMFrameTypeCallback {
public:
MOCK_METHOD1(FrameTypeRequest, int32_t(const FrameType frameType));
MOCK_METHOD1(SliceLossIndicationRequest,
WebRtc_Word32(const WebRtc_UWord64 pictureId));
};
class MockPacketRequestCallback : public VCMPacketRequestCallback {
public:
MOCK_METHOD2(ResendPackets, int32_t(const uint16_t* sequenceNumbers,
uint16_t length));
};
} // namespace webrtc
#endif // WEBRTC_MODULES_VIDEO_CODING_MAIN_INTERFACE_MOCK_MOCK_VCM_CALLBACKS_H_

View File

@ -26,6 +26,25 @@ struct CodecSpecificInfo;
class VideoCodingModule : public Module
{
public:
enum SenderNackMode {
kNackNone,
kNackAll,
kNackSelective
};
enum ReceiverRobustness {
kNone,
kHardNack,
kSoftNack,
kDualDecoder,
kReferenceSelection
};
enum DecodeErrors {
kNoDecodeErrors,
kAllowDecodeErrors
};
static VideoCodingModule* Create(const WebRtc_Word32 id);
static VideoCodingModule* Create(const WebRtc_Word32 id,
@ -501,6 +520,57 @@ public:
// frame was sent to the decoder. Therefore packets which were prematurely
// NACKed will be counted.
virtual WebRtc_UWord32 DiscardedPackets() const = 0;
// Robustness APIs
// Set the sender RTX/NACK mode.
// Input:
// - mode : the selected NACK mode.
//
// Return value : VCM_OK, on success;
// < 0, on error.
virtual int SetSenderNackMode(SenderNackMode mode) = 0;
// Set the sender reference picture selection (RPS) mode.
// Input:
// - enable : true or false, for enable and disable, respectively.
//
// Return value : VCM_OK, on success;
// < 0, on error.
virtual int SetSenderReferenceSelection(bool enable) = 0;
// Set the sender forward error correction (FEC) mode.
// Input:
// - enable : true or false, for enable and disable, respectively.
//
// Return value : VCM_OK, on success;
// < 0, on error.
virtual int SetSenderFEC(bool enable) = 0;
// Set the key frame period, or disable periodic key frames (I-frames).
// Input:
// - periodMs : period in ms; <= 0 to disable periodic key frames.
//
// Return value : VCM_OK, on success;
// < 0, on error.
virtual int SetSenderKeyFramePeriod(int periodMs) = 0;
// Set the receiver robustness mode. The mode decides how the receiver
// responds to losses in the stream. The type of counter-measure (soft or
// hard NACK, dual decoder, RPS, etc.) is selected through the
// robustnessMode parameter. The errorMode parameter decides if it is
// allowed to display frames corrupted by losses. Note that not all
// combinations of the two parameters are feasible. An error will be
// returned for invalid combinations.
// Input:
// - robustnessMode : selected robustness mode.
// - errorMode : selected error mode.
//
// Return value : VCM_OK, on success;
// < 0, on error.
virtual int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
DecodeErrors errorMode) = 0;
};
} // namespace webrtc

View File

@ -1578,4 +1578,85 @@ WebRtc_UWord32 VideoCodingModuleImpl::DiscardedPackets() const {
return _receiver.DiscardedPackets();
}
int VideoCodingModuleImpl::SetSenderNackMode(SenderNackMode mode) {
CriticalSectionScoped cs(_sendCritSect);
switch (mode) {
case kNackNone:
_mediaOpt.EnableProtectionMethod(false, kNack);
break;
case kNackAll:
_mediaOpt.EnableProtectionMethod(true, kNack);
break;
case kNackSelective:
return VCM_NOT_IMPLEMENTED;
break;
}
return VCM_OK;
}
int VideoCodingModuleImpl::SetSenderReferenceSelection(bool enable) {
return VCM_NOT_IMPLEMENTED;
}
int VideoCodingModuleImpl::SetSenderFEC(bool enable) {
CriticalSectionScoped cs(_sendCritSect);
_mediaOpt.EnableProtectionMethod(enable, kFec);
return VCM_OK;
}
int VideoCodingModuleImpl::SetSenderKeyFramePeriod(int periodMs) {
return VCM_NOT_IMPLEMENTED;
}
int VideoCodingModuleImpl::SetReceiverRobustnessMode(
ReceiverRobustness robustnessMode,
DecodeErrors errorMode) {
CriticalSectionScoped cs(_receiveCritSect);
switch (robustnessMode) {
case kNone:
_receiver.SetNackMode(kNoNack);
_dualReceiver.SetNackMode(kNoNack);
if (errorMode == kNoDecodeErrors) {
_keyRequestMode = kKeyOnLoss;
} else {
_keyRequestMode = kKeyOnError;
}
break;
case kHardNack:
if (errorMode == kAllowDecodeErrors) {
return VCM_PARAMETER_ERROR;
}
_receiver.SetNackMode(kNackInfinite);
_dualReceiver.SetNackMode(kNoNack);
_keyRequestMode = kKeyOnError; // TODO(hlundin): On long NACK list?
break;
case kSoftNack:
assert(false); // TODO(hlundin): Not completed.
return VCM_NOT_IMPLEMENTED;
_receiver.SetNackMode(kNackHybrid);
_dualReceiver.SetNackMode(kNoNack);
_keyRequestMode = kKeyOnError;
break;
case kDualDecoder:
if (errorMode == kNoDecodeErrors) {
return VCM_PARAMETER_ERROR;
}
_receiver.SetNackMode(kNoNack);
_dualReceiver.SetNackMode(kNackInfinite);
_keyRequestMode = kKeyOnError;
break;
case kReferenceSelection:
assert(false); // TODO(hlundin): Not completed.
return VCM_NOT_IMPLEMENTED;
if (errorMode == kNoDecodeErrors) {
return VCM_PARAMETER_ERROR;
}
_receiver.SetNackMode(kNoNack);
_dualReceiver.SetNackMode(kNoNack);
break;
}
return VCM_OK;
}
} // namespace webrtc

View File

@ -256,6 +256,25 @@ public:
// Returns the number of packets discarded by the jitter buffer.
virtual WebRtc_UWord32 DiscardedPackets() const;
// Robustness APIs
// Set the sender RTX/NACK mode.
virtual int SetSenderNackMode(SenderNackMode mode);
// Set the sender reference picture selection (RPS) mode.
virtual int SetSenderReferenceSelection(bool enable);
// Set the sender forward error correction (FEC) mode.
virtual int SetSenderFEC(bool enable);
// Set the key frame period, or disable periodic key frames (I-frames).
virtual int SetSenderKeyFramePeriod(int periodMs);
// Set the receiver robustness mode.
virtual int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
DecodeErrors errorMode);
protected:
WebRtc_Word32 Decode(const webrtc::VCMEncodedFrame& frame);
WebRtc_Word32 RequestKeyFrame();

View File

@ -0,0 +1,373 @@
/*
* Copyright (c) 2011 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 "gmock/gmock.h"
#include "gtest/gtest.h"
#include "modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h"
#include "modules/video_coding/main/interface/video_coding.h"
#include "modules/video_coding/main/interface/mock/mock_vcm_callbacks.h"
#include "modules/video_coding/main/source/mock/fake_tick_time.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_ = new FakeTickTime(0);
ASSERT_TRUE(clock_ != NULL);
vcm_ = VideoCodingModule::Create(0, clock_);
ASSERT_TRUE(vcm_ != NULL);
ASSERT_EQ(0, vcm_->InitializeReceiver());
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));
ASSERT_EQ(VCM_OK, vcm_->RegisterExternalDecoder(&decoder_,
video_codec_.plType,
true));
}
virtual void TearDown() {
VideoCodingModule::Destroy(vcm_);
delete clock_;
}
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_;
FakeTickTime* clock_;
};
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,
VideoCodingModule::kNoDecodeErrors));
InsertPacket(0, 0, true, false, kVideoFrameKey);
InsertPacket(0, 1, false, false, kVideoFrameKey);
InsertPacket(0, 2, false, true, kVideoFrameKey);
InsertPacket(3000, 3, true, false, kVideoFrameDelta);
InsertPacket(3000, 4, false, false, kVideoFrameDelta);
InsertPacket(3000, 5, false, true, kVideoFrameDelta);
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
clock_->IncrementDebugClock(10);
ASSERT_EQ(VCM_OK, vcm_->Process());
ASSERT_EQ(VCM_FRAME_NOT_READY, vcm_->Decode(0));
InsertPacket(6000, 8, false, true, kVideoFrameDelta);
clock_->IncrementDebugClock(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_->IncrementDebugClock(10);
ASSERT_EQ(VCM_OK, vcm_->Process());
ASSERT_EQ(VCM_OK, vcm_->Decode(0));
}
TEST_F(VCMRobustnessTest, TestDualDecoder) {
Sequence s1, s2;
EXPECT_CALL(request_callback_, ResendPackets(_, 1))
.With(Args<0, 1>(ElementsAre(4)))
.Times(1);
EXPECT_CALL(decoder_, Copy())
.Times(1)
.WillOnce(Return(&decoderCopy_));
EXPECT_CALL(decoderCopy_, Copy())
.Times(1)
.WillOnce(Return(&decoder_));
// 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);
EXPECT_CALL(decoderCopy_, Decode(AllOf(Field(&EncodedImage::_timeStamp, 3000),
Field(&EncodedImage::_completeFrame,
true)),
false, _, _, _))
.Times(1)
.InSequence(s2);
EXPECT_CALL(decoderCopy_, Decode(AllOf(Field(&EncodedImage::_timeStamp, 6000),
Field(&EncodedImage::_completeFrame,
true)),
false, _, _, _))
.Times(1)
.InSequence(s2);
ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode(
VideoCodingModule::kDualDecoder,
VideoCodingModule::kAllowDecodeErrors));
InsertPacket(0, 0, true, false, kVideoFrameKey);
InsertPacket(0, 1, false, false, kVideoFrameKey);
InsertPacket(0, 2, false, true, kVideoFrameKey);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 0.
clock_->IncrementDebugClock(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));
clock_->IncrementDebugClock(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.
// Spawn a decoder copy.
EXPECT_EQ(0, vcm_->DecodeDualFrame(0)); // Expect no dual decoder action.
clock_->IncrementDebugClock(10);
EXPECT_EQ(VCM_OK, vcm_->Process()); // Generate NACK list.
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 6000 complete.
EXPECT_EQ(0, vcm_->DecodeDualFrame(0)); // Expect no dual decoder action.
InsertPacket(3000, 4, false, false, kVideoFrameDelta);
EXPECT_EQ(1, vcm_->DecodeDualFrame(0)); // Dual decode of timestamp 3000.
EXPECT_EQ(1, vcm_->DecodeDualFrame(0)); // Dual decode of timestamp 6000.
EXPECT_EQ(0, vcm_->DecodeDualFrame(0)); // No more frames.
InsertPacket(9000, 9, true, false, kVideoFrameDelta);
InsertPacket(9000, 10, false, false, kVideoFrameDelta);
InsertPacket(9000, 11, false, true, kVideoFrameDelta);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 9000 complete.
EXPECT_EQ(0, vcm_->DecodeDualFrame(0)); // Expect no dual decoder action.
}
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,
VideoCodingModule::kAllowDecodeErrors));
InsertPacket(0, 0, true, false, kVideoFrameKey);
InsertPacket(0, 1, false, false, kVideoFrameKey);
InsertPacket(0, 2, false, true, kVideoFrameKey);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 0.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
clock_->IncrementDebugClock(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_->IncrementDebugClock(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_->IncrementDebugClock(10);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 6000 complete.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
clock_->IncrementDebugClock(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(0)); // Decode timestamp 9000 complete.
}
TEST_F(VCMRobustnessTest, TestModeNoneWithoutErrors) {
Sequence s1;
EXPECT_CALL(decoder_, InitDecode(_, _)).Times(1);
EXPECT_CALL(decoder_, Release()).Times(1);
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(frame_type_callback_, FrameTypeRequest(kVideoFrameKey))
.Times(1);
ASSERT_EQ(VCM_OK, vcm_->SetReceiverRobustnessMode(
VideoCodingModule::kNone,
VideoCodingModule::kNoDecodeErrors));
InsertPacket(0, 0, true, false, kVideoFrameKey);
InsertPacket(0, 1, false, false, kVideoFrameKey);
InsertPacket(0, 2, false, true, kVideoFrameKey);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 0.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
clock_->IncrementDebugClock(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_->IncrementDebugClock(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.
// Schedule key frame request.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
clock_->IncrementDebugClock(10);
EXPECT_EQ(VCM_OK, vcm_->Decode(0)); // Decode timestamp 6000 complete.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect no NACK list.
clock_->IncrementDebugClock(500); // Wait for the key request timer to set.
EXPECT_EQ(VCM_OK, vcm_->Process()); // Expect key frame request.
}
} // namespace webrtc

View File

@ -69,13 +69,17 @@
'webrtc_video_coding',
'<(webrtc_root)/../test/test.gyp:test_support_main',
'<(webrtc_root)/../testing/gtest.gyp:gtest',
'<(webrtc_root)/../testing/gmock.gyp:gmock',
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
],
'include_dirs': [
'../../../interface',
'../../codecs/interface',
],
'sources': [
'../interface/mock/mock_vcm_callbacks.h',
'session_info_unittest.cc',
'video_coding_robustness_unittest.cc',
],
},
],