Add possibility to get the last processed RTT from the call stats class (to be used by RTP/RTCP module).

R=mflodman@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2383004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5139 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
asapersson@webrtc.org 2013-11-20 12:46:11 +00:00
parent 27326b6a42
commit 1ae1d0c471
12 changed files with 115 additions and 59 deletions

View File

@ -63,7 +63,7 @@ class RtpRtcp : public Module {
RtcpFeedback* rtcp_feedback;
RtcpIntraFrameObserver* intra_frame_callback;
RtcpBandwidthObserver* bandwidth_callback;
RtcpRttObserver* rtt_observer;
RtcpRttStats* rtt_stats;
RtpAudioFeedback* audio_messages;
RemoteBitrateEstimator* remote_bitrate_estimator;
PacedSender* paced_sender;

View File

@ -288,11 +288,13 @@ class RtcpBandwidthObserver {
virtual ~RtcpBandwidthObserver() {}
};
class RtcpRttObserver {
class RtcpRttStats {
public:
virtual void OnRttUpdate(uint32_t rtt) = 0;
virtual ~RtcpRttObserver() {};
virtual uint32_t LastProcessedRtt() const = 0;
virtual ~RtcpRttStats() {};
};
// Null object version of RtpFeedback.

View File

@ -39,7 +39,7 @@ RtpRtcp::Configuration::Configuration()
rtcp_feedback(NULL),
intra_frame_callback(NULL),
bandwidth_callback(NULL),
rtt_observer(NULL),
rtt_stats(NULL),
audio_messages(NullObjectRtpAudioFeedback()),
remote_bitrate_estimator(NULL),
paced_sender(NULL) {
@ -92,7 +92,9 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
#ifdef MATLAB
, plot1_(NULL),
#endif
rtt_observer_(configuration.rtt_observer) {
rtt_stats_(configuration.rtt_stats),
critical_section_rtt_(CriticalSectionWrapper::CreateCriticalSection()),
rtt_ms_(0) {
send_video_codec_.codecType = kVideoCodecUnknown;
if (default_module_) {
@ -212,8 +214,8 @@ int32_t ModuleRtpRtcpImpl::Process() {
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
}
// Report the rtt.
if (rtt_observer_ && max_rtt != 0)
rtt_observer_->OnRttUpdate(max_rtt);
if (rtt_stats_ && max_rtt != 0)
rtt_stats_->OnRttUpdate(max_rtt);
}
// Verify receiver reports are delivered and the reported sequence number
@ -240,14 +242,18 @@ int32_t ModuleRtpRtcpImpl::Process() {
// Report rtt from receiver.
if (process_rtt) {
uint16_t rtt_ms;
if (rtt_observer_ && rtcp_receiver_.GetAndResetXrRrRtt(&rtt_ms)) {
rtt_observer_->OnRttUpdate(rtt_ms);
if (rtt_stats_ && rtcp_receiver_.GetAndResetXrRrRtt(&rtt_ms)) {
rtt_stats_->OnRttUpdate(rtt_ms);
}
}
}
// Get processed rtt.
if (process_rtt) {
last_rtt_process_time_ = now;
if (rtt_stats_) {
set_rtt_ms(rtt_stats_->LastProcessedRtt());
}
}
if (rtcp_sender_.TimeToSendRTCPReport()) {
@ -1623,4 +1629,14 @@ void ModuleRtpRtcpImpl::SetRtcpReceiverSsrcs(uint32_t main_ssrc) {
rtcp_receiver_.SetSsrcs(main_ssrc, ssrcs);
}
void ModuleRtpRtcpImpl::set_rtt_ms(uint32_t rtt_ms) {
CriticalSectionScoped cs(critical_section_rtt_.get());
rtt_ms_ = rtt_ms;
}
uint32_t ModuleRtpRtcpImpl::rtt_ms() const {
CriticalSectionScoped cs(critical_section_rtt_.get());
return rtt_ms_;
}
} // Namespace webrtc

View File

@ -19,6 +19,7 @@
#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/testsupport/gtest_prod_util.h"
#ifdef MATLAB
class MatlabPlot;
@ -383,9 +384,13 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
Clock* clock_;
private:
FRIEND_TEST_ALL_PREFIXES(RtpRtcpImplTest, RttForReceiverOnly);
int64_t RtcpReportInterval();
void SetRtcpReceiverSsrcs(uint32_t main_ssrc);
void set_rtt_ms(uint32_t rtt_ms);
uint32_t rtt_ms() const;
int32_t id_;
const bool audio_;
bool collision_detected_;
@ -414,7 +419,11 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
MatlabPlot* plot1_;
#endif
RtcpRttObserver* rtt_observer_;
RtcpRttStats* rtt_stats_;
// The processed RTT from RtcpRttStats.
scoped_ptr<CriticalSectionWrapper> critical_section_rtt_;
uint32_t rtt_ms_;
};
} // namespace webrtc

View File

@ -18,7 +18,7 @@
namespace webrtc {
namespace {
class RtcpRttStatsTestImpl : public RtcpRttObserver {
class RtcpRttStatsTestImpl : public RtcpRttStats {
public:
RtcpRttStatsTestImpl() : rtt_ms_(0) {}
virtual ~RtcpRttStatsTestImpl() {}
@ -26,6 +26,9 @@ class RtcpRttStatsTestImpl : public RtcpRttObserver {
virtual void OnRttUpdate(uint32_t rtt_ms) {
rtt_ms_ = rtt_ms;
}
virtual uint32_t LastProcessedRtt() const {
return rtt_ms_;
}
uint32_t rtt_ms_;
};
@ -70,7 +73,7 @@ class RtpRtcpImplTest : public ::testing::Test {
configuration.clock = &clock_;
configuration.outgoing_transport = &transport_;
configuration.receive_statistics = receive_statistics_.get();
configuration.rtt_observer = &rtt_stats_;
configuration.rtt_stats = &rtt_stats_;
rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
transport_.SetRtpRtcpModule(rtp_rtcp_impl_.get());
@ -136,10 +139,12 @@ TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));
// Verify RTT.
EXPECT_EQ(0U, rtt_stats_.rtt_ms_);
EXPECT_EQ(0U, rtt_stats_.LastProcessedRtt());
EXPECT_EQ(0U, rtp_rtcp_impl_->rtt_ms());
rtp_rtcp_impl_->Process();
EXPECT_EQ(100U, rtt_stats_.rtt_ms_);
EXPECT_EQ(100U, rtt_stats_.LastProcessedRtt());
EXPECT_EQ(100U, rtp_rtcp_impl_->rtt_ms());
}
} // namespace webrtc

View File

@ -24,7 +24,7 @@ const int kRttTimeoutMs = 1500;
// Time interval for updating the observers.
const int kUpdateIntervalMs = 1000;
class RtcpObserver : public RtcpRttObserver {
class RtcpObserver : public RtcpRttStats {
public:
explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
virtual ~RtcpObserver() {}
@ -33,6 +33,10 @@ class RtcpObserver : public RtcpRttObserver {
owner_->OnRttUpdate(rtt);
}
virtual uint32_t LastProcessedRtt() const {
return owner_->last_processed_rtt_ms();
}
private:
CallStats* owner_;
@ -41,8 +45,9 @@ class RtcpObserver : public RtcpRttObserver {
CallStats::CallStats()
: crit_(CriticalSectionWrapper::CreateCriticalSection()),
rtcp_rtt_observer_(new RtcpObserver(this)),
last_process_time_(TickTime::MillisecondTimestamp()) {
rtcp_rtt_stats_(new RtcpObserver(this)),
last_process_time_(TickTime::MillisecondTimestamp()),
last_processed_rtt_ms_(0) {
}
CallStats::~CallStats() {
@ -81,12 +86,18 @@ int32_t CallStats::Process() {
(*it)->OnRttUpdate(max_rtt);
}
}
last_processed_rtt_ms_ = max_rtt;
last_process_time_ = time_now;
return 0;
}
RtcpRttObserver* CallStats::rtcp_rtt_observer() const {
return rtcp_rtt_observer_.get();
uint32_t CallStats::last_processed_rtt_ms() const {
CriticalSectionScoped cs(crit_.get());
return last_processed_rtt_ms_;
}
RtcpRttStats* CallStats::rtcp_rtt_stats() const {
return rtcp_rtt_stats_.get();
}
void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {

View File

@ -19,9 +19,9 @@
namespace webrtc {
class CriticalSectionWrapper;
class RtcpRttObserver;
class CallStatsObserver;
class CriticalSectionWrapper;
class RtcpRttStats;
// CallStats keeps track of statistics for a call.
class CallStats : public Module {
@ -35,9 +35,9 @@ class CallStats : public Module {
virtual int32_t TimeUntilNextProcess();
virtual int32_t Process();
// Returns a RtcpRttObserver to register at a statistics provider. The object
// Returns a RtcpRttStats to register at a statistics provider. The object
// has the same lifetime as the CallStats instance.
RtcpRttObserver* rtcp_rtt_observer() const;
RtcpRttStats* rtcp_rtt_stats() const;
// Registers/deregisters a new observer to receive statistics updates.
void RegisterStatsObserver(CallStatsObserver* observer);
@ -46,6 +46,8 @@ class CallStats : public Module {
protected:
void OnRttUpdate(uint32_t rtt);
uint32_t last_processed_rtt_ms() const;
private:
// Helper struct keeping track of the time a rtt value is reported.
struct RttTime {
@ -58,9 +60,11 @@ class CallStats : public Module {
// Protecting all members.
scoped_ptr<CriticalSectionWrapper> crit_;
// Observer receiving statistics updates.
scoped_ptr<RtcpRttObserver> rtcp_rtt_observer_;
scoped_ptr<RtcpRttStats> rtcp_rtt_stats_;
// The last time 'Process' resulted in statistic update.
int64_t last_process_time_;
// The last RTT in the statistics update (zero if there is no valid estimate).
uint32_t last_processed_rtt_ms_;
// All Rtt reports within valid time interval, oldest first.
std::list<RttTime> reports_;

View File

@ -41,15 +41,24 @@ class CallStatsTest : public ::testing::Test {
TEST_F(CallStatsTest, AddAndTriggerCallback) {
MockStatsObserver stats_observer;
RtcpRttObserver* rtcp_observer = call_stats_->rtcp_rtt_observer();
RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats();
call_stats_->RegisterStatsObserver(&stats_observer);
TickTime::AdvanceFakeClock(1000);
EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt());
uint32_t rtt = 25;
rtcp_observer->OnRttUpdate(rtt);
EXPECT_CALL(stats_observer, OnRttUpdate(rtt))
const uint32_t kRtt = 25;
rtcp_rtt_stats->OnRttUpdate(kRtt);
EXPECT_CALL(stats_observer, OnRttUpdate(kRtt))
.Times(1);
call_stats_->Process();
EXPECT_EQ(kRtt, rtcp_rtt_stats->LastProcessedRtt());
const int kRttTimeOutMs = 1500 + 10;
TickTime::AdvanceFakeClock(kRttTimeOutMs);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(0);
call_stats_->Process();
EXPECT_EQ(0U, rtcp_rtt_stats->LastProcessedRtt());
call_stats_->DeregisterStatsObserver(&stats_observer);
}
@ -57,8 +66,8 @@ TEST_F(CallStatsTest, AddAndTriggerCallback) {
TEST_F(CallStatsTest, ProcessTime) {
MockStatsObserver stats_observer;
call_stats_->RegisterStatsObserver(&stats_observer);
RtcpRttObserver* rtcp_observer = call_stats_->rtcp_rtt_observer();
rtcp_observer->OnRttUpdate(100);
RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats();
rtcp_rtt_stats->OnRttUpdate(100);
// Time isn't updated yet.
EXPECT_CALL(stats_observer, OnRttUpdate(_))
@ -73,7 +82,7 @@ TEST_F(CallStatsTest, ProcessTime) {
// Advance clock just too little to get an update.
TickTime::AdvanceFakeClock(999);
rtcp_observer->OnRttUpdate(100);
rtcp_rtt_stats->OnRttUpdate(100);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(0);
call_stats_->Process();
@ -98,9 +107,9 @@ TEST_F(CallStatsTest, MultipleObservers) {
call_stats_->RegisterStatsObserver(&stats_observer_2);
call_stats_->RegisterStatsObserver(&stats_observer_2);
RtcpRttObserver* rtcp_observer = call_stats_->rtcp_rtt_observer();
RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats();
uint32_t rtt = 100;
rtcp_observer->OnRttUpdate(rtt);
rtcp_rtt_stats->OnRttUpdate(rtt);
// Verify both observers are updated.
TickTime::AdvanceFakeClock(1000);
@ -113,7 +122,7 @@ TEST_F(CallStatsTest, MultipleObservers) {
// Deregister the second observer and verify update is only sent to the first
// observer.
call_stats_->DeregisterStatsObserver(&stats_observer_2);
rtcp_observer->OnRttUpdate(rtt);
rtcp_rtt_stats->OnRttUpdate(rtt);
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt))
.Times(1);
@ -123,7 +132,7 @@ TEST_F(CallStatsTest, MultipleObservers) {
// Deregister the first observer.
call_stats_->DeregisterStatsObserver(&stats_observer_1);
rtcp_observer->OnRttUpdate(rtt);
rtcp_rtt_stats->OnRttUpdate(rtt);
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer_1, OnRttUpdate(rtt))
.Times(0);
@ -136,14 +145,14 @@ TEST_F(CallStatsTest, MultipleObservers) {
TEST_F(CallStatsTest, ChangeRtt) {
MockStatsObserver stats_observer;
call_stats_->RegisterStatsObserver(&stats_observer);
RtcpRttObserver* rtcp_observer = call_stats_->rtcp_rtt_observer();
RtcpRttStats* rtcp_rtt_stats = call_stats_->rtcp_rtt_stats();
// Advance clock to be ready for an update.
TickTime::AdvanceFakeClock(1000);
// Set a first value and verify the callback is triggered.
const uint32_t first_rtt = 100;
rtcp_observer->OnRttUpdate(first_rtt);
rtcp_rtt_stats->OnRttUpdate(first_rtt);
EXPECT_CALL(stats_observer, OnRttUpdate(first_rtt))
.Times(1);
call_stats_->Process();
@ -151,7 +160,7 @@ TEST_F(CallStatsTest, ChangeRtt) {
// Increase rtt and verify the new value is reported.
TickTime::AdvanceFakeClock(1000);
const uint32_t high_rtt = first_rtt + 20;
rtcp_observer->OnRttUpdate(high_rtt);
rtcp_rtt_stats->OnRttUpdate(high_rtt);
EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt))
.Times(1);
call_stats_->Process();
@ -161,13 +170,13 @@ TEST_F(CallStatsTest, ChangeRtt) {
// in the callback.
TickTime::AdvanceFakeClock(1000);
const uint32_t low_rtt = first_rtt - 20;
rtcp_observer->OnRttUpdate(low_rtt);
rtcp_rtt_stats->OnRttUpdate(low_rtt);
EXPECT_CALL(stats_observer, OnRttUpdate(high_rtt))
.Times(1);
call_stats_->Process();
// Advance time to make the high report invalid, the lower rtt should no be in
// the callback.
// Advance time to make the high report invalid, the lower rtt should now be
// in the callback.
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer, OnRttUpdate(low_rtt))
.Times(1);

View File

@ -62,7 +62,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtt_observer,
RtcpRttStats* rtt_stats,
PacedSender* paced_sender,
RtpRtcp* default_rtp_rtcp,
bool sender)
@ -85,7 +85,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
rtp_observer_(NULL),
rtcp_observer_(NULL),
intra_frame_observer_(intra_frame_observer),
rtt_observer_(rtt_observer),
rtt_stats_(rtt_stats),
paced_sender_(paced_sender),
bandwidth_observer_(bandwidth_observer),
send_timestamp_extension_id_(kInvalidRtpExtensionId),
@ -115,7 +115,7 @@ ViEChannel::ViEChannel(int32_t channel_id,
configuration.rtcp_feedback = this;
configuration.intra_frame_callback = intra_frame_observer;
configuration.bandwidth_callback = bandwidth_observer;
configuration.rtt_observer = rtt_observer;
configuration.rtt_stats = rtt_stats;
configuration.remote_bitrate_estimator = remote_bitrate_estimator;
configuration.paced_sender = paced_sender;
configuration.receive_statistics = vie_receiver_.GetReceiveStatistics();
@ -319,7 +319,7 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
configuration.outgoing_transport = &vie_sender_;
configuration.intra_frame_callback = intra_frame_observer_;
configuration.bandwidth_callback = bandwidth_observer_.get();
configuration.rtt_observer = rtt_observer_;
configuration.rtt_stats = rtt_stats_;
configuration.paced_sender = paced_sender_;
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);

View File

@ -37,7 +37,7 @@ class Encryption;
class I420FrameCallback;
class PacedSender;
class ProcessThread;
class RtcpRttObserver;
class RtcpRttStats;
class RtpRtcp;
class ThreadWrapper;
class ViEDecoderObserver;
@ -69,7 +69,7 @@ class ViEChannel
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtt_observer,
RtcpRttStats* rtt_stats,
PacedSender* paced_sender,
RtpRtcp* default_rtp_rtcp,
bool sender);
@ -370,7 +370,7 @@ class ViEChannel
ViERTPObserver* rtp_observer_;
ViERTCPObserver* rtcp_observer_;
RtcpIntraFrameObserver* intra_frame_observer_;
RtcpRttObserver* rtt_observer_;
RtcpRttStats* rtt_stats_;
PacedSender* paced_sender_;
scoped_ptr<RtcpBandwidthObserver> bandwidth_observer_;

View File

@ -104,12 +104,12 @@ int ViEChannelManager::CreateChannel(int* channel_id) {
group->GetRemoteBitrateEstimator();
EncoderStateFeedback* encoder_state_feedback =
group->GetEncoderStateFeedback();
RtcpRttObserver* rtcp_rtt_observer =
group->GetCallStats()->rtcp_rtt_observer();
RtcpRttStats* rtcp_rtt_stats =
group->GetCallStats()->rtcp_rtt_stats();
if (!(vie_encoder->Init() &&
CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
remote_bitrate_estimator, rtcp_rtt_observer,
remote_bitrate_estimator, rtcp_rtt_stats,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
true))) {
delete vie_encoder;
@ -156,8 +156,8 @@ int ViEChannelManager::CreateChannel(int* channel_id,
channel_group->GetRemoteBitrateEstimator();
EncoderStateFeedback* encoder_state_feedback =
channel_group->GetEncoderStateFeedback();
RtcpRttObserver* rtcp_rtt_observer =
channel_group->GetCallStats()->rtcp_rtt_observer();
RtcpRttStats* rtcp_rtt_stats =
channel_group->GetCallStats()->rtcp_rtt_stats();
ViEEncoder* vie_encoder = NULL;
if (sender) {
@ -172,7 +172,7 @@ int ViEChannelManager::CreateChannel(int* channel_id,
vie_encoder,
bandwidth_observer,
remote_bitrate_estimator,
rtcp_rtt_observer,
rtcp_rtt_stats,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
sender))) {
delete vie_encoder;
@ -191,7 +191,7 @@ int ViEChannelManager::CreateChannel(int* channel_id,
vie_encoder,
bandwidth_observer,
remote_bitrate_estimator,
rtcp_rtt_observer,
rtcp_rtt_stats,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
sender)) {
vie_encoder = NULL;
@ -421,7 +421,7 @@ bool ViEChannelManager::CreateChannelObject(
ViEEncoder* vie_encoder,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtcp_rtt_observer,
RtcpRttStats* rtcp_rtt_stats,
RtcpIntraFrameObserver* intra_frame_observer,
bool sender) {
PacedSender* paced_sender = vie_encoder->GetPacedSender();
@ -436,7 +436,7 @@ bool ViEChannelManager::CreateChannelObject(
intra_frame_observer,
bandwidth_observer,
remote_bitrate_estimator,
rtcp_rtt_observer,
rtcp_rtt_stats,
paced_sender,
send_rtp_rtcp_module,
sender);

View File

@ -28,7 +28,7 @@ namespace webrtc {
class Config;
class CriticalSectionWrapper;
class ProcessThread;
class RtcpRttObserver;
class RtcpRttStats;
class ViEChannel;
class ViEEncoder;
class VoEVideoSync;
@ -89,7 +89,7 @@ class ViEChannelManager: private ViEManagerBase {
ViEEncoder* vie_encoder,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtcp_rtt_observer,
RtcpRttStats* rtcp_rtt_stats,
RtcpIntraFrameObserver* intra_frame_observer,
bool sender);