Wire up CallStats to provide modules with correct RTT.

BUG=769
TEST=Manual test since there is no ViE APi to get RTT for receive channels.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3163 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mflodman@webrtc.org 2012-11-26 12:40:15 +00:00
parent 5ba3decc94
commit 7c894b7cc7
11 changed files with 123 additions and 42 deletions

View File

@ -37,6 +37,7 @@ class RtpRtcp : public Module {
rtcp_feedback(NULL),
intra_frame_callback(NULL),
bandwidth_callback(NULL),
rtt_observer(NULL),
audio_messages(NULL),
remote_bitrate_estimator(NULL),
paced_sender(NULL) {
@ -53,7 +54,7 @@ class RtpRtcp : public Module {
* outgoing_transport - Transport object that will be called when packets
* are ready to be sent out on the network
* rtcp_feedback - Callback object that will receive the incoming
* RTP messages.
* RTCP messages.
* intra_frame_callback - Called when the receiver request a intra frame.
* bandwidth_callback - Called when we receive a changed estimate from
* the receiver of out stream.
@ -73,6 +74,7 @@ class RtpRtcp : public Module {
RtcpFeedback* rtcp_feedback;
RtcpIntraFrameObserver* intra_frame_callback;
RtcpBandwidthObserver* bandwidth_callback;
RtcpRttObserver* rtt_observer;
RtpAudioFeedback* audio_messages;
RemoteBitrateEstimator* remote_bitrate_estimator;
PacedSender* paced_sender;
@ -593,6 +595,12 @@ class RtpRtcp : public Module {
*/
virtual WebRtc_Word32 ResetRTT(const WebRtc_UWord32 remoteSSRC)= 0 ;
/*
* Sets the estimated RTT, to be used for receive only modules without
* possibility of calculating its own RTT.
*/
virtual void SetRtt(uint32_t rtt) = 0;
/*
* Force a send of a RTCP packet
* normal SR and RR are triggered via the process function

View File

@ -184,6 +184,7 @@ class MockRtpRtcp : public RtpRtcp {
WebRtc_Word32(const WebRtc_UWord32 remoteSSRC, WebRtc_UWord16* RTT, WebRtc_UWord16* avgRTT, WebRtc_UWord16* minRTT, WebRtc_UWord16* maxRTT));
MOCK_METHOD1(ResetRTT,
WebRtc_Word32(const WebRtc_UWord32 remoteSSRC));
MOCK_METHOD1(SetRtt, void(uint32_t rtt));
MOCK_METHOD1(SendRTCP,
WebRtc_Word32(WebRtc_UWord32 rtcpPacketType));
MOCK_METHOD1(SendRTCPReferencePictureSelection,

View File

@ -86,7 +86,8 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
_nackLastSeqNumberSent(0),
_simulcast(false),
_keyFrameReqMethod(kKeyFrameReqFirRtp),
remote_bitrate_(configuration.remote_bitrate_estimator)
remote_bitrate_(configuration.remote_bitrate_estimator),
rtt_observer_(configuration.rtt_observer)
#ifdef MATLAB
, _plot1(NULL)
#endif
@ -211,21 +212,23 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin();
it != receive_blocks.end(); ++it) {
WebRtc_UWord16 rtt = 0;
_rtcpReceiver.RTT(it->remoteSSRC, &max_rtt, NULL, NULL, NULL);
_rtcpReceiver.RTT(it->remoteSSRC, &rtt, NULL, NULL, NULL);
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
}
// Report the rtt.
if (rtt_observer_ && max_rtt != 0)
rtt_observer_->OnRttUpdate(max_rtt);
} else {
// We're only receiving, i.e. this module doesn't have its own RTT
// estimate. Use the RTT set by a sending channel using the same default
// module.
// No valid RTT estimate, probably since this is a receive only channel.
// Use an estimate set by a send module.
max_rtt = _rtcpReceiver.RTT();
}
if (max_rtt == 0) {
// No valid estimate available, i.e. no sending channel using the same
// default module or no RTCP received yet.
// No own rtt calculation or set rtt, use default value.
max_rtt = kDefaultRtt;
}
if (remote_bitrate_) {
// TODO(mflodman) Remove this and let this be propagated by CallStats.
remote_bitrate_->SetRtt(max_rtt);
remote_bitrate_->UpdateEstimate(_rtpReceiver.SSRC(), now);
if (TMMBR()) {
@ -1143,6 +1146,11 @@ ModuleRtpRtcpImpl::ResetRTT(const WebRtc_UWord32 remoteSSRC) {
return _rtcpReceiver.ResetRTT(remoteSSRC);
}
void ModuleRtpRtcpImpl:: SetRtt(uint32_t rtt) {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRtt(rtt: %u)", rtt);
_rtcpReceiver.SetRTT(static_cast<WebRtc_UWord16>(rtt));
}
// Reset RTP statistics
WebRtc_Word32
ModuleRtpRtcpImpl::ResetStatisticsRTP() {

View File

@ -225,6 +225,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// Reset RoundTripTime statistics
virtual WebRtc_Word32 ResetRTT(const WebRtc_UWord32 remoteSSRC);
virtual void SetRtt(uint32_t rtt);
// Force a send of an RTCP packet
// normal SR and RR are triggered via the process function
virtual WebRtc_Word32 SendRTCP(WebRtc_UWord32 rtcpPacketType = kRtcpReport);
@ -509,6 +511,8 @@ private:
RemoteBitrateEstimator* remote_bitrate_;
RtcpRttObserver* rtt_observer_;
#ifdef MATLAB
MatlabPlot* _plot1;
#endif

View File

@ -25,6 +25,9 @@
namespace webrtc {
// Use this rtt if no value has been reported.
static uint32_t kDefaultRtt = 200;
// Predicates used when searching for frames in the frame buffer list
class FrameSmallerTimestamp {
public:
@ -88,7 +91,7 @@ VCMJitterBuffer::VCMJitterBuffer(TickTimeBase* clock,
num_discarded_packets_(0),
jitter_estimate_(vcm_id, receiver_id),
inter_frame_delay_(clock_->MillisecondTimestamp()),
rtt_ms_(0),
rtt_ms_(kDefaultRtt),
nack_mode_(kNoNack),
low_rtt_nack_threshold_ms_(-1),
high_rtt_nack_threshold_ms_(-1),
@ -190,7 +193,7 @@ void VCMJitterBuffer::Start() {
first_packet_ = true;
nack_seq_nums_length_ = 0;
waiting_for_key_frame_ = false;
rtt_ms_ = 0;
rtt_ms_ = kDefaultRtt;
num_not_decodable_packets_ = 0;
WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding,
@ -796,6 +799,11 @@ void VCMJitterBuffer::SetNackMode(VCMNackMode mode,
assert(low_rtt_nack_threshold_ms > -1 || high_rtt_nack_threshold_ms == -1);
low_rtt_nack_threshold_ms_ = low_rtt_nack_threshold_ms;
high_rtt_nack_threshold_ms_ = high_rtt_nack_threshold_ms;
// Don't set a high start rtt if high_rtt_nack_threshold_ms_ is used, to not
// disable NACK in hybrid mode.
if (rtt_ms_ == kDefaultRtt && high_rtt_nack_threshold_ms_ != -1) {
rtt_ms_ = 0;
}
if (nack_mode_ == kNoNack) {
jitter_estimate_.ResetNackCount();
}

View File

@ -24,6 +24,7 @@
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/thread_wrapper.h"
#include "system_wrappers/interface/trace.h"
#include "video_engine/call_stats.h"
#include "video_engine/include/vie_codec.h"
#include "video_engine/include/vie_errors.h"
#include "video_engine/include/vie_image_process.h"
@ -35,6 +36,21 @@ namespace webrtc {
const int kMaxDecodeWaitTimeMs = 50;
const int kInvalidRtpExtensionId = 0;
// Helper class receiving statistics callbacks.
class ChannelStatsObserver : public StatsObserver {
public:
explicit ChannelStatsObserver(ViEChannel* owner) : owner_(owner) {}
virtual ~ChannelStatsObserver() {}
// Implements StatsObserver.
virtual void OnRttUpdate(uint32_t rtt) {
owner_->OnRttUpdate(rtt);
}
private:
ViEChannel* owner_;
};
ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
WebRtc_Word32 engine_id,
WebRtc_UWord32 number_of_cores,
@ -42,6 +58,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtt_observer,
PacedSender* paced_sender,
RtpRtcp* default_rtp_rtcp,
bool sender)
@ -62,6 +79,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
vie_receiver_(channel_id, &vcm_, remote_bitrate_estimator),
vie_sender_(channel_id),
vie_sync_(&vcm_, this),
stats_observer_(new ChannelStatsObserver(this)),
module_process_thread_(module_process_thread),
codec_observer_(NULL),
do_key_frame_callbackRequest_(false),
@ -69,6 +87,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
rtcp_observer_(NULL),
networkObserver_(NULL),
intra_frame_observer_(intra_frame_observer),
rtt_observer_(rtt_observer),
paced_sender_(paced_sender),
bandwidth_observer_(bandwidth_observer),
rtp_packet_timeout_(false),
@ -81,7 +100,6 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
external_encryption_(NULL),
effect_filter_(NULL),
color_enhancement_(false),
vcm_rttreported_(TickTime::Now()),
file_recorder_(channel_id),
mtu_(0),
sender_(sender) {
@ -99,6 +117,7 @@ ViEChannel::ViEChannel(WebRtc_Word32 channel_id,
configuration.rtcp_feedback = this;
configuration.intra_frame_callback = intra_frame_observer;
configuration.bandwidth_callback = bandwidth_observer;
configuration.rtt_observer = rtt_observer;
configuration.remote_bitrate_estimator = remote_bitrate_estimator;
configuration.paced_sender = paced_sender;
@ -262,6 +281,7 @@ WebRtc_Word32 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.paced_sender = paced_sender_;
RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
@ -2078,6 +2098,10 @@ RtpRtcp* ViEChannel::rtp_rtcp() {
return rtp_rtcp_.get();
}
StatsObserver* ViEChannel::GetStatsObserver() {
return stats_observer_.get();
}
WebRtc_Word32 ViEChannel::FrameToRender(
I420VideoFrame& video_frame) { // NOLINT
CriticalSectionScoped cs(callback_cs_.get());
@ -2182,30 +2206,16 @@ bool ViEChannel::ChannelDecodeThreadFunction(void* obj) {
}
bool ViEChannel::ChannelDecodeProcess() {
// Decode is blocking, but sleep some time anyway to not get a spin.
vcm_.Decode(kMaxDecodeWaitTimeMs);
if ((TickTime::Now() - vcm_rttreported_).Milliseconds() > 1000) {
WebRtc_UWord16 RTT;
WebRtc_UWord16 avgRTT;
WebRtc_UWord16 minRTT;
WebRtc_UWord16 maxRTT;
if (rtp_rtcp_->RTT(rtp_rtcp_->RemoteSSRC(), &RTT, &avgRTT, &minRTT, &maxRTT)
== 0) {
vcm_.SetReceiveChannelParameters(RTT);
vcm_rttreported_ = TickTime::Now();
} else if (!rtp_rtcp_->Sending() &&
(TickTime::Now() - vcm_rttreported_).Milliseconds() > 5000) {
// Wait at least 5 seconds before faking a 200 ms RTT. This is to
// make sure we have a chance to start sending before we decide to fake.
vcm_.SetReceiveChannelParameters(200);
vcm_rttreported_ = TickTime::Now();
}
}
return true;
}
void ViEChannel::OnRttUpdate(uint32_t rtt) {
vcm_.SetReceiveChannelParameters(rtt);
if (!sender_)
rtp_rtcp_->SetRtt(rtt);
}
WebRtc_Word32 ViEChannel::StartDecodeThread() {
// Start the decode thread
if (decode_thread_) {
@ -2230,10 +2240,6 @@ WebRtc_Word32 ViEChannel::StartDecodeThread() {
return -1;
}
// Used to make sure that we don't give the VCM a faked RTT
// too early.
vcm_rttreported_ = TickTime::Now();
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_),
"%s: decode thread with id %u started", __FUNCTION__);
return 0;

View File

@ -31,11 +31,14 @@
namespace webrtc {
class ChannelStatsObserver;
class CriticalSectionWrapper;
class Encryption;
class PacedSender;
class ProcessThread;
class RtpRtcp;
class RtcpRttObserver;
class StatsObserver;
class ThreadWrapper;
class VideoCodingModule;
class VideoDecoder;
@ -57,6 +60,8 @@ class ViEChannel
public RtpFeedback,
public ViEFrameProviderBase {
public:
friend class ChannelStatsObserver;
ViEChannel(WebRtc_Word32 channel_id,
WebRtc_Word32 engine_id,
WebRtc_UWord32 number_of_cores,
@ -64,6 +69,7 @@ class ViEChannel
RtcpIntraFrameObserver* intra_frame_observer,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtt_observer,
PacedSender* paced_sender,
RtpRtcp* default_rtp_rtcp,
bool sender);
@ -297,6 +303,8 @@ class ViEChannel
// Gets the modules used by the channel.
RtpRtcp* rtp_rtcp();
StatsObserver* GetStatsObserver();
// Implements VCMReceiveCallback.
virtual WebRtc_Word32 FrameToRender(I420VideoFrame& video_frame); // NOLINT
@ -342,6 +350,8 @@ class ViEChannel
static bool ChannelDecodeThreadFunction(void* obj);
bool ChannelDecodeProcess();
void OnRttUpdate(uint32_t rtt);
private:
// Assumed to be protected.
WebRtc_Word32 StartDecodeThread();
@ -374,6 +384,9 @@ class ViEChannel
ViESender vie_sender_;
ViESyncModule vie_sync_;
// Helper to report call statistics.
scoped_ptr<ChannelStatsObserver> stats_observer_;
// Not owned.
ProcessThread& module_process_thread_;
ViEDecoderObserver* codec_observer_;
@ -382,6 +395,7 @@ class ViEChannel
ViERTCPObserver* rtcp_observer_;
ViENetworkObserver* networkObserver_;
RtcpIntraFrameObserver* intra_frame_observer_;
RtcpRttObserver* rtt_observer_;
PacedSender* paced_sender_;
scoped_ptr<RtcpBandwidthObserver> bandwidth_observer_;
@ -400,9 +414,6 @@ class ViEChannel
ViEEffectFilter* effect_filter_;
bool color_enhancement_;
// Time when RTT time was last reported to VCM JB.
TickTime vcm_rttreported_;
ViEFileRecorder file_recorder_;
// User set MTU, -1 if not set.

View File

@ -13,6 +13,8 @@
#include "modules/bitrate_controller/include/bitrate_controller.h"
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "modules/utility/interface/process_thread.h"
#include "video_engine/call_stats.h"
#include "video_engine/encoder_state_feedback.h"
#include "video_engine/vie_channel.h"
#include "video_engine/vie_encoder.h"
@ -25,12 +27,16 @@ ChannelGroup::ChannelGroup(ProcessThread* process_thread,
RemoteBitrateEstimator::EstimationMode mode)
: remb_(new VieRemb(process_thread)),
bitrate_controller_(BitrateController::CreateBitrateController()),
call_stats_(new CallStats()),
remote_bitrate_estimator_(RemoteBitrateEstimator::Create(remb_.get(),
options, mode)),
encoder_state_feedback_(new EncoderStateFeedback()) {
encoder_state_feedback_(new EncoderStateFeedback()),
process_thread_(process_thread) {
process_thread->RegisterModule(call_stats_.get());
}
ChannelGroup::~ChannelGroup() {
process_thread_->DeRegisterModule(call_stats_.get());
assert(channels_.empty());
assert(!remb_->InUse());
}
@ -59,6 +65,10 @@ RemoteBitrateEstimator* ChannelGroup::GetRemoteBitrateEstimator() {
return remote_bitrate_estimator_.get();
}
CallStats* ChannelGroup::GetCallStats() {
return call_stats_.get();
}
EncoderStateFeedback* ChannelGroup::GetEncoderStateFeedback() {
return encoder_state_feedback_.get();
}

View File

@ -19,6 +19,7 @@
namespace webrtc {
class BitrateController;
class CallStats;
class EncoderStateFeedback;
struct OverUseDetectorOptions;
class ProcessThread;
@ -47,6 +48,7 @@ class ChannelGroup {
ViEEncoder* encoder);
BitrateController* GetBitrateController();
CallStats* GetCallStats();
RemoteBitrateEstimator* GetRemoteBitrateEstimator();
EncoderStateFeedback* GetEncoderStateFeedback();
@ -55,9 +57,13 @@ class ChannelGroup {
scoped_ptr<VieRemb> remb_;
scoped_ptr<BitrateController> bitrate_controller_;
scoped_ptr<CallStats> call_stats_;
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
scoped_ptr<EncoderStateFeedback> encoder_state_feedback_;
ChannelSet channels_;
// Regisered at construct time and assumed to outlive this class.
ProcessThread* process_thread_;
};
} // namespace webrtc

View File

@ -16,6 +16,7 @@
#include "system_wrappers/interface/critical_section_wrapper.h"
#include "system_wrappers/interface/map_wrapper.h"
#include "system_wrappers/interface/trace.h"
#include "video_engine/call_stats.h"
#include "video_engine/encoder_state_feedback.h"
#include "video_engine/vie_channel.h"
#include "video_engine/vie_defines.h"
@ -105,10 +106,12 @@ int ViEChannelManager::CreateChannel(int* channel_id) {
group->GetRemoteBitrateEstimator();
EncoderStateFeedback* encoder_state_feedback =
group->GetEncoderStateFeedback();
RtcpRttObserver* rtcp_rtt_observer =
group->GetCallStats()->rtcp_rtt_observer();
if (!(vie_encoder->Init() &&
CreateChannelObject(new_channel_id, vie_encoder, bandwidth_observer,
remote_bitrate_estimator,
remote_bitrate_estimator, rtcp_rtt_observer,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
true))) {
delete vie_encoder;
@ -126,10 +129,12 @@ int ViEChannelManager::CreateChannel(int* channel_id) {
std::list<unsigned int> ssrcs;
ssrcs.push_back(ssrc);
vie_encoder->SetSsrcs(ssrcs);
*channel_id = new_channel_id;
group->AddChannel(*channel_id);
channel_groups_.push_back(group);
// Register the channel to receive stats updates.
group->GetCallStats()->RegisterStatsObserver(
channel_map_[new_channel_id]->GetStatsObserver());
return 0;
}
@ -153,6 +158,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();
ViEEncoder* vie_encoder = NULL;
if (sender) {
@ -166,7 +173,9 @@ int ViEChannelManager::CreateChannel(int* channel_id,
vie_encoder,
bandwidth_observer,
remote_bitrate_estimator,
encoder_state_feedback->GetRtcpIntraFrameObserver(), sender))) {
rtcp_rtt_observer,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
sender))) {
delete vie_encoder;
vie_encoder = NULL;
}
@ -183,6 +192,7 @@ int ViEChannelManager::CreateChannel(int* channel_id,
vie_encoder,
bandwidth_observer,
remote_bitrate_estimator,
rtcp_rtt_observer,
encoder_state_feedback->GetRtcpIntraFrameObserver(),
sender)) {
vie_encoder = NULL;
@ -194,6 +204,9 @@ int ViEChannelManager::CreateChannel(int* channel_id,
}
*channel_id = new_channel_id;
channel_group->AddChannel(*channel_id);
// Register the channel to receive stats updates.
channel_group->GetCallStats()->RegisterStatsObserver(
channel_map_[new_channel_id]->GetStatsObserver());
return 0;
}
@ -226,6 +239,8 @@ int ViEChannelManager::DeleteChannel(int channel_id) {
vie_encoder = e_it->second;
group = FindGroup(channel_id);
group->GetCallStats()->DeregisterStatsObserver(
vie_channel->GetStatsObserver());
group->SetChannelRembStatus(channel_id, false, false, vie_channel,
vie_encoder);
@ -399,6 +414,7 @@ bool ViEChannelManager::CreateChannelObject(
ViEEncoder* vie_encoder,
RtcpBandwidthObserver* bandwidth_observer,
RemoteBitrateEstimator* remote_bitrate_estimator,
RtcpRttObserver* rtcp_rtt_observer,
RtcpIntraFrameObserver* intra_frame_observer,
bool sender) {
PacedSender* paced_sender = vie_encoder->GetPacedSender();
@ -412,6 +428,7 @@ bool ViEChannelManager::CreateChannelObject(
intra_frame_observer,
bandwidth_observer,
remote_bitrate_estimator,
rtcp_rtt_observer,
paced_sender,
send_rtp_rtcp_module,
sender);

View File

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