Propagate estimated RTT from receivers to rtt observer.

BUG=1613
R=stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5063 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
asapersson@webrtc.org
2013-10-31 12:14:34 +00:00
parent da2c37b759
commit 7d6bd22019
8 changed files with 93 additions and 9 deletions

View File

@@ -509,6 +509,11 @@ class RtpRtcp : public Module {
virtual int32_t SetRTCPVoIPMetrics( virtual int32_t SetRTCPVoIPMetrics(
const RTCPVoIPMetric* VoIPMetric) = 0; const RTCPVoIPMetric* VoIPMetric) = 0;
/*
* (XR) Receiver Reference Time Report
*/
virtual void SetRtcpXrRrtrStatus(bool enable) = 0;
/* /*
* (REMB) Receiver Estimated Max Bitrate * (REMB) Receiver Estimated Max Bitrate
*/ */

View File

@@ -168,6 +168,8 @@ class MockRtpRtcp : public RtpRtcp {
int32_t(const uint8_t subType, const uint32_t name, const uint8_t* data, const uint16_t length)); int32_t(const uint8_t subType, const uint32_t name, const uint8_t* data, const uint16_t length));
MOCK_METHOD1(SetRTCPVoIPMetrics, MOCK_METHOD1(SetRTCPVoIPMetrics,
int32_t(const RTCPVoIPMetric* VoIPMetric)); int32_t(const RTCPVoIPMetric* VoIPMetric));
MOCK_METHOD1(SetRtcpXrRrtrStatus,
void(bool enable));
MOCK_CONST_METHOD0(REMB, MOCK_CONST_METHOD0(REMB,
bool()); bool());
MOCK_METHOD1(SetREMBStatus, MOCK_METHOD1(SetREMBStatus,

View File

@@ -50,6 +50,7 @@ RTCPReceiver::RTCPReceiver(const int32_t id, Clock* clock,
_lastReceivedSRNTPfrac(0), _lastReceivedSRNTPfrac(0),
_lastReceivedXRNTPsecs(0), _lastReceivedXRNTPsecs(0),
_lastReceivedXRNTPfrac(0), _lastReceivedXRNTPfrac(0),
xr_rr_rtt_ms_(0),
_receivedInfoMap(), _receivedInfoMap(),
_packetTimeOutMS(0), _packetTimeOutMS(0),
_lastReceivedRrMs(0), _lastReceivedRrMs(0),
@@ -216,6 +217,17 @@ int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
return 0; return 0;
} }
bool RTCPReceiver::GetAndResetXrRrRtt(uint16_t* rtt_ms) {
assert(rtt_ms);
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
if (xr_rr_rtt_ms_ == 0) {
return false;
}
*rtt_ms = xr_rr_rtt_ms_;
xr_rr_rtt_ms_ = 0;
return true;
}
uint16_t RTCPReceiver::RTT() const { uint16_t RTCPReceiver::RTT() const {
CriticalSectionScoped lock(_criticalSectionRTCPReceiver); CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
if (!_receivedReportBlockMap.empty()) { if (!_receivedReportBlockMap.empty()) {
@@ -897,6 +909,7 @@ void RTCPReceiver::HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) {
delete cnameInfoIt->second; delete cnameInfoIt->second;
_receivedCnameMap.erase(cnameInfoIt); _receivedCnameMap.erase(cnameInfoIt);
} }
xr_rr_rtt_ms_ = 0;
rtcpParser.Iterate(); rtcpParser.Iterate();
} }
@@ -968,13 +981,13 @@ void RTCPReceiver::HandleXrDlrrReportBlockItem(
} }
// The DelayLastRR field is in units of 1/65536 sec. // The DelayLastRR field is in units of 1/65536 sec.
// uint32_t delay_rr_ms = uint32_t delay_rr_ms =
// (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) + (((packet.XRDLRRReportBlockItem.DelayLastRR & 0x0000ffff) * 1000) >> 16) +
// (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000); (((packet.XRDLRRReportBlockItem.DelayLastRR & 0xffff0000) >> 16) * 1000);
// TODO(asapersson): Not yet used. int32_t rtt = _clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
// int32_t rtt =_clock->CurrentNtpInMilliseconds() - delay_rr_ms - send_time_ms;
// rtt = std::max(rtt, 1); xr_rr_rtt_ms_ = static_cast<uint16_t>(std::max(rtt, 1));
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock; rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
} }

View File

@@ -86,6 +86,8 @@ public:
int32_t SenderInfoReceived(RTCPSenderInfo* senderInfo) const; int32_t SenderInfoReceived(RTCPSenderInfo* senderInfo) const;
bool GetAndResetXrRrRtt(uint16_t* rtt_ms);
// get statistics // get statistics
int32_t StatisticsReceived( int32_t StatisticsReceived(
std::vector<RTCPReportBlock>* receiveBlocks) const; std::vector<RTCPReportBlock>* receiveBlocks) const;
@@ -245,6 +247,8 @@ protected:
// Time when the report was received. // Time when the report was received.
uint32_t _lastReceivedXRNTPsecs; uint32_t _lastReceivedXRNTPsecs;
uint32_t _lastReceivedXRNTPfrac; uint32_t _lastReceivedXRNTPfrac;
// Estimated rtt, zero when there is no valid estimate.
uint16_t xr_rr_rtt_ms_;
// Received report blocks. // Received report blocks.
std::map<uint32_t, RTCPHelp::RTCPReportBlockInformation*> std::map<uint32_t, RTCPHelp::RTCPReportBlockInformation*>

View File

@@ -459,6 +459,11 @@ TEST(RtcpUtilityTest, MidNtp) {
EXPECT_EQ(kNtpMid, RTCPUtility::MidNtp(kNtpSec, kNtpFrac)); EXPECT_EQ(kNtpMid, RTCPUtility::MidNtp(kNtpSec, kNtpFrac));
} }
TEST_F(RtcpReceiverTest, TestXrRrRttInitiallyFalse) {
uint16_t rtt_ms;
EXPECT_FALSE(rtcp_receiver_->GetAndResetXrRrRtt(&rtt_ms));
}
TEST_F(RtcpReceiverTest, LastReceivedXrReferenceTimeInfoInitiallyFalse) { TEST_F(RtcpReceiverTest, LastReceivedXrReferenceTimeInfoInitiallyFalse) {
RtcpReceiveTimeInfo info; RtcpReceiveTimeInfo info;
EXPECT_FALSE(rtcp_receiver_->LastReceivedXrReferenceTimeInfo(&info)); EXPECT_FALSE(rtcp_receiver_->LastReceivedXrReferenceTimeInfo(&info));

View File

@@ -196,13 +196,12 @@ int32_t ModuleRtpRtcpImpl::Process() {
default_instance = true; default_instance = true;
} }
if (!default_instance) { if (!default_instance) {
bool process_rtt = now >= last_rtt_process_time_ + kRtpRtcpRttProcessTimeMs;
if (rtcp_sender_.Sending()) { if (rtcp_sender_.Sending()) {
// Process RTT if we have received a receiver report and we haven't // Process RTT if we have received a receiver report and we haven't
// processed RTT for at least |kRtpRtcpRttProcessTimeMs| milliseconds. // processed RTT for at least |kRtpRtcpRttProcessTimeMs| milliseconds.
if (rtcp_receiver_.LastReceivedReceiverReport() > if (rtcp_receiver_.LastReceivedReceiverReport() >
last_rtt_process_time_ && now >= last_rtt_process_time_ + last_rtt_process_time_ && process_rtt) {
kRtpRtcpRttProcessTimeMs) {
last_rtt_process_time_ = now;
std::vector<RTCPReportBlock> receive_blocks; std::vector<RTCPReportBlock> receive_blocks;
rtcp_receiver_.StatisticsReceived(&receive_blocks); rtcp_receiver_.StatisticsReceived(&receive_blocks);
uint16_t max_rtt = 0; uint16_t max_rtt = 0;
@@ -237,7 +236,20 @@ int32_t ModuleRtpRtcpImpl::Process() {
rtcp_sender_.SetTargetBitrate(target_bitrate); rtcp_sender_.SetTargetBitrate(target_bitrate);
} }
} }
} else {
// 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 (process_rtt) {
last_rtt_process_time_ = now;
}
if (rtcp_sender_.TimeToSendRTCPReport()) { if (rtcp_sender_.TimeToSendRTCPReport()) {
RTCPSender::FeedbackState feedback_state(this); RTCPSender::FeedbackState feedback_state(this);
rtcp_sender_.SendRTCP(feedback_state, kRtcpReport); rtcp_sender_.SendRTCP(feedback_state, kRtcpReport);
@@ -941,6 +953,12 @@ int32_t ModuleRtpRtcpImpl::SetRTCPVoIPMetrics(
return rtcp_sender_.SetRTCPVoIPMetrics(voip_metric); return rtcp_sender_.SetRTCPVoIPMetrics(voip_metric);
} }
void ModuleRtpRtcpImpl::SetRtcpXrRrtrStatus(bool enable) {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_,
"SetRtcpXrRrtrStatus(%s)", enable ? "true" : "false");
return rtcp_sender_.SendRtcpXrReceiverReferenceTime(enable);
}
int32_t ModuleRtpRtcpImpl::DataCountersRTP( int32_t ModuleRtpRtcpImpl::DataCountersRTP(
uint32_t* bytes_sent, uint32_t* bytes_sent,
uint32_t* packets_sent) const { uint32_t* packets_sent) const {

View File

@@ -255,6 +255,9 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// (XR) VOIP metric. // (XR) VOIP metric.
virtual int32_t SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) OVERRIDE; virtual int32_t SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) OVERRIDE;
// (XR) Receiver reference time report.
virtual void SetRtcpXrRrtrStatus(bool enable) OVERRIDE;
// Audio part. // Audio part.
// Set audio packet size, used to determine when it's time to send a DTMF // Set audio packet size, used to determine when it's time to send a DTMF

View File

@@ -18,6 +18,17 @@
namespace webrtc { namespace webrtc {
namespace { namespace {
class RtcpRttStatsTestImpl : public RtcpRttObserver {
public:
RtcpRttStatsTestImpl() : rtt_ms_(0) {}
virtual ~RtcpRttStatsTestImpl() {}
virtual void OnRttUpdate(uint32_t rtt_ms) {
rtt_ms_ = rtt_ms;
}
uint32_t rtt_ms_;
};
class SendTransport : public Transport, class SendTransport : public Transport,
public NullRtpData { public NullRtpData {
public: public:
@@ -59,6 +70,7 @@ class RtpRtcpImplTest : public ::testing::Test {
configuration.clock = &clock_; configuration.clock = &clock_;
configuration.outgoing_transport = &transport_; configuration.outgoing_transport = &transport_;
configuration.receive_statistics = receive_statistics_.get(); configuration.receive_statistics = receive_statistics_.get();
configuration.rtt_observer = &rtt_stats_;
rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration)); rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
transport_.SetRtpRtcpModule(rtp_rtcp_impl_.get()); transport_.SetRtpRtcpModule(rtp_rtcp_impl_.get());
@@ -68,6 +80,7 @@ class RtpRtcpImplTest : public ::testing::Test {
scoped_ptr<ReceiveStatistics> receive_statistics_; scoped_ptr<ReceiveStatistics> receive_statistics_;
scoped_ptr<ModuleRtpRtcpImpl> rtp_rtcp_impl_; scoped_ptr<ModuleRtpRtcpImpl> rtp_rtcp_impl_;
SendTransport transport_; SendTransport transport_;
RtcpRttStatsTestImpl rtt_stats_;
}; };
TEST_F(RtpRtcpImplTest, Rtt) { TEST_F(RtpRtcpImplTest, Rtt) {
@@ -108,4 +121,25 @@ TEST_F(RtpRtcpImplTest, Rtt) {
rtp_rtcp_impl_->RTT(kSsrc + 1, &rtt, &avg_rtt, &min_rtt, &max_rtt)); rtp_rtcp_impl_->RTT(kSsrc + 1, &rtt, &avg_rtt, &min_rtt, &max_rtt));
} }
TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
rtp_rtcp_impl_->SetRtcpXrRrtrStatus(true);
EXPECT_EQ(0, rtp_rtcp_impl_->SetSendingStatus(false));
EXPECT_EQ(0, rtp_rtcp_impl_->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, rtp_rtcp_impl_->SetSSRC(0x12345));
// A Receiver time reference report (RTRR) should be sent and received.
EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));
// Send new RTRR. A response to the last RTRR should be sent.
clock_.AdvanceTimeMilliseconds(1000);
transport_.SimulateNetworkDelay(100, &clock_);
EXPECT_EQ(0, rtp_rtcp_impl_->SendRTCP(kRtcpReport));
// Verify RTT.
EXPECT_EQ(0U, rtt_stats_.rtt_ms_);
rtp_rtcp_impl_->Process();
EXPECT_EQ(100U, rtt_stats_.rtt_ms_);
}
} // namespace webrtc } // namespace webrtc