diff --git a/api/neteq/neteq.h b/api/neteq/neteq.h index ea7079e369..81340f16f8 100644 --- a/api/neteq/neteq.h +++ b/api/neteq/neteq.h @@ -60,7 +60,7 @@ struct NetEqNetworkStatistics { // These metrics are never reset. struct NetEqLifetimeStatistics { // Stats below correspond to similarly-named fields in the WebRTC stats spec. - // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats uint64_t total_samples_received = 0; uint64_t concealed_samples = 0; uint64_t concealment_events = 0; diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 2030380918..6995db8093 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -399,13 +399,14 @@ class RTC_EXPORT RTCReceivedRtpStreamStats : public RTCRTPStreamStats { // TODO(hbos) The following fields need to be added and migrated // both from RTCInboundRtpStreamStats and RTCRemoteInboundRtpStreamStats: - // packetsReceived, packetsDiscarded, packetsRepaired, burstPacketsLost, + // packetsReceived, packetsRepaired, burstPacketsLost, // burstPacketDiscarded, burstLossCount, burstDiscardCount, burstLossRate, // burstDiscardRate, gapLossRate, gapDiscardRate, framesDropped, // partialFramesLost, fullFramesLost // crbug.com/webrtc/12532 RTCStatsMember jitter; RTCStatsMember packets_lost; // Signed per RFC 3550 + RTCStatsMember packets_discarded; protected: RTCReceivedRtpStreamStats(const std::string&& id, int64_t timestamp_us); @@ -463,8 +464,6 @@ class RTC_EXPORT RTCInboundRTPStreamStats final // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 RTCStatsMember round_trip_time; // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 - RTCStatsMember packets_discarded; - // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 RTCStatsMember packets_repaired; // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 RTCStatsMember burst_packets_lost; @@ -569,7 +568,7 @@ class RTC_EXPORT RTCRemoteInboundRtpStreamStats final ~RTCRemoteInboundRtpStreamStats() override; // TODO(hbos): The following RTCReceivedRtpStreamStats metrics should also be - // implemented: packetsReceived, packetsDiscarded, packetsRepaired, + // implemented: packetsReceived, packetsRepaired, // burstPacketsLost, burstPacketsDiscarded, burstLossCount, burstDiscardCount, // burstLossRate, burstDiscardRate, gapLossRate and gapDiscardRate. // RTCRemoteInboundRtpStreamStats diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index f243fa67db..f3843812ee 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -298,6 +298,7 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats( // Get jitter buffer and total delay (alg + jitter + playout) stats. auto ns = channel_receive_->GetNetworkStatistics(get_and_clear_legacy_stats); + stats.packets_discarded = ns.packetsDiscarded; stats.fec_packets_received = ns.fecPacketsReceived; stats.fec_packets_discarded = ns.fecPacketsDiscarded; stats.jitter_buffer_ms = ns.currentBufferSize; diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc index fb5f1cb876..1d6183a1d4 100644 --- a/audio/audio_receive_stream_unittest.cc +++ b/audio/audio_receive_stream_unittest.cc @@ -68,8 +68,34 @@ const std::pair kReceiveCodec = { 123, {"codec_name_recv", 96000, 0}}; const NetworkStatistics kNetworkStats = { - 123, 456, false, 789012, 3456, 123, 456, 789, 543, 123, 432, 321, 123, - 101, 789, 12, 345, 678, 901, 0, -1, -1, 0, 0, 0, 0}; + /*currentBufferSize=*/123, + /*preferredBufferSize=*/456, + /*jitterPeaksFound=*/false, + /*totalSamplesReceived=*/789012, + /*concealedSamples=*/3456, + /*silentConcealedSamples=*/123, + /*concealmentEvents=*/456, + /*jitterBufferDelayMs=*/789, + /*jitterBufferEmittedCount=*/543, + /*jitterBufferTargetDelayMs=*/123, + /*insertedSamplesForDeceleration=*/432, + /*removedSamplesForAcceleration=*/321, + /*fecPacketsReceived=*/123, + /*fecPacketsDiscarded=*/101, + /*packetsDiscarded=*/989, + /*currentExpandRate=*/789, + /*currentSpeechExpandRate=*/12, + /*currentPreemptiveRate=*/345, + /*currentAccelerateRate =*/678, + /*currentSecondaryDecodedRate=*/901, + /*currentSecondaryDiscardedRate=*/0, + /*meanWaitingTimeMs=*/-1, + /*maxWaitingTimeMs=*/-1, + /*packetBufferFlushes=*/0, + /*delayedPacketOutageSamples=*/0, + /*relativePacketArrivalDelayMs=*/135, + /*interruptionCount=*/-1, + /*totalInterruptionDurationMs=*/-1}; const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest(); struct ConfigHelper { @@ -253,6 +279,13 @@ TEST(AudioReceiveStreamTest, GetStats) { EXPECT_EQ(static_cast(kNetworkStats.jitterBufferTargetDelayMs) / static_cast(rtc::kNumMillisecsPerSec), stats.jitter_buffer_target_delay_seconds); + EXPECT_EQ(kNetworkStats.insertedSamplesForDeceleration, + stats.inserted_samples_for_deceleration); + EXPECT_EQ(kNetworkStats.removedSamplesForAcceleration, + stats.removed_samples_for_acceleration); + EXPECT_EQ(kNetworkStats.fecPacketsReceived, stats.fec_packets_received); + EXPECT_EQ(kNetworkStats.fecPacketsDiscarded, stats.fec_packets_discarded); + EXPECT_EQ(kNetworkStats.packetsDiscarded, stats.packets_discarded); EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate); EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate), stats.speech_expand_rate); @@ -264,6 +297,16 @@ TEST(AudioReceiveStreamTest, GetStats) { stats.accelerate_rate); EXPECT_EQ(Q14ToFloat(kNetworkStats.currentPreemptiveRate), stats.preemptive_expand_rate); + EXPECT_EQ(kNetworkStats.packetBufferFlushes, stats.jitter_buffer_flushes); + EXPECT_EQ(kNetworkStats.delayedPacketOutageSamples, + stats.delayed_packet_outage_samples); + EXPECT_EQ(static_cast(kNetworkStats.relativePacketArrivalDelayMs) / + static_cast(rtc::kNumMillisecsPerSec), + stats.relative_packet_arrival_delay_seconds); + EXPECT_EQ(kNetworkStats.interruptionCount, stats.interruption_count); + EXPECT_EQ(kNetworkStats.totalInterruptionDurationMs, + stats.total_interruption_duration_ms); + EXPECT_EQ(kAudioDecodeStats.calls_to_silence_generator, stats.decoding_calls_to_silence_generator); EXPECT_EQ(kAudioDecodeStats.calls_to_neteq, stats.decoding_calls_to_neteq); diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h index 8403e6bea0..182cd49679 100644 --- a/call/audio_receive_stream.h +++ b/call/audio_receive_stream.h @@ -39,6 +39,7 @@ class AudioReceiveStream : public MediaReceiveStream { uint64_t fec_packets_received = 0; uint64_t fec_packets_discarded = 0; uint32_t packets_lost = 0; + uint64_t packets_discarded = 0; uint32_t nacks_sent = 0; std::string codec_name; absl::optional codec_payload_type; diff --git a/media/base/media_channel.h b/media/base/media_channel.h index 7b9a6f138c..c6bbc0735f 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -471,7 +471,7 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { int delay_estimate_ms = 0; int audio_level = 0; // Stats below correspond to similarly-named fields in the WebRTC stats spec. - // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats double total_output_energy = 0.0; uint64_t total_samples_received = 0; double total_output_duration = 0.0; @@ -483,6 +483,9 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { uint64_t removed_samples_for_acceleration = 0; uint64_t fec_packets_received = 0; uint64_t fec_packets_discarded = 0; + // Stats below correspond to similarly-named fields in the WebRTC stats spec. + // https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats + uint64_t packets_discarded = 0; // Stats below DO NOT correspond directly to anything in the WebRTC stats // fraction of synthesized audio inserted through expansion. float expand_rate = 0.0f; diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index aa80c8724a..7ce61b01f9 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc @@ -2365,6 +2365,7 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info, rinfo.fec_packets_received = stats.fec_packets_received; rinfo.fec_packets_discarded = stats.fec_packets_discarded; rinfo.packets_lost = stats.packets_lost; + rinfo.packets_discarded = stats.packets_discarded; rinfo.codec_name = stats.codec_name; rinfo.codec_payload_type = stats.codec_payload_type; rinfo.jitter_ms = stats.jitter_ms; diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc index 3214ce6f7b..80cb3c5ccf 100644 --- a/modules/audio_coding/acm2/acm_receiver.cc +++ b/modules/audio_coding/acm2/acm_receiver.cc @@ -307,6 +307,8 @@ void AcmReceiver::GetNetworkStatistics( neteq_->GetOperationsAndState(); acm_stat->packetBufferFlushes = neteq_operations_and_state.packet_buffer_flushes; + acm_stat->packetsDiscarded = + neteq_operations_and_state.discarded_primary_packets; } int AcmReceiver::EnableNack(size_t max_nack_list_size) { diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h index a7210dadcb..e5598e3c45 100644 --- a/modules/audio_coding/include/audio_coding_module_typedefs.h +++ b/modules/audio_coding/include/audio_coding_module_typedefs.h @@ -81,19 +81,22 @@ struct NetworkStatistics { // adding extra delay due to "peaky jitter" bool jitterPeaksFound; // Stats below correspond to similarly-named fields in the WebRTC stats spec. - // https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats uint64_t totalSamplesReceived; uint64_t concealedSamples; uint64_t silentConcealedSamples; uint64_t concealmentEvents; uint64_t jitterBufferDelayMs; uint64_t jitterBufferEmittedCount; - // Non standard stats propagated to spec complaint GetStats API. - uint64_t jitterBufferTargetDelayMs; uint64_t insertedSamplesForDeceleration; uint64_t removedSamplesForAcceleration; uint64_t fecPacketsReceived; uint64_t fecPacketsDiscarded; + // Stats below correspond to similarly-named fields in the WebRTC stats spec. + // https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats + uint64_t packetsDiscarded; + // Non standard stats propagated to spec complaint GetStats API. + uint64_t jitterBufferTargetDelayMs; // Stats below DO NOT correspond directly to anything in the WebRTC stats // fraction (of original stream) of synthesized audio inserted through // expansion (in Q14) diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 6599d0ef49..ee5826486c 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -392,6 +392,7 @@ std::unique_ptr CreateInboundAudioStreamStats( voice_receiver_info.fec_packets_received; inbound_audio->fec_packets_discarded = voice_receiver_info.fec_packets_discarded; + inbound_audio->packets_discarded = voice_receiver_info.packets_discarded; return inbound_audio; } diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 2ac0737715..4ec86ab24f 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -1953,6 +1953,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { cricket::SsrcReceiverInfo()); voice_media_info.receivers[0].local_stats[0].ssrc = 1; voice_media_info.receivers[0].packets_lost = -1; // Signed per RFC3550 + voice_media_info.receivers[0].packets_discarded = 7788; voice_media_info.receivers[0].packets_rcvd = 2; voice_media_info.receivers[0].nacks_sent = 5; voice_media_info.receivers[0].fec_packets_discarded = 5566; @@ -2009,6 +2010,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { expected_audio.bytes_received = 3; expected_audio.header_bytes_received = 4; expected_audio.packets_lost = -1; + expected_audio.packets_discarded = 7788; // |expected_audio.last_packet_received_timestamp| should be undefined. expected_audio.jitter = 4.5; expected_audio.jitter_buffer_delay = 1.0; diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index 2dfe1b5cd5..df7b8a3ff0 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -800,7 +800,9 @@ class RTCStatsReportVerifier { bool VerifyRTCInboundRTPStreamStats( const RTCInboundRTPStreamStats& inbound_stream) { RTCStatsVerifier verifier(report_, &inbound_stream); - VerifyRTCReceivedRtpStreamStats(inbound_stream, verifier); + VerifyRTCReceivedRtpStreamStats(inbound_stream, verifier, + inbound_stream.media_type.is_defined() && + *inbound_stream.media_type == "audio"); verifier.TestMemberIsOptionalIDReference( inbound_stream.remote_id, RTCRemoteOutboundRtpStreamStats::kType); if (inbound_stream.media_type.is_defined() && @@ -884,7 +886,6 @@ class RTCStatsReportVerifier { verifier.TestMemberIsUndefined(inbound_stream.frames_received); } verifier.TestMemberIsUndefined(inbound_stream.round_trip_time); - verifier.TestMemberIsUndefined(inbound_stream.packets_discarded); verifier.TestMemberIsUndefined(inbound_stream.packets_repaired); verifier.TestMemberIsUndefined(inbound_stream.burst_packets_lost); verifier.TestMemberIsUndefined(inbound_stream.burst_packets_discarded); @@ -1022,16 +1023,23 @@ class RTCStatsReportVerifier { void VerifyRTCReceivedRtpStreamStats( const RTCReceivedRtpStreamStats& received_rtp, - RTCStatsVerifier& verifier) { + RTCStatsVerifier& verifier, + bool packets_discarded_defined) { VerifyRTCRTPStreamStats(received_rtp, verifier); verifier.TestMemberIsNonNegative(received_rtp.jitter); verifier.TestMemberIsDefined(received_rtp.packets_lost); + if (packets_discarded_defined) { + verifier.TestMemberIsNonNegative( + received_rtp.packets_discarded); + } else { + verifier.TestMemberIsUndefined(received_rtp.packets_discarded); + } } bool VerifyRTCRemoteInboundRtpStreamStats( const RTCRemoteInboundRtpStreamStats& remote_inbound_stream) { RTCStatsVerifier verifier(report_, &remote_inbound_stream); - VerifyRTCReceivedRtpStreamStats(remote_inbound_stream, verifier); + VerifyRTCReceivedRtpStreamStats(remote_inbound_stream, verifier, false); verifier.TestMemberIsDefined(remote_inbound_stream.fraction_lost); verifier.TestMemberIsIDReference(remote_inbound_stream.local_id, RTCOutboundRTPStreamStats::kType); diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index a2d7aa0b07..6af724e55b 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -582,7 +582,8 @@ RTCRTPStreamStats::~RTCRTPStreamStats() {} WEBRTC_RTCSTATS_IMPL( RTCReceivedRtpStreamStats, RTCRTPStreamStats, "received-rtp", &jitter, - &packets_lost) + &packets_lost, + &packets_discarded) // clang-format on RTCReceivedRtpStreamStats::RTCReceivedRtpStreamStats(const std::string&& id, @@ -593,13 +594,15 @@ RTCReceivedRtpStreamStats::RTCReceivedRtpStreamStats(std::string&& id, int64_t timestamp_us) : RTCRTPStreamStats(std::move(id), timestamp_us), jitter("jitter"), - packets_lost("packetsLost") {} + packets_lost("packetsLost"), + packets_discarded("packetsDiscarded") {} RTCReceivedRtpStreamStats::RTCReceivedRtpStreamStats( const RTCReceivedRtpStreamStats& other) : RTCRTPStreamStats(other), jitter(other.jitter), - packets_lost(other.packets_lost) {} + packets_lost(other.packets_lost), + packets_discarded(other.packets_discarded) {} RTCReceivedRtpStreamStats::~RTCReceivedRtpStreamStats() {} @@ -650,7 +653,6 @@ WEBRTC_RTCSTATS_IMPL( &total_samples_duration, &frames_received, &round_trip_time, - &packets_discarded, &packets_repaired, &burst_packets_lost, &burst_packets_discarded, @@ -706,7 +708,6 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(std::string&& id, total_samples_duration("totalSamplesDuration"), frames_received("framesReceived"), round_trip_time("roundTripTime"), - packets_discarded("packetsDiscarded"), packets_repaired("packetsRepaired"), burst_packets_lost("burstPacketsLost"), burst_packets_discarded("burstPacketsDiscarded"), @@ -758,7 +759,6 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats( total_samples_duration(other.total_samples_duration), frames_received(other.frames_received), round_trip_time(other.round_trip_time), - packets_discarded(other.packets_discarded), packets_repaired(other.packets_repaired), burst_packets_lost(other.burst_packets_lost), burst_packets_discarded(other.burst_packets_discarded),