Replacing NetEq discard rate with secondary discarded rate.

NetEq network statistics contains discard rate but has not been used and even not been implemented until recently.

According to w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats-packetsdiscarded,
this statistics needs to be replaced with an accumulative stats. Such work will be carried out separately.

Meanwhile, we need to add a rate to reflect rate of discarded redundant packets. See webrtc:8025.

In this CL, we replace the existing discard rate with secondary discarded rate, so as to
1. fulfill the requests on webrtc:8025
2. get ready to implement an accumulative statistics for discarded packets.

BUG: webrtc:7903,webrtc:8025
Change-Id: Idbf143a105db76ca15f0af54848e1448f2a810ec
Reviewed-on: https://chromium-review.googlesource.com/582863
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#19495}
This commit is contained in:
minyue-webrtc
2017-08-23 15:59:38 +02:00
committed by Commit Bot
parent d950d9eda1
commit 0c3ca753c5
14 changed files with 88 additions and 64 deletions

View File

@ -65,7 +65,7 @@ const CallStatistics kCallStats = {
const CodecInst kCodecInst = { const CodecInst kCodecInst = {
123, "codec_name_recv", 96000, -187, 0, -103}; 123, "codec_name_recv", 96000, -187, 0, -103};
const NetworkStatistics kNetworkStats = { const NetworkStatistics kNetworkStats = {
123, 456, false, 0, 0, 789, 12, 345, 678, 901, -1, -1, -1, -1, -1, 0}; 123, 456, false, 0, {}, 789, 12, 345, 678, 901, 0, -1, -1, -1, -1, -1, 0};
const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest(); const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
struct ConfigHelper { struct ConfigHelper {

View File

@ -370,7 +370,9 @@ struct NetworkStatistics {
// Loss rate (network + late); fraction between 0 and 1, scaled to Q14. // Loss rate (network + late); fraction between 0 and 1, scaled to Q14.
uint16_t currentPacketLossRate; uint16_t currentPacketLossRate;
// Late loss rate; fraction between 0 and 1, scaled to Q14. // Late loss rate; fraction between 0 and 1, scaled to Q14.
uint16_t currentDiscardRate; union {
RTC_DEPRECATED uint16_t currentDiscardRate;
};
// fraction (of original stream) of synthesized audio inserted through // fraction (of original stream) of synthesized audio inserted through
// expansion (in Q14) // expansion (in Q14)
uint16_t currentExpandRate; uint16_t currentExpandRate;
@ -384,6 +386,8 @@ struct NetworkStatistics {
uint16_t currentAccelerateRate; uint16_t currentAccelerateRate;
// fraction of data coming from secondary decoding (in Q14) // fraction of data coming from secondary decoding (in Q14)
uint16_t currentSecondaryDecodedRate; uint16_t currentSecondaryDecodedRate;
// fraction of secondary data that is discarded (in Q14).
uint16_t currentSecondaryDiscardedRate;
// clock-drift in parts-per-million (negative or positive) // clock-drift in parts-per-million (negative or positive)
int32_t clockDriftPPM; int32_t clockDriftPPM;
// average packet waiting time in the jitter buffer (ms) // average packet waiting time in the jitter buffer (ms)

View File

@ -320,12 +320,12 @@ void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms; acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms;
acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found ? true : false; acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found ? true : false;
acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate; acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
acm_stat->currentDiscardRate = neteq_stat.packet_discard_rate;
acm_stat->currentExpandRate = neteq_stat.expand_rate; acm_stat->currentExpandRate = neteq_stat.expand_rate;
acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate; acm_stat->currentSpeechExpandRate = neteq_stat.speech_expand_rate;
acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate; acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate; acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate; acm_stat->currentSecondaryDecodedRate = neteq_stat.secondary_decoded_rate;
acm_stat->currentSecondaryDiscardedRate = neteq_stat.secondary_discarded_rate;
acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm; acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm;
acm_stat->addedSamples = neteq_stat.added_zero_samples; acm_stat->addedSamples = neteq_stat.added_zero_samples;
acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms; acm_stat->meanWaitingTimeMs = neteq_stat.mean_waiting_time_ms;

View File

@ -35,7 +35,6 @@ struct NetEqNetworkStatistics {
uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky
// jitter; 0 otherwise. // jitter; 0 otherwise.
uint16_t packet_loss_rate; // Loss rate (network + late) in Q14. uint16_t packet_loss_rate; // Loss rate (network + late) in Q14.
uint16_t packet_discard_rate; // Late loss rate in Q14.
uint16_t expand_rate; // Fraction (of original stream) of synthesized uint16_t expand_rate; // Fraction (of original stream) of synthesized
// audio inserted through expansion (in Q14). // audio inserted through expansion (in Q14).
uint16_t speech_expand_rate; // Fraction (of original stream) of synthesized uint16_t speech_expand_rate; // Fraction (of original stream) of synthesized
@ -44,8 +43,10 @@ struct NetEqNetworkStatistics {
// expansion (in Q14). // expansion (in Q14).
uint16_t accelerate_rate; // Fraction of data removed through acceleration uint16_t accelerate_rate; // Fraction of data removed through acceleration
// (in Q14). // (in Q14).
uint16_t secondary_decoded_rate; // Fraction of data coming from secondary uint16_t secondary_decoded_rate; // Fraction of data coming from FEC/RED
// decoding (in Q14). // decoding (in Q14).
uint16_t secondary_discarded_rate; // Fraction of discarded FEC/RED data (in
// Q14).
int32_t clockdrift_ppm; // Average clock-drift in parts-per-million int32_t clockdrift_ppm; // Average clock-drift in parts-per-million
// (positive or negative). // (positive or negative).
size_t added_zero_samples; // Number of zero samples added in "off" mode. size_t added_zero_samples; // Number of zero samples added in "off" mode.

View File

@ -19,8 +19,8 @@ namespace webrtc {
class MockStatisticsCalculator : public StatisticsCalculator { class MockStatisticsCalculator : public StatisticsCalculator {
public: public:
// For current unittest, we mock only one method.
MOCK_METHOD1(PacketsDiscarded, void(size_t num_packets)); MOCK_METHOD1(PacketsDiscarded, void(size_t num_packets));
MOCK_METHOD1(SecondaryPacketsDiscarded, void(size_t num_packets));
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -136,12 +136,12 @@ struct NetEqNetworkStatsCheck {
logic preferred_buffer_size_ms; logic preferred_buffer_size_ms;
logic jitter_peaks_found; logic jitter_peaks_found;
logic packet_loss_rate; logic packet_loss_rate;
logic packet_discard_rate;
logic expand_rate; logic expand_rate;
logic speech_expand_rate; logic speech_expand_rate;
logic preemptive_rate; logic preemptive_rate;
logic accelerate_rate; logic accelerate_rate;
logic secondary_decoded_rate; logic secondary_decoded_rate;
logic secondary_discarded_rate;
logic clockdrift_ppm; logic clockdrift_ppm;
logic added_zero_samples; logic added_zero_samples;
NetEqNetworkStatistics stats_ref; NetEqNetworkStatistics stats_ref;
@ -201,12 +201,12 @@ NetEqNetworkStatsTest(NetEqDecoder codec,
CHECK_NETEQ_NETWORK_STATS(preferred_buffer_size_ms); CHECK_NETEQ_NETWORK_STATS(preferred_buffer_size_ms);
CHECK_NETEQ_NETWORK_STATS(jitter_peaks_found); CHECK_NETEQ_NETWORK_STATS(jitter_peaks_found);
CHECK_NETEQ_NETWORK_STATS(packet_loss_rate); CHECK_NETEQ_NETWORK_STATS(packet_loss_rate);
CHECK_NETEQ_NETWORK_STATS(packet_discard_rate);
CHECK_NETEQ_NETWORK_STATS(expand_rate); CHECK_NETEQ_NETWORK_STATS(expand_rate);
CHECK_NETEQ_NETWORK_STATS(speech_expand_rate); CHECK_NETEQ_NETWORK_STATS(speech_expand_rate);
CHECK_NETEQ_NETWORK_STATS(preemptive_rate); CHECK_NETEQ_NETWORK_STATS(preemptive_rate);
CHECK_NETEQ_NETWORK_STATS(accelerate_rate); CHECK_NETEQ_NETWORK_STATS(accelerate_rate);
CHECK_NETEQ_NETWORK_STATS(secondary_decoded_rate); CHECK_NETEQ_NETWORK_STATS(secondary_decoded_rate);
CHECK_NETEQ_NETWORK_STATS(secondary_discarded_rate);
CHECK_NETEQ_NETWORK_STATS(clockdrift_ppm); CHECK_NETEQ_NETWORK_STATS(clockdrift_ppm);
CHECK_NETEQ_NETWORK_STATS(added_zero_samples); CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
@ -249,12 +249,12 @@ NetEqNetworkStatsTest(NetEqDecoder codec,
kIgnore, // preferred_buffer_size_ms kIgnore, // preferred_buffer_size_ms
kIgnore, // jitter_peaks_found kIgnore, // jitter_peaks_found
kEqual, // packet_loss_rate kEqual, // packet_loss_rate
kEqual, // packet_discard_rate
kEqual, // expand_rate kEqual, // expand_rate
kEqual, // voice_expand_rate kEqual, // voice_expand_rate
kIgnore, // preemptive_rate kIgnore, // preemptive_rate
kEqual, // accelerate_rate kEqual, // accelerate_rate
kEqual, // decoded_fec_rate kEqual, // decoded_fec_rate
kEqual, // discarded_fec_rate
kIgnore, // clockdrift_ppm kIgnore, // clockdrift_ppm
kEqual, // added_zero_samples kEqual, // added_zero_samples
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@ -273,7 +273,7 @@ NetEqNetworkStatsTest(NetEqDecoder codec,
expects.stats_ref.packet_loss_rate = 0; expects.stats_ref.packet_loss_rate = 0;
expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0; expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
expects.stats_ref.secondary_decoded_rate = 2006; expects.stats_ref.secondary_decoded_rate = 2006;
expects.stats_ref.packet_discard_rate = 13374; expects.stats_ref.secondary_discarded_rate = 14336;
RunTest(50, expects); RunTest(50, expects);
} }
@ -283,12 +283,12 @@ NetEqNetworkStatsTest(NetEqDecoder codec,
kIgnore, // preferred_buffer_size_ms kIgnore, // preferred_buffer_size_ms
kIgnore, // jitter_peaks_found kIgnore, // jitter_peaks_found
kEqual, // packet_loss_rate kEqual, // packet_loss_rate
kEqual, // packet_discard_rate
kEqual, // expand_rate kEqual, // expand_rate
kEqual, // speech_expand_rate kEqual, // speech_expand_rate
kIgnore, // preemptive_rate kIgnore, // preemptive_rate
kEqual, // accelerate_rate kEqual, // accelerate_rate
kEqual, // decoded_fec_rate kEqual, // decoded_fec_rate
kEqual, // discard_fec_rate
kIgnore, // clockdrift_ppm kIgnore, // clockdrift_ppm
kEqual, // added_zero_samples kEqual, // added_zero_samples
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

View File

@ -75,12 +75,12 @@ void Convert(const webrtc::NetEqNetworkStatistics& stats_raw,
stats->set_preferred_buffer_size_ms(stats_raw.preferred_buffer_size_ms); stats->set_preferred_buffer_size_ms(stats_raw.preferred_buffer_size_ms);
stats->set_jitter_peaks_found(stats_raw.jitter_peaks_found); stats->set_jitter_peaks_found(stats_raw.jitter_peaks_found);
stats->set_packet_loss_rate(stats_raw.packet_loss_rate); stats->set_packet_loss_rate(stats_raw.packet_loss_rate);
stats->set_packet_discard_rate(stats_raw.packet_discard_rate);
stats->set_expand_rate(stats_raw.expand_rate); stats->set_expand_rate(stats_raw.expand_rate);
stats->set_speech_expand_rate(stats_raw.speech_expand_rate); stats->set_speech_expand_rate(stats_raw.speech_expand_rate);
stats->set_preemptive_rate(stats_raw.preemptive_rate); stats->set_preemptive_rate(stats_raw.preemptive_rate);
stats->set_accelerate_rate(stats_raw.accelerate_rate); stats->set_accelerate_rate(stats_raw.accelerate_rate);
stats->set_secondary_decoded_rate(stats_raw.secondary_decoded_rate); stats->set_secondary_decoded_rate(stats_raw.secondary_decoded_rate);
stats->set_secondary_discarded_rate(stats_raw.secondary_discarded_rate);
stats->set_clockdrift_ppm(stats_raw.clockdrift_ppm); stats->set_clockdrift_ppm(stats_raw.clockdrift_ppm);
stats->set_added_zero_samples(stats_raw.added_zero_samples); stats->set_added_zero_samples(stats_raw.added_zero_samples);
stats->set_mean_waiting_time_ms(stats_raw.mean_waiting_time_ms); stats->set_mean_waiting_time_ms(stats_raw.mean_waiting_time_ms);
@ -445,10 +445,10 @@ TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) {
"759fef89a5de52bd17e733dc255c671ce86be909"); "759fef89a5de52bd17e733dc255c671ce86be909");
const std::string network_stats_checksum = const std::string network_stats_checksum =
PlatformChecksum("f7c2158761a531dd2804d13da0480033faa7be12", PlatformChecksum("5b4262ca328e5f066af5d34f3380521583dd20de",
"8b5e3c8247dce48cb33923eaa1a502ca91429d5e", "80235b6d727281203acb63b98f9a9e85d95f7ec0",
"f7c2158761a531dd2804d13da0480033faa7be12", "5b4262ca328e5f066af5d34f3380521583dd20de",
"f7c2158761a531dd2804d13da0480033faa7be12"); "5b4262ca328e5f066af5d34f3380521583dd20de");
const std::string rtcp_stats_checksum = PlatformChecksum( const std::string rtcp_stats_checksum = PlatformChecksum(
"b8880bf9fed2487efbddcb8d94b9937a29ae521d", "b8880bf9fed2487efbddcb8d94b9937a29ae521d",
@ -481,10 +481,10 @@ TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) {
"721e1e0c6effe4b2401536a4eef11512c9fb709c"); "721e1e0c6effe4b2401536a4eef11512c9fb709c");
const std::string network_stats_checksum = const std::string network_stats_checksum =
PlatformChecksum("dda4cee006d9369c7114a03790c5761346cf5e23", PlatformChecksum("4e749c46e2611877120ac7a20cbbe555cfbd70ea",
"dda4cee006d9369c7114a03790c5761346cf5e23", "4e749c46e2611877120ac7a20cbbe555cfbd70ea",
"dda4cee006d9369c7114a03790c5761346cf5e23", "4e749c46e2611877120ac7a20cbbe555cfbd70ea",
"dda4cee006d9369c7114a03790c5761346cf5e23"); "4e749c46e2611877120ac7a20cbbe555cfbd70ea");
const std::string rtcp_stats_checksum = PlatformChecksum( const std::string rtcp_stats_checksum = PlatformChecksum(
"e37c797e3de6a64dda88c9ade7a013d022a2e1e0", "e37c797e3de6a64dda88c9ade7a013d022a2e1e0",

View File

@ -3,16 +3,18 @@ option optimize_for = LITE_RUNTIME;
package webrtc.neteq_unittest; package webrtc.neteq_unittest;
message NetEqNetworkStatistics { message NetEqNetworkStatistics {
// Next field number 18.
optional uint32 current_buffer_size_ms = 1; optional uint32 current_buffer_size_ms = 1;
optional uint32 preferred_buffer_size_ms = 2; optional uint32 preferred_buffer_size_ms = 2;
optional uint32 jitter_peaks_found = 3; optional uint32 jitter_peaks_found = 3;
optional uint32 packet_loss_rate = 4; optional uint32 packet_loss_rate = 4;
optional uint32 packet_discard_rate = 5; optional uint32 packet_discard_rate = 5 [deprecated = true];
optional uint32 expand_rate = 6; optional uint32 expand_rate = 6;
optional uint32 speech_expand_rate = 7; optional uint32 speech_expand_rate = 7;
optional uint32 preemptive_rate = 8; optional uint32 preemptive_rate = 8;
optional uint32 accelerate_rate = 9; optional uint32 accelerate_rate = 9;
optional uint32 secondary_decoded_rate = 10; optional uint32 secondary_decoded_rate = 10;
optional uint32 secondary_discarded_rate = 17;
optional int32 clockdrift_ppm = 11; optional int32 clockdrift_ppm = 11;
optional uint64 added_zero_samples = 12; optional uint64 added_zero_samples = 12;
optional int32 mean_waiting_time_ms = 13; optional int32 mean_waiting_time_ms = 13;

View File

@ -48,6 +48,16 @@ bool EqualSampleRates(uint8_t pt1,
auto* di2 = decoder_database.GetDecoderInfo(pt2); auto* di2 = decoder_database.GetDecoderInfo(pt2);
return di1 && di2 && di1->SampleRateHz() == di2->SampleRateHz(); return di1 && di2 && di1->SampleRateHz() == di2->SampleRateHz();
} }
void LogPacketDiscarded(int codec_level, StatisticsCalculator* stats) {
RTC_CHECK(stats);
if (codec_level > 0) {
stats->SecondaryPacketsDiscarded(1);
} else {
stats->PacketsDiscarded(1);
}
}
} // namespace } // namespace
PacketBuffer::PacketBuffer(size_t max_number_of_packets, PacketBuffer::PacketBuffer(size_t max_number_of_packets,
@ -99,8 +109,7 @@ int PacketBuffer::InsertPacket(Packet&& packet, StatisticsCalculator* stats) {
// timestamp as |rit|, which has a higher priority, do not insert the new // timestamp as |rit|, which has a higher priority, do not insert the new
// packet to list. // packet to list.
if (rit != buffer_.rend() && packet.timestamp == rit->timestamp) { if (rit != buffer_.rend() && packet.timestamp == rit->timestamp) {
RTC_CHECK(stats); LogPacketDiscarded(packet.priority.codec_level, stats);
stats->PacketsDiscarded(1);
return return_val; return return_val;
} }
@ -109,9 +118,8 @@ int PacketBuffer::InsertPacket(Packet&& packet, StatisticsCalculator* stats) {
// packet. // packet.
PacketList::iterator it = rit.base(); PacketList::iterator it = rit.base();
if (it != buffer_.end() && packet.timestamp == it->timestamp) { if (it != buffer_.end() && packet.timestamp == it->timestamp) {
LogPacketDiscarded(packet.priority.codec_level, stats);
it = buffer_.erase(it); it = buffer_.erase(it);
RTC_CHECK(stats);
stats->PacketsDiscarded(1);
} }
buffer_.insert(it, std::move(packet)); // Insert the packet at that position. buffer_.insert(it, std::move(packet)); // Insert the packet at that position.
@ -218,25 +226,24 @@ int PacketBuffer::DiscardNextPacket(StatisticsCalculator* stats) {
return kBufferEmpty; return kBufferEmpty;
} }
// Assert that the packet sanity checks in InsertPacket method works. // Assert that the packet sanity checks in InsertPacket method works.
RTC_DCHECK(!buffer_.front().empty()); const Packet& packet = buffer_.front();
RTC_DCHECK(!packet.empty());
LogPacketDiscarded(packet.priority.codec_level, stats);
buffer_.pop_front(); buffer_.pop_front();
RTC_CHECK(stats);
stats->PacketsDiscarded(1);
return kOK; return kOK;
} }
void PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit, void PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
uint32_t horizon_samples, uint32_t horizon_samples,
StatisticsCalculator* stats) { StatisticsCalculator* stats) {
const size_t old_size = buffer_.size(); buffer_.remove_if([timestamp_limit, horizon_samples, stats](const Packet& p) {
buffer_.remove_if([timestamp_limit, horizon_samples](const Packet& p) { if (timestamp_limit == p.timestamp ||
return timestamp_limit != p.timestamp && !IsObsoleteTimestamp(p.timestamp, timestamp_limit, horizon_samples)) {
IsObsoleteTimestamp(p.timestamp, timestamp_limit, horizon_samples); return false;
}
LogPacketDiscarded(p.priority.codec_level, stats);
return true;
}); });
if (old_size > buffer_.size()) {
RTC_CHECK(stats);
stats->PacketsDiscarded(old_size - buffer_.size());
}
} }
void PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit, void PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit,
@ -246,20 +253,13 @@ void PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit,
void PacketBuffer::DiscardPacketsWithPayloadType(uint8_t payload_type, void PacketBuffer::DiscardPacketsWithPayloadType(uint8_t payload_type,
StatisticsCalculator* stats) { StatisticsCalculator* stats) {
int packets_discarded = 0; buffer_.remove_if([payload_type, stats](const Packet& p) {
for (auto it = buffer_.begin(); it != buffer_.end(); /* */) { if (p.payload_type != payload_type) {
const Packet& packet = *it; return false;
if (packet.payload_type == payload_type) {
it = buffer_.erase(it);
++packets_discarded;
} else {
++it;
} }
} LogPacketDiscarded(p.priority.codec_level, stats);
if (packets_discarded > 0) { return true;
RTC_CHECK(stats); });
stats->PacketsDiscarded(packets_discarded);
}
} }
size_t PacketBuffer::NumPacketsInBuffer() const { size_t PacketBuffer::NumPacketsInBuffer() const {

View File

@ -292,9 +292,13 @@ TEST(PacketBuffer, ExtractOrderRedundancy) {
packet_facts[i].payload_type, packet_facts[i].payload_type,
kFrameSize); kFrameSize);
Packet packet = gen.NextPacket(kPayloadLength); Packet packet = gen.NextPacket(kPayloadLength);
packet.priority.red_level = packet_facts[i].primary ? 0 : 1; packet.priority.codec_level = packet_facts[i].primary ? 0 : 1;
if (packet_facts[i].extract_order < 0) { if (packet_facts[i].extract_order < 0) {
EXPECT_CALL(mock_stats, PacketsDiscarded(1)); if (packet.priority.codec_level > 0) {
EXPECT_CALL(mock_stats, SecondaryPacketsDiscarded(1));
} else {
EXPECT_CALL(mock_stats, PacketsDiscarded(1));
}
} }
EXPECT_CALL(check, Call(i)); EXPECT_CALL(check, Call(i));
EXPECT_EQ(PacketBuffer::kOK, EXPECT_EQ(PacketBuffer::kOK,
@ -358,7 +362,8 @@ TEST(PacketBuffer, DiscardPackets) {
// This will discard all remaining packets but one. The oldest packet is older // This will discard all remaining packets but one. The oldest packet is older
// than the indicated horizon_samples, and will thus be left in the buffer. // than the indicated horizon_samples, and will thus be left in the buffer.
constexpr size_t kSkipPackets = 1; constexpr size_t kSkipPackets = 1;
EXPECT_CALL(mock_stats, PacketsDiscarded(kRemainingPackets - kSkipPackets)); EXPECT_CALL(mock_stats, PacketsDiscarded(1))
.Times(kRemainingPackets - kSkipPackets);
EXPECT_CALL(check, Call(17)); // Arbitrary id number. EXPECT_CALL(check, Call(17)); // Arbitrary id number.
buffer.DiscardOldPackets(start_ts + kTotalPackets * ts_increment, buffer.DiscardOldPackets(start_ts + kTotalPackets * ts_increment,
kRemainingPackets * ts_increment, &mock_stats); kRemainingPackets * ts_increment, &mock_stats);

View File

@ -123,14 +123,14 @@ StatisticsCalculator::StatisticsCalculator()
lost_timestamps_(0), lost_timestamps_(0),
timestamps_since_last_report_(0), timestamps_since_last_report_(0),
secondary_decoded_samples_(0), secondary_decoded_samples_(0),
discarded_secondary_packets_(0),
delayed_packet_outage_counter_( delayed_packet_outage_counter_(
"WebRTC.Audio.DelayedPacketOutageEventsPerMinute", "WebRTC.Audio.DelayedPacketOutageEventsPerMinute",
60000, // 60 seconds report interval. 60000, // 60 seconds report interval.
100), 100),
excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs", excess_buffer_delay_("WebRTC.Audio.AverageExcessBufferDelayMs",
60000, // 60 seconds report interval. 60000, // 60 seconds report interval.
1000) { 1000) {}
}
StatisticsCalculator::~StatisticsCalculator() = default; StatisticsCalculator::~StatisticsCalculator() = default;
@ -141,6 +141,7 @@ void StatisticsCalculator::Reset() {
expanded_speech_samples_ = 0; expanded_speech_samples_ = 0;
expanded_noise_samples_ = 0; expanded_noise_samples_ = 0;
secondary_decoded_samples_ = 0; secondary_decoded_samples_ = 0;
discarded_secondary_packets_ = 0;
waiting_times_.clear(); waiting_times_.clear();
} }
@ -184,6 +185,10 @@ void StatisticsCalculator::PacketsDiscarded(size_t num_packets) {
discarded_packets_ += num_packets; discarded_packets_ += num_packets;
} }
void StatisticsCalculator::SecondaryPacketsDiscarded(size_t num_packets) {
discarded_secondary_packets_ += num_packets;
}
void StatisticsCalculator::LostSamples(size_t num_samples) { void StatisticsCalculator::LostSamples(size_t num_samples) {
lost_timestamps_ += num_samples; lost_timestamps_ += num_samples;
} }
@ -249,10 +254,6 @@ void StatisticsCalculator::GetNetworkStatistics(
stats->packet_loss_rate = stats->packet_loss_rate =
CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_); CalculateQ14Ratio(lost_timestamps_, timestamps_since_last_report_);
const size_t discarded_samples = discarded_packets_ * samples_per_packet;
stats->packet_discard_rate =
CalculateQ14Ratio(discarded_samples, timestamps_since_last_report_);
stats->accelerate_rate = stats->accelerate_rate =
CalculateQ14Ratio(accelerate_samples_, timestamps_since_last_report_); CalculateQ14Ratio(accelerate_samples_, timestamps_since_last_report_);
@ -271,6 +272,12 @@ void StatisticsCalculator::GetNetworkStatistics(
CalculateQ14Ratio(secondary_decoded_samples_, CalculateQ14Ratio(secondary_decoded_samples_,
timestamps_since_last_report_); timestamps_since_last_report_);
const size_t discarded_secondary_samples =
discarded_secondary_packets_ * samples_per_packet;
stats->secondary_discarded_rate = CalculateQ14Ratio(
discarded_secondary_samples,
discarded_secondary_samples + secondary_decoded_samples_);
if (waiting_times_.size() == 0) { if (waiting_times_.size() == 0) {
stats->mean_waiting_time_ms = -1; stats->mean_waiting_time_ms = -1;
stats->median_waiting_time_ms = -1; stats->median_waiting_time_ms = -1;

View File

@ -66,6 +66,9 @@ class StatisticsCalculator {
// Reports that |num_packets| packets were discarded. // Reports that |num_packets| packets were discarded.
virtual void PacketsDiscarded(size_t num_packets); virtual void PacketsDiscarded(size_t num_packets);
// Reports that |num_packets| packets samples were discarded.
virtual void SecondaryPacketsDiscarded(size_t num_samples);
// Reports that |num_samples| were lost. // Reports that |num_samples| were lost.
void LostSamples(size_t num_samples); void LostSamples(size_t num_samples);
@ -165,6 +168,7 @@ class StatisticsCalculator {
uint32_t timestamps_since_last_report_; uint32_t timestamps_since_last_report_;
std::deque<int> waiting_times_; std::deque<int> waiting_times_;
uint32_t secondary_decoded_samples_; uint32_t secondary_decoded_samples_;
size_t discarded_secondary_packets_;
PeriodicUmaCount delayed_packet_outage_counter_; PeriodicUmaCount delayed_packet_outage_counter_;
PeriodicUmaAverage excess_buffer_delay_; PeriodicUmaAverage excess_buffer_delay_;

View File

@ -352,12 +352,12 @@ class StatsGetter : public NetEqGetAudioCallback {
double preferred_buffer_size_ms = 0.0; double preferred_buffer_size_ms = 0.0;
double jitter_peaks_found = 0.0; double jitter_peaks_found = 0.0;
double packet_loss_rate = 0.0; double packet_loss_rate = 0.0;
double packet_discard_rate = 0.0;
double expand_rate = 0.0; double expand_rate = 0.0;
double speech_expand_rate = 0.0; double speech_expand_rate = 0.0;
double preemptive_rate = 0.0; double preemptive_rate = 0.0;
double accelerate_rate = 0.0; double accelerate_rate = 0.0;
double secondary_decoded_rate = 0.0; double secondary_decoded_rate = 0.0;
double secondary_discarded_rate = 0.0;
double clockdrift_ppm = 0.0; double clockdrift_ppm = 0.0;
double added_zero_samples = 0.0; double added_zero_samples = 0.0;
double mean_waiting_time_ms = 0.0; double mean_waiting_time_ms = 0.0;
@ -410,12 +410,12 @@ class StatsGetter : public NetEqGetAudioCallback {
a.preferred_buffer_size_ms += b.preferred_buffer_size_ms; a.preferred_buffer_size_ms += b.preferred_buffer_size_ms;
a.jitter_peaks_found += b.jitter_peaks_found; a.jitter_peaks_found += b.jitter_peaks_found;
a.packet_loss_rate += b.packet_loss_rate / 16384.0; a.packet_loss_rate += b.packet_loss_rate / 16384.0;
a.packet_discard_rate += b.packet_discard_rate / 16384.0;
a.expand_rate += b.expand_rate / 16384.0; a.expand_rate += b.expand_rate / 16384.0;
a.speech_expand_rate += b.speech_expand_rate / 16384.0; a.speech_expand_rate += b.speech_expand_rate / 16384.0;
a.preemptive_rate += b.preemptive_rate / 16384.0; a.preemptive_rate += b.preemptive_rate / 16384.0;
a.accelerate_rate += b.accelerate_rate / 16384.0; a.accelerate_rate += b.accelerate_rate / 16384.0;
a.secondary_decoded_rate += b.secondary_decoded_rate / 16384.0; a.secondary_decoded_rate += b.secondary_decoded_rate / 16384.0;
a.secondary_discarded_rate += b.secondary_discarded_rate / 16384.0;
a.clockdrift_ppm += b.clockdrift_ppm; a.clockdrift_ppm += b.clockdrift_ppm;
a.added_zero_samples += b.added_zero_samples; a.added_zero_samples += b.added_zero_samples;
a.mean_waiting_time_ms += b.mean_waiting_time_ms; a.mean_waiting_time_ms += b.mean_waiting_time_ms;
@ -429,12 +429,12 @@ class StatsGetter : public NetEqGetAudioCallback {
sum_stats.preferred_buffer_size_ms /= stats_.size(); sum_stats.preferred_buffer_size_ms /= stats_.size();
sum_stats.jitter_peaks_found /= stats_.size(); sum_stats.jitter_peaks_found /= stats_.size();
sum_stats.packet_loss_rate /= stats_.size(); sum_stats.packet_loss_rate /= stats_.size();
sum_stats.packet_discard_rate /= stats_.size();
sum_stats.expand_rate /= stats_.size(); sum_stats.expand_rate /= stats_.size();
sum_stats.speech_expand_rate /= stats_.size(); sum_stats.speech_expand_rate /= stats_.size();
sum_stats.preemptive_rate /= stats_.size(); sum_stats.preemptive_rate /= stats_.size();
sum_stats.accelerate_rate /= stats_.size(); sum_stats.accelerate_rate /= stats_.size();
sum_stats.secondary_decoded_rate /= stats_.size(); sum_stats.secondary_decoded_rate /= stats_.size();
sum_stats.secondary_discarded_rate /= stats_.size();
sum_stats.clockdrift_ppm /= stats_.size(); sum_stats.clockdrift_ppm /= stats_.size();
sum_stats.added_zero_samples /= stats_.size(); sum_stats.added_zero_samples /= stats_.size();
sum_stats.mean_waiting_time_ms /= stats_.size(); sum_stats.mean_waiting_time_ms /= stats_.size();
@ -644,13 +644,14 @@ int RunTest(int argc, char* argv[]) {
printf(" output duration: %" PRId64 " ms\n", test_duration_ms); printf(" output duration: %" PRId64 " ms\n", test_duration_ms);
auto stats = stats_getter.AverageStats(); auto stats = stats_getter.AverageStats();
printf(" packet_loss_rate: %f %%\n", 100.0 * stats.packet_loss_rate); printf(" packet_loss_rate: %f %%\n", 100.0 * stats.packet_loss_rate);
printf(" packet_discard_rate: %f %%\n", 100.0 * stats.packet_discard_rate);
printf(" expand_rate: %f %%\n", 100.0 * stats.expand_rate); printf(" expand_rate: %f %%\n", 100.0 * stats.expand_rate);
printf(" speech_expand_rate: %f %%\n", 100.0 * stats.speech_expand_rate); printf(" speech_expand_rate: %f %%\n", 100.0 * stats.speech_expand_rate);
printf(" preemptive_rate: %f %%\n", 100.0 * stats.preemptive_rate); printf(" preemptive_rate: %f %%\n", 100.0 * stats.preemptive_rate);
printf(" accelerate_rate: %f %%\n", 100.0 * stats.accelerate_rate); printf(" accelerate_rate: %f %%\n", 100.0 * stats.accelerate_rate);
printf(" secondary_decoded_rate: %f %%\n", printf(" secondary_decoded_rate: %f %%\n",
100.0 * stats.secondary_decoded_rate); 100.0 * stats.secondary_decoded_rate);
printf(" secondary_discarded_rate: %f %%\n",
100.0 * stats.secondary_discarded_rate);
printf(" clockdrift_ppm: %f ppm\n", stats.clockdrift_ppm); printf(" clockdrift_ppm: %f ppm\n", stats.clockdrift_ppm);
printf(" mean_waiting_time_ms: %f ms\n", stats.mean_waiting_time_ms); printf(" mean_waiting_time_ms: %f ms\n", stats.mean_waiting_time_ms);
printf(" median_waiting_time_ms: %f ms\n", stats.median_waiting_time_ms); printf(" median_waiting_time_ms: %f ms\n", stats.median_waiting_time_ms);

View File

@ -752,8 +752,6 @@ void APITest::TestDelay(char side) {
networkStat.jitterPeaksFound); networkStat.jitterPeaksFound);
fprintf(stdout, "packet-size rate........ %d\n", fprintf(stdout, "packet-size rate........ %d\n",
networkStat.currentPacketLossRate); networkStat.currentPacketLossRate);
fprintf(stdout, "discard rate............ %d\n",
networkStat.currentDiscardRate);
fprintf(stdout, "expand rate............. %d\n", fprintf(stdout, "expand rate............. %d\n",
networkStat.currentExpandRate); networkStat.currentExpandRate);
fprintf(stdout, "speech expand rate...... %d\n", fprintf(stdout, "speech expand rate...... %d\n",
@ -764,6 +762,8 @@ void APITest::TestDelay(char side) {
networkStat.currentAccelerateRate); networkStat.currentAccelerateRate);
fprintf(stdout, "Secondary decoded rate.. %d\n", fprintf(stdout, "Secondary decoded rate.. %d\n",
networkStat.currentSecondaryDecodedRate); networkStat.currentSecondaryDecodedRate);
fprintf(stdout, "Secondary discarded rate.%d\n",
networkStat.currentSecondaryDiscardedRate);
fprintf(stdout, "Clock-drift............. %d\n", networkStat.clockDriftPPM); fprintf(stdout, "Clock-drift............. %d\n", networkStat.clockDriftPPM);
fprintf(stdout, "Mean waiting time....... %d\n", fprintf(stdout, "Mean waiting time....... %d\n",
networkStat.meanWaitingTimeMs); networkStat.meanWaitingTimeMs);