Revert "Update packetsLost and jitter stats any time a packet is received."

This reverts commit 84916937b70472715efe5682bc273e91c3a72695.

Reason for revert: breaking downstream projects.

Original change's description:
> Update packetsLost and jitter stats any time a packet is received.
>
> Before this CL, the packetsLost and jitter stats (as returned by
> GetStats, at the API level) were only being updated when an RTCP SR or
> RR is generated. According to the stats spec, "local" stats like this
> should be updated any time a packet is received.
>
> This CL also fixes some minor issues with the calculation of packetsLost
> (and fractionLost):
> * Packets weren't being count as lost if lost over a sequence number
>   rollover.
> * Temporary periods of "negative" loss (caused by duplicate or out of
>   order packets) weren't being accumulated into the cumulative loss
>   counter. Example:
>   Period 1: Received packets 1, 2, 4
>     Loss over that period: 1 (expected 4 packets, got 3)
>     Reported cumulative loss: 1
>   Period 2: Received packets 3, 5
>     Loss over that period: -1 (expected 1 packet, got 2)
>     Reported cumulative loss: 1 (should be 0!)
>
> Landing with NOTRY because Android compile bots are broken for an
> unrelated reason.
> NOTRY=True
>
> Bug: webrtc:8804
> Change-Id: I840ba34de8957b1276f6bdaf93718f805629f5c8
> Reviewed-on: https://webrtc-review.googlesource.com/50020
> Commit-Queue: Taylor Brandstetter <deadbeef@webrtc.org>
> Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
> Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#23731}

TBR=danilchap@webrtc.org,deadbeef@webrtc.org,ossu@webrtc.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Landing with NOTRY because ios64_sim_ios10_dbg bot is broken.
Passing all other bots.
NOTRY=True

Bug: webrtc:8804
Change-Id: I07bd6b1206d5a8d211792ad392842f9ed6c505e9
Reviewed-on: https://webrtc-review.googlesource.com/95280
Commit-Queue: Qingsi Wang <qingsi@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24370}
This commit is contained in:
Qingsi Wang
2018-08-21 14:24:26 -07:00
committed by Commit Bot
parent ddbbf4601b
commit 2370b0831f
5 changed files with 150 additions and 534 deletions

View File

@ -39,12 +39,16 @@ StreamStatisticianImpl::StreamStatisticianImpl(
RateStatistics::kBpsScale),
max_reordering_threshold_(kDefaultMaxReorderingThreshold),
jitter_q4_(0),
cumulative_loss_(0),
last_receive_time_ms_(0),
last_received_timestamp_(0),
received_seq_first_(0),
received_seq_max_(0),
received_seq_wraps_(0),
received_packet_overhead_(12),
last_report_inorder_packets_(0),
last_report_old_packets_(0),
last_report_seq_max_(0),
rtcp_callback_(rtcp_callback),
rtp_callback_(rtp_callback) {}
@ -53,24 +57,15 @@ StreamStatisticianImpl::~StreamStatisticianImpl() = default;
void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
size_t packet_length,
bool retransmitted) {
StreamDataCounters counters;
RtcpStatistics rtcp_stats;
{
rtc::CritScope cs(&stream_lock_);
counters = UpdateCounters(header, packet_length, retransmitted);
// We only want to recalculate |fraction_lost| when sending an RTCP SR or
// RR.
rtcp_stats = CalculateRtcpStatistics(/*update_fraction_lost=*/false);
}
auto counters = UpdateCounters(header, packet_length, retransmitted);
rtp_callback_->DataCountersUpdated(counters, ssrc_);
rtcp_callback_->StatisticsUpdated(rtcp_stats, ssrc_);
}
StreamDataCounters StreamStatisticianImpl::UpdateCounters(
const RTPHeader& header,
size_t packet_length,
bool retransmitted) {
rtc::CritScope cs(&stream_lock_);
bool in_order = InOrderPacketInternal(header.sequenceNumber);
RTC_DCHECK_EQ(ssrc_, header.ssrc);
incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
@ -158,7 +153,7 @@ void StreamStatisticianImpl::SetMaxReorderingThreshold(
}
bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics,
bool update_fraction_lost) {
bool reset) {
{
rtc::CritScope cs(&stream_lock_);
if (received_seq_first_ == 0 &&
@ -167,12 +162,20 @@ bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics,
return false;
}
*statistics = CalculateRtcpStatistics(update_fraction_lost);
if (!reset) {
if (last_report_inorder_packets_ == 0) {
// No report.
return false;
}
// Just get last report.
*statistics = last_reported_statistics_;
return true;
}
*statistics = CalculateRtcpStatistics();
}
if (update_fraction_lost) {
rtcp_callback_->StatisticsUpdated(*statistics, ssrc_);
}
rtcp_callback_->StatisticsUpdated(*statistics, ssrc_);
return true;
}
@ -191,71 +194,84 @@ bool StreamStatisticianImpl::GetActiveStatisticsAndReset(
return false;
}
*statistics = CalculateRtcpStatistics(/*update_fraction_lost=*/true);
*statistics = CalculateRtcpStatistics();
}
rtcp_callback_->StatisticsUpdated(*statistics, ssrc_);
return true;
}
RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics(
bool update_fraction_lost) {
RtcpStatistics statistics;
RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() {
RtcpStatistics stats;
uint32_t extended_seq_max = (received_seq_wraps_ << 16) + received_seq_max_;
if (update_fraction_lost) {
if (last_report_received_packets_ == 0) {
// First time we're calculating fraction lost.
last_report_extended_seq_max_ = received_seq_first_ - 1;
}
uint32_t exp_since_last =
(extended_seq_max - last_report_extended_seq_max_);
// Number of received RTP packets since last report; counts all packets
// including retransmissions.
uint32_t rec_since_last =
receive_counters_.transmitted.packets - last_report_received_packets_;
// Calculate fraction lost according to RFC3550 Appendix A.3. Snap to 0 if
// negative (which is possible with duplicate packets).
uint8_t local_fraction_lost = 0;
if (exp_since_last > rec_since_last) {
// Scale 0 to 255, where 255 is 100% loss.
local_fraction_lost = static_cast<uint8_t>(
255 * (exp_since_last - rec_since_last) / exp_since_last);
}
last_fraction_lost_ = local_fraction_lost;
last_report_received_packets_ = receive_counters_.transmitted.packets;
last_report_extended_seq_max_ = extended_seq_max;
if (last_report_inorder_packets_ == 0) {
// First time we send a report.
last_report_seq_max_ = received_seq_first_ - 1;
}
statistics.fraction_lost = last_fraction_lost_;
// Calculate cumulative loss, according to RFC3550 Appendix A.3.
uint32_t total_expected_packets = extended_seq_max - received_seq_first_ + 1;
statistics.packets_lost =
total_expected_packets - receive_counters_.transmitted.packets;
// Since cumulative loss is carried in a signed 24-bit field in RTCP, we may
// need to clamp it.
statistics.packets_lost = std::min(statistics.packets_lost, 0x7fffff);
// TODO(bugs.webrtc.org/9598): This packets_lost should be signed according to
// RFC3550. However, old WebRTC implementations reads it as unsigned.
// Therefore we limit this to 0.
statistics.packets_lost = std::max(statistics.packets_lost, 0);
statistics.extended_highest_sequence_number = extended_seq_max;
// Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
statistics.jitter = jitter_q4_ >> 4;
// Calculate fraction lost.
uint16_t exp_since_last = (received_seq_max_ - last_report_seq_max_);
if (last_report_seq_max_ > received_seq_max_) {
// Can we assume that the seq_num can't go decrease over a full RTCP period?
exp_since_last = 0;
}
// Number of received RTP packets since last report, counts all packets but
// not re-transmissions.
uint32_t rec_since_last = (receive_counters_.transmitted.packets -
receive_counters_.retransmitted.packets) -
last_report_inorder_packets_;
// With NACK we don't know the expected retransmissions during the last
// second. We know how many "old" packets we have received. We just count
// the number of old received to estimate the loss, but it still does not
// guarantee an exact number since we run this based on time triggered by
// sending of an RTP packet. This should have a minimum effect.
// With NACK we don't count old packets as received since they are
// re-transmitted. We use RTT to decide if a packet is re-ordered or
// re-transmitted.
uint32_t retransmitted_packets =
receive_counters_.retransmitted.packets - last_report_old_packets_;
rec_since_last += retransmitted_packets;
int32_t missing = 0;
if (exp_since_last > rec_since_last) {
missing = (exp_since_last - rec_since_last);
}
uint8_t local_fraction_lost = 0;
if (exp_since_last) {
// Scale 0 to 255, where 255 is 100% loss.
local_fraction_lost = static_cast<uint8_t>(255 * missing / exp_since_last);
}
stats.fraction_lost = local_fraction_lost;
// We need a counter for cumulative loss too.
// TODO(danilchap): Ensure cumulative loss is below maximum value of 2^24.
cumulative_loss_ += missing;
stats.packets_lost = cumulative_loss_;
stats.extended_highest_sequence_number =
(received_seq_wraps_ << 16) + received_seq_max_;
// Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
stats.jitter = jitter_q4_ >> 4;
// Store this report.
last_reported_statistics_ = stats;
// Only for report blocks in RTCP SR and RR.
last_report_inorder_packets_ = receive_counters_.transmitted.packets -
receive_counters_.retransmitted.packets;
last_report_old_packets_ = receive_counters_.retransmitted.packets;
last_report_seq_max_ = received_seq_max_;
BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "cumulative_loss_pkts",
clock_->TimeInMilliseconds(),
statistics.packets_lost, ssrc_);
cumulative_loss_, ssrc_);
BWE_TEST_LOGGING_PLOT_WITH_SSRC(
1, "received_seq_max_pkts", clock_->TimeInMilliseconds(),
(received_seq_max_ - received_seq_first_), ssrc_);
return statistics;
return stats;
}
void StreamStatisticianImpl::GetDataCounters(size_t* bytes_received,
@ -316,7 +332,7 @@ bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
bool StreamStatisticianImpl::InOrderPacketInternal(
uint16_t sequence_number) const {
// First packet is always in order.
if (receive_counters_.transmitted.packets == 0)
if (last_receive_time_ms_ == 0)
return true;
if (IsNewerSequenceNumber(sequence_number, received_seq_max_)) {