Wire up RTCOutboundRtpStreamStats.totalEncodeTime.

This is a follow-up to
https://webrtc-review.googlesource.com/c/src/+/130517 that calculated
this metric.

This CL is purely plumbing, exposing
VideoSendStream::total_encode_time_ms in standard getStats() as
RTCOutboundRtpStreamStats.totalEncodeTime (in seconds):
https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-totalencodetime

Bug: webrtc:10448
Change-Id: I715f1ef937e441169dee55b5e8d4fbf98811c5f3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131940
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27501}
diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h
index e07e5a0..158ea92 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -437,6 +437,7 @@
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066
   RTCStatsMember<double> target_bitrate;
   RTCStatsMember<uint32_t> frames_encoded;
+  RTCStatsMember<double> total_encode_time;
 };
 
 // https://w3c.github.io/webrtc-stats/#transportstats-dict*
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index 617af32..b64803b 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -527,6 +527,8 @@
   int avg_encode_ms = 0;
   int encode_usage_percent = 0;
   uint32_t frames_encoded = 0;
+  // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-totalencodetime
+  uint64_t total_encode_time_ms = 0;
   bool has_entered_low_resolution = false;
   absl::optional<uint64_t> qp_sum;
   webrtc::VideoContentType content_type = webrtc::VideoContentType::UNSPECIFIED;
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index b3abf00..2f0cfe4 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -2243,6 +2243,7 @@
   info.avg_encode_ms = stats.avg_encode_time_ms;
   info.encode_usage_percent = stats.encode_usage_percent;
   info.frames_encoded = stats.frames_encoded;
+  info.total_encode_time_ms = stats.total_encode_time_ms;
   info.qp_sum = stats.qp_sum;
 
   info.nominal_bitrate = stats.media_bitrate_bps;
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index a604663..df2f09c 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -319,6 +319,9 @@
   if (video_sender_info.qp_sum)
     outbound_video->qp_sum = *video_sender_info.qp_sum;
   outbound_video->frames_encoded = video_sender_info.frames_encoded;
+  outbound_video->total_encode_time =
+      static_cast<double>(video_sender_info.total_encode_time_ms) /
+      rtc::kNumMillisecsPerSec;
 }
 
 void ProduceCertificateStatsFromSSLCertificateStats(
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index 64a5ec6..ec2a9eb 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -1804,6 +1804,7 @@
   video_media_info.senders[0].bytes_sent = 6;
   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;
   video_media_info.senders[0].qp_sum = absl::nullopt;
 
   RtpCodecParameters codec_parameters;
@@ -1841,6 +1842,7 @@
   expected_video.packets_sent = 5;
   expected_video.bytes_sent = 6;
   expected_video.frames_encoded = 8;
+  expected_video.total_encode_time = 9.0;
   // |expected_video.qp_sum| should be undefined.
   ASSERT_TRUE(report->Get(expected_video.id()));
 
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc
index 5fd353c..13eb213 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -762,8 +762,11 @@
     if (outbound_stream.media_type.is_defined() &&
         *outbound_stream.media_type == "video") {
       verifier.TestMemberIsDefined(outbound_stream.frames_encoded);
+      verifier.TestMemberIsNonNegative<double>(
+          outbound_stream.total_encode_time);
     } else {
       verifier.TestMemberIsUndefined(outbound_stream.frames_encoded);
+      verifier.TestMemberIsUndefined(outbound_stream.total_encode_time);
     }
     return verifier.ExpectAllMembersSuccessfullyTested();
   }
diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc
index 69b5e0a..de317aa 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -644,7 +644,8 @@
     &packets_sent,
     &bytes_sent,
     &target_bitrate,
-    &frames_encoded)
+    &frames_encoded,
+    &total_encode_time)
 // clang-format on
 
 RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(const std::string& id,
@@ -657,7 +658,8 @@
       packets_sent("packetsSent"),
       bytes_sent("bytesSent"),
       target_bitrate("targetBitrate"),
-      frames_encoded("framesEncoded") {}
+      frames_encoded("framesEncoded"),
+      total_encode_time("totalEncodeTime") {}
 
 RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
     const RTCOutboundRTPStreamStats& other)
@@ -665,7 +667,8 @@
       packets_sent(other.packets_sent),
       bytes_sent(other.bytes_sent),
       target_bitrate(other.target_bitrate),
-      frames_encoded(other.frames_encoded) {}
+      frames_encoded(other.frames_encoded),
+      total_encode_time(other.total_encode_time) {}
 
 RTCOutboundRTPStreamStats::~RTCOutboundRTPStreamStats() {}