Implement RTCOutboundRtpStreamStats.retransmitted[Bytes/Packets]Sent.

Spec: https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent

These are already existed in StreamDataCounters. This CL takes care of
the plumbing of these values to the standard stats collector.

TBR=solenberg@webrtc.org

Bug: webrtc:10447
Change-Id: I27d6c3ee3ab627d306303e6ee67e586ddf31cc81
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132012
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27663}
diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h
index 81ec084..4ddfa93 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -442,7 +442,9 @@
   ~RTCOutboundRTPStreamStats() override;
 
   RTCStatsMember<uint32_t> packets_sent;
+  RTCStatsMember<uint64_t> retransmitted_packets_sent;
   RTCStatsMember<uint64_t> bytes_sent;
+  RTCStatsMember<uint64_t> retransmitted_bytes_sent;
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066
   RTCStatsMember<double> target_bitrate;
   RTCStatsMember<uint32_t> frames_encoded;
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 7804f55..283fd9a 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -389,7 +389,9 @@
 
   webrtc::CallSendStatistics call_stats = channel_send_->GetRTCPStatistics();
   stats.bytes_sent = call_stats.bytesSent;
+  stats.retransmitted_bytes_sent = call_stats.retransmitted_bytes_sent;
   stats.packets_sent = call_stats.packetsSent;
+  stats.retransmitted_packets_sent = call_stats.retransmitted_packets_sent;
   // RTT isn't known until a RTCP report is received. Until then, VoiceEngine
   // returns 0 to indicate an error value.
   if (call_stats.rttMs > 0) {
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index 4e0094e..99e3f90 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -1070,17 +1070,22 @@
   CallSendStatistics stats = {0};
   stats.rttMs = GetRTT();
 
-  size_t bytesSent(0);
-  uint32_t packetsSent(0);
-
-  if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
-    RTC_DLOG(LS_WARNING)
-        << "GetRTPStatistics() failed to retrieve RTP datacounters"
-        << " => output will not be complete";
-  }
-
-  stats.bytesSent = bytesSent;
-  stats.packetsSent = packetsSent;
+  StreamDataCounters rtp_stats;
+  StreamDataCounters rtx_stats;
+  _rtpRtcpModule->GetSendStreamDataCounters(&rtp_stats, &rtx_stats);
+  // TODO(https://crbug.com/webrtc/10525): Bytes sent should only include
+  // payload bytes, not header and padding bytes.
+  stats.bytesSent =
+      rtp_stats.transmitted.payload_bytes +
+      rtp_stats.transmitted.padding_bytes + rtp_stats.transmitted.header_bytes +
+      rtx_stats.transmitted.payload_bytes +
+      rtx_stats.transmitted.padding_bytes + rtx_stats.transmitted.header_bytes;
+  // TODO(https://crbug.com/webrtc/10555): RTX retransmissions should show up in
+  // separate outbound-rtp stream objects.
+  stats.retransmitted_bytes_sent = rtp_stats.retransmitted.payload_bytes;
+  stats.packetsSent =
+      rtp_stats.transmitted.packets + rtx_stats.transmitted.packets;
+  stats.retransmitted_packets_sent = rtp_stats.retransmitted.packets;
 
   return stats;
 }
diff --git a/audio/channel_send.h b/audio/channel_send.h
index 761e4b2..45f7b1e 100644
--- a/audio/channel_send.h
+++ b/audio/channel_send.h
@@ -35,7 +35,11 @@
 struct CallSendStatistics {
   int64_t rttMs;
   size_t bytesSent;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent
+  uint64_t retransmitted_bytes_sent;
   int packetsSent;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent
+  uint64_t retransmitted_packets_sent;
 };
 
 // See section 6.4.2 in http://www.ietf.org/rfc/rfc3550.txt for details.
diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h
index 08a50c8..7e17b7c 100644
--- a/call/audio_send_stream.h
+++ b/call/audio_send_stream.h
@@ -42,7 +42,11 @@
     // TODO(solenberg): Harmonize naming and defaults with receive stream stats.
     uint32_t local_ssrc = 0;
     int64_t bytes_sent = 0;
+    // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent
+    uint64_t retransmitted_bytes_sent = 0;
     int32_t packets_sent = 0;
+    // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent
+    uint64_t retransmitted_packets_sent = 0;
     int32_t packets_lost = -1;
     float fraction_lost = -1.0f;
     std::string codec_name;
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index c21f89e..710fd1a 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -387,7 +387,11 @@
     }
   }
   int64_t bytes_sent = 0;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent
+  uint64_t retransmitted_bytes_sent = 0;
   int packets_sent = 0;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent
+  uint64_t retransmitted_packets_sent = 0;
   int packets_lost = 0;
   float fraction_lost = 0.0f;
   int64_t rtt_ms = 0;
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 5240b28..234c7ab 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -2267,10 +2267,20 @@
        it != stats.substreams.end(); ++it) {
     // TODO(pbos): Wire up additional stats, such as padding bytes.
     webrtc::VideoSendStream::StreamStats stream_stats = it->second;
+    // TODO(http://crbug.com/webrtc/10525): Bytes sent should only include
+    // payload bytes, not header and padding bytes.
     info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes +
                        stream_stats.rtp_stats.transmitted.header_bytes +
                        stream_stats.rtp_stats.transmitted.padding_bytes;
     info.packets_sent += stream_stats.rtp_stats.transmitted.packets;
+    // TODO(https://crbug.com/webrtc/10555): RTX retransmissions should show up
+    // in separate outbound-rtp stream objects.
+    if (!stream_stats.is_rtx && !stream_stats.is_flexfec) {
+      info.retransmitted_bytes_sent +=
+          stream_stats.rtp_stats.retransmitted.payload_bytes;
+      info.retransmitted_packets_sent +=
+          stream_stats.rtp_stats.retransmitted.packets;
+    }
     info.packets_lost += stream_stats.rtcp_stats.packets_lost;
     if (stream_stats.width > info.send_frame_width)
       info.send_frame_width = stream_stats.width;
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index 0765427..9110d55 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -2192,7 +2192,9 @@
     VoiceSenderInfo sinfo;
     sinfo.add_ssrc(stats.local_ssrc);
     sinfo.bytes_sent = stats.bytes_sent;
+    sinfo.retransmitted_bytes_sent = stats.retransmitted_bytes_sent;
     sinfo.packets_sent = stats.packets_sent;
+    sinfo.retransmitted_packets_sent = stats.retransmitted_packets_sent;
     sinfo.packets_lost = stats.packets_lost;
     sinfo.fraction_lost = stats.fraction_lost;
     sinfo.codec_name = stats.codec_name;
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index f716718..a15558d 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -542,6 +542,8 @@
   rtp_sender_->GetDataCounters(&rtp_stats, &rtx_stats);
 
   if (bytes_sent) {
+    // TODO(http://crbug.com/webrtc/10525): Bytes sent should only include
+    // payload bytes, not header and padding bytes.
     *bytes_sent = rtp_stats.transmitted.payload_bytes +
                   rtp_stats.transmitted.padding_bytes +
                   rtp_stats.transmitted.header_bytes +
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index 3bf8566..611dfe3 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -295,8 +295,12 @@
   outbound_stats->is_remote = false;
   outbound_stats->packets_sent =
       static_cast<uint32_t>(media_sender_info.packets_sent);
+  outbound_stats->retransmitted_packets_sent =
+      media_sender_info.retransmitted_packets_sent;
   outbound_stats->bytes_sent =
       static_cast<uint64_t>(media_sender_info.bytes_sent);
+  outbound_stats->retransmitted_bytes_sent =
+      media_sender_info.retransmitted_bytes_sent;
 }
 
 void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index 82cd241..ba80732e 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -1771,7 +1771,9 @@
   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
   voice_media_info.senders[0].local_stats[0].ssrc = 1;
   voice_media_info.senders[0].packets_sent = 2;
+  voice_media_info.senders[0].retransmitted_packets_sent = 20;
   voice_media_info.senders[0].bytes_sent = 3;
+  voice_media_info.senders[0].retransmitted_bytes_sent = 30;
   voice_media_info.senders[0].codec_payload_type = 42;
 
   RtpCodecParameters codec_parameters;
@@ -1799,7 +1801,9 @@
   expected_audio.transport_id = "RTCTransport_TransportName_1";
   expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
   expected_audio.packets_sent = 2;
+  expected_audio.retransmitted_packets_sent = 20;
   expected_audio.bytes_sent = 3;
+  expected_audio.retransmitted_bytes_sent = 30;
 
   ASSERT_TRUE(report->Get(expected_audio.id()));
   EXPECT_EQ(
@@ -1825,7 +1829,9 @@
   video_media_info.senders[0].plis_rcvd = 3;
   video_media_info.senders[0].nacks_rcvd = 4;
   video_media_info.senders[0].packets_sent = 5;
+  video_media_info.senders[0].retransmitted_packets_sent = 50;
   video_media_info.senders[0].bytes_sent = 6;
+  video_media_info.senders[0].retransmitted_bytes_sent = 60;
   video_media_info.senders[0].codec_payload_type = 42;
   video_media_info.senders[0].frames_encoded = 8;
   video_media_info.senders[0].total_encode_time_ms = 9000;
@@ -1865,7 +1871,9 @@
   expected_video.pli_count = 3;
   expected_video.nack_count = 4;
   expected_video.packets_sent = 5;
+  expected_video.retransmitted_packets_sent = 50;
   expected_video.bytes_sent = 6;
+  expected_video.retransmitted_bytes_sent = 60;
   expected_video.frames_encoded = 8;
   expected_video.total_encode_time = 9.0;
   // |expected_video.content_type| should be undefined.
@@ -2038,7 +2046,9 @@
   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
   voice_media_info.senders[0].local_stats[0].ssrc = 1;
   voice_media_info.senders[0].packets_sent = 2;
+  voice_media_info.senders[0].retransmitted_packets_sent = 20;
   voice_media_info.senders[0].bytes_sent = 3;
+  voice_media_info.senders[0].retransmitted_bytes_sent = 30;
   voice_media_info.senders[0].codec_payload_type = 42;
 
   RtpCodecParameters codec_parameters;
@@ -2067,7 +2077,9 @@
   expected_audio.transport_id = "RTCTransport_TransportName_1";
   expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
   expected_audio.packets_sent = 2;
+  expected_audio.retransmitted_packets_sent = 20;
   expected_audio.bytes_sent = 3;
+  expected_audio.retransmitted_bytes_sent = 30;
 
   ASSERT_TRUE(report->Get(expected_audio.id()));
   EXPECT_EQ(
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc
index 9b1b6d0..bb13c20 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -762,7 +762,11 @@
       verifier.TestMemberIsUndefined(outbound_stream.qp_sum);
     }
     verifier.TestMemberIsNonNegative<uint32_t>(outbound_stream.packets_sent);
+    verifier.TestMemberIsNonNegative<uint64_t>(
+        outbound_stream.retransmitted_packets_sent);
     verifier.TestMemberIsNonNegative<uint64_t>(outbound_stream.bytes_sent);
+    verifier.TestMemberIsNonNegative<uint64_t>(
+        outbound_stream.retransmitted_bytes_sent);
     verifier.TestMemberIsUndefined(outbound_stream.target_bitrate);
     if (outbound_stream.media_type.is_defined() &&
         *outbound_stream.media_type == "video") {
diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc
index 4bf3e68..89d5a85 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -652,7 +652,9 @@
 WEBRTC_RTCSTATS_IMPL(
     RTCOutboundRTPStreamStats, RTCRTPStreamStats, "outbound-rtp",
     &packets_sent,
+    &retransmitted_packets_sent,
     &bytes_sent,
+    &retransmitted_bytes_sent,
     &target_bitrate,
     &frames_encoded,
     &total_encode_time,
@@ -667,7 +669,9 @@
                                                      int64_t timestamp_us)
     : RTCRTPStreamStats(std::move(id), timestamp_us),
       packets_sent("packetsSent"),
+      retransmitted_packets_sent("retransmittedPacketsSent"),
       bytes_sent("bytesSent"),
+      retransmitted_bytes_sent("retransmittedBytesSent"),
       target_bitrate("targetBitrate"),
       frames_encoded("framesEncoded"),
       total_encode_time("totalEncodeTime"),
@@ -677,7 +681,9 @@
     const RTCOutboundRTPStreamStats& other)
     : RTCRTPStreamStats(other),
       packets_sent(other.packets_sent),
+      retransmitted_packets_sent(other.retransmitted_packets_sent),
       bytes_sent(other.bytes_sent),
+      retransmitted_bytes_sent(other.retransmitted_bytes_sent),
       target_bitrate(other.target_bitrate),
       frames_encoded(other.frames_encoded),
       total_encode_time(other.total_encode_time),