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:
@@ -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
|
||||||
*/
|
*/
|
||||||
|
@@ -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,
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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*>
|
||||||
|
@@ -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));
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user