Adding packetsDiscarded to RTCReceivedRtpStreamStats.

Bug: webrtc:12532, webrtc:7065, webrtc:8199
Change-Id: I3ba62ec65e5660e98787f629aec3ee7a0889207a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/225261
Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Commit-Queue: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34468}
diff --git a/api/neteq/neteq.h b/api/neteq/neteq.h
index ea7079e..81340f1 100644
--- a/api/neteq/neteq.h
+++ b/api/neteq/neteq.h
@@ -60,7 +60,7 @@
 // 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 2030380..6995db8 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -399,13 +399,14 @@
 
   // 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<double> jitter;
   RTCStatsMember<int32_t> packets_lost;  // Signed per RFC 3550
+  RTCStatsMember<uint64_t> packets_discarded;
 
  protected:
   RTCReceivedRtpStreamStats(const std::string&& id, int64_t timestamp_us);
@@ -463,8 +464,6 @@
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065
   RTCStatsMember<double> round_trip_time;
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065
-  RTCStatsMember<uint32_t> packets_discarded;
-  // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065
   RTCStatsMember<uint32_t> packets_repaired;
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065
   RTCStatsMember<uint32_t> burst_packets_lost;
@@ -569,7 +568,7 @@
   ~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 f243fa6..f384381 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -298,6 +298,7 @@
 
   // 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 fb5f1cb..1d6183a 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -68,8 +68,34 @@
     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 @@
     EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferTargetDelayMs) /
                   static_cast<double>(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 @@
               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<double>(kNetworkStats.relativePacketArrivalDelayMs) /
+                  static_cast<double>(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 8403e6b..182cd49 100644
--- a/call/audio_receive_stream.h
+++ b/call/audio_receive_stream.h
@@ -39,6 +39,7 @@
     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<int> codec_payload_type;
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index 7b9a6f1..c6bbc07 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -471,7 +471,7 @@
   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 @@
   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 aa80c87..7ce61b0 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -2365,6 +2365,7 @@
     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 3214ce6..80cb3c5 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -307,6 +307,8 @@
       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 a7210da..e5598e3 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 @@
   // 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 6599d0e..ee58264 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -392,6 +392,7 @@
       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 2ac0737..4ec86ab 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -1953,6 +1953,7 @@
       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 @@
   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 2dfe1b5..df7b8a3 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -800,7 +800,9 @@
   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 @@
       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 @@
 
   void VerifyRTCReceivedRtpStreamStats(
       const RTCReceivedRtpStreamStats& received_rtp,
-      RTCStatsVerifier& verifier) {
+      RTCStatsVerifier& verifier,
+      bool packets_discarded_defined) {
     VerifyRTCRTPStreamStats(received_rtp, verifier);
     verifier.TestMemberIsNonNegative<double>(received_rtp.jitter);
     verifier.TestMemberIsDefined(received_rtp.packets_lost);
+    if (packets_discarded_defined) {
+      verifier.TestMemberIsNonNegative<uint64_t>(
+          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 a2d7aa0..6af724e 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -582,7 +582,8 @@
 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 @@
                                                      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 @@
     &total_samples_duration,
     &frames_received,
     &round_trip_time,
-    &packets_discarded,
     &packets_repaired,
     &burst_packets_lost,
     &burst_packets_discarded,
@@ -706,7 +708,6 @@
       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 @@
       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),