Reland "[GetStats] Expose video codec implementation in standardized metrics."

This is a reland of 2b9fa09fa3e3379fd8e76490c394f25670352ef2.

It got reverted because I forgot to whitelist the new metrics in chromium,
which has now been done:
https://chromium-review.googlesource.com/c/chromium/src/+/1760209
Relanding requires no changes to the CL.

Original change's description:
> [GetStats] Expose video codec implementation in standardized metrics.
>
> Spec issue: https://github.com/w3c/webrtc-stats/issues/445
> Spec PR: https://github.com/w3c/webrtc-stats/pull/473
>
> Now that the spec's RTCCodecStats.implementation has moved to
> RTCOutboundRtpStreamStats.encoderImplementation and
> RTCInboundRtpStreamStats.decoderImplementation, this CL implements them
> using the same string that the legacy getStats() API used.
>
> Bug: webrtc:10890
> Change-Id: Ic43ce44735453626791959df3061ee253356015a
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149168
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#28877}

TBR=ilnik@webrtc.org

Bug: webrtc:10890
Change-Id: Ib874b608856c2795b1ca08f6af43c61dd859ea21
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149800
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28887}
diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h
index 8955c4e..b492203 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -122,8 +122,6 @@
   RTCStatsMember<uint32_t> channels;
   // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7061
   RTCStatsMember<std::string> sdp_fmtp_line;
-  // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7061
-  RTCStatsMember<std::string> implementation;
 };
 
 // https://w3c.github.io/webrtc-stats/#dcstats-dict*
@@ -447,6 +445,9 @@
   RTCStatsMember<double> total_decode_time;
   // https://henbos.github.io/webrtc-provisional-stats/#dom-rtcinboundrtpstreamstats-contenttype
   RTCStatsMember<std::string> content_type;
+  // TODO(hbos): This is only implemented for video; implement it for audio as
+  // well.
+  RTCStatsMember<std::string> decoder_implementation;
 };
 
 // https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict*
@@ -482,6 +483,9 @@
   RTCStatsMember<std::string> quality_limitation_reason;
   // https://henbos.github.io/webrtc-provisional-stats/#dom-rtcoutboundrtpstreamstats-contenttype
   RTCStatsMember<std::string> content_type;
+  // TODO(hbos): This is only implemented for video; implement it for audio as
+  // well.
+  RTCStatsMember<std::string> encoder_implementation;
 };
 
 // TODO(https://crbug.com/webrtc/10671): Refactor the stats dictionaries to have
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index b0b0b88..4b2d393 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -546,7 +546,6 @@
   VideoSenderInfo();
   ~VideoSenderInfo();
   std::vector<SsrcGroup> ssrc_groups;
-  // TODO(hbos): Move this to |VideoMediaInfo::send_codecs|?
   std::string encoder_implementation_name;
   int firs_rcvd = 0;
   int plis_rcvd = 0;
@@ -584,7 +583,6 @@
   VideoReceiverInfo();
   ~VideoReceiverInfo();
   std::vector<SsrcGroup> ssrc_groups;
-  // TODO(hbos): Move this to |VideoMediaInfo::receive_codecs|?
   std::string decoder_implementation_name;
   int packets_concealed = 0;
   int firs_sent = 0;
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index 8336812..c1b4878 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -325,6 +325,10 @@
   // optional, support the "unspecified" value.
   if (video_receiver_info.content_type == VideoContentType::SCREENSHARE)
     inbound_video->content_type = RTCContentType::kScreenshare;
+  if (!video_receiver_info.decoder_implementation_name.empty()) {
+    inbound_video->decoder_implementation =
+        video_receiver_info.decoder_implementation_name;
+  }
 }
 
 // Provides the media independent counters (both audio and video).
@@ -398,6 +402,10 @@
   // optional, support the "unspecified" value.
   if (video_sender_info.content_type == VideoContentType::SCREENSHARE)
     outbound_video->content_type = RTCContentType::kScreenshare;
+  if (!video_sender_info.encoder_implementation_name.empty()) {
+    outbound_video->encoder_implementation =
+        video_sender_info.encoder_implementation_name;
+  }
 }
 
 std::unique_ptr<RTCRemoteInboundRtpStreamStats>
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index edbfac1..4d59e7c 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -1815,6 +1815,7 @@
   video_media_info.receivers[0].last_packet_received_timestamp_ms =
       absl::nullopt;
   video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
+  video_media_info.receivers[0].decoder_implementation_name = "";
 
   RtpCodecParameters codec_parameters;
   codec_parameters.payload_type = 42;
@@ -1852,6 +1853,7 @@
   expected_video.total_decode_time = 9.0;
   // |expected_video.last_packet_received_timestamp| should be undefined.
   // |expected_video.content_type| should be undefined.
+  // |expected_video.decoder_implementation| should be undefined.
 
   ASSERT_TRUE(report->Get(expected_video.id()));
   EXPECT_EQ(
@@ -1865,6 +1867,8 @@
   expected_video.last_packet_received_timestamp = 1.0;
   video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
   expected_video.content_type = "screenshare";
+  video_media_info.receivers[0].decoder_implementation_name = "libfoodecoder";
+  expected_video.decoder_implementation = "libfoodecoder";
   video_media_channel->SetStats(video_media_info);
 
   report = stats_->GetFreshStatsReport();
@@ -1958,6 +1962,7 @@
       QualityLimitationReason::kBandwidth;
   video_media_info.senders[0].qp_sum = absl::nullopt;
   video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
+  video_media_info.senders[0].encoder_implementation_name = "";
 
   RtpCodecParameters codec_parameters;
   codec_parameters.payload_type = 42;
@@ -2005,6 +2010,7 @@
   expected_video.quality_limitation_reason = "bandwidth";
   // |expected_video.content_type| should be undefined.
   // |expected_video.qp_sum| should be undefined.
+  // |expected_video.encoder_implementation| should be undefined.
   ASSERT_TRUE(report->Get(expected_video.id()));
 
   EXPECT_EQ(
@@ -2016,6 +2022,8 @@
   expected_video.qp_sum = 9;
   video_media_info.senders[0].content_type = VideoContentType::SCREENSHARE;
   expected_video.content_type = "screenshare";
+  video_media_info.senders[0].encoder_implementation_name = "libfooencoder";
+  expected_video.encoder_implementation = "libfooencoder";
   video_media_channel->SetStats(video_media_info);
 
   report = stats_->GetFreshStatsReport();
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc
index a723123..ddddb27 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -446,7 +446,6 @@
     verifier.TestMemberIsPositive<uint32_t>(codec.clock_rate);
     verifier.TestMemberIsUndefined(codec.channels);
     verifier.TestMemberIsUndefined(codec.sdp_fmtp_line);
-    verifier.TestMemberIsUndefined(codec.implementation);
     return verifier.ExpectAllMembersSuccessfullyTested();
   }
 
@@ -772,8 +771,10 @@
     if (inbound_stream.media_type.is_defined() &&
         *inbound_stream.media_type == "video") {
       verifier.TestMemberIsNonNegative<uint64_t>(inbound_stream.qp_sum);
+      verifier.TestMemberIsDefined(inbound_stream.decoder_implementation);
     } else {
       verifier.TestMemberIsUndefined(inbound_stream.qp_sum);
+      verifier.TestMemberIsUndefined(inbound_stream.decoder_implementation);
     }
     verifier.TestMemberIsNonNegative<uint32_t>(inbound_stream.packets_received);
     if (inbound_stream.media_type.is_defined() &&
@@ -859,6 +860,7 @@
       // The integration test is not set up to test screen share; don't require
       // this to be present.
       verifier.MarkMemberTested(outbound_stream.content_type, true);
+      verifier.TestMemberIsDefined(outbound_stream.encoder_implementation);
     } else {
       verifier.TestMemberIsUndefined(outbound_stream.frames_encoded);
       verifier.TestMemberIsUndefined(outbound_stream.key_frames_encoded);
@@ -869,6 +871,8 @@
       verifier.TestMemberIsUndefined(outbound_stream.total_packet_send_delay);
       verifier.TestMemberIsUndefined(outbound_stream.quality_limitation_reason);
       verifier.TestMemberIsUndefined(outbound_stream.content_type);
+      // TODO(hbos): Implement for audio as well.
+      verifier.TestMemberIsUndefined(outbound_stream.encoder_implementation);
     }
     return verifier.ExpectAllMembersSuccessfullyTested();
   }
diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc
index 8a89d76..ead0ebf 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -96,8 +96,7 @@
     &mime_type,
     &clock_rate,
     &channels,
-    &sdp_fmtp_line,
-    &implementation)
+    &sdp_fmtp_line)
 // clang-format on
 
 RTCCodecStats::RTCCodecStats(const std::string& id, int64_t timestamp_us)
@@ -109,8 +108,7 @@
       mime_type("mimeType"),
       clock_rate("clockRate"),
       channels("channels"),
-      sdp_fmtp_line("sdpFmtpLine"),
-      implementation("implementation") {}
+      sdp_fmtp_line("sdpFmtpLine") {}
 
 RTCCodecStats::RTCCodecStats(const RTCCodecStats& other)
     : RTCStats(other.id(), other.timestamp_us()),
@@ -118,8 +116,7 @@
       mime_type(other.mime_type),
       clock_rate(other.clock_rate),
       channels(other.channels),
-      sdp_fmtp_line(other.sdp_fmtp_line),
-      implementation(other.implementation) {}
+      sdp_fmtp_line(other.sdp_fmtp_line) {}
 
 RTCCodecStats::~RTCCodecStats() {}
 
@@ -615,7 +612,8 @@
     &frames_decoded,
     &key_frames_decoded,
     &total_decode_time,
-    &content_type)
+    &content_type,
+    &decoder_implementation)
 // clang-format on
 
 RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(const std::string& id,
@@ -646,7 +644,8 @@
       frames_decoded("framesDecoded"),
       key_frames_decoded("keyFramesDecoded"),
       total_decode_time("totalDecodeTime"),
-      content_type("contentType") {}
+      content_type("contentType"),
+      decoder_implementation("decoderImplementation") {}
 
 RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(
     const RTCInboundRTPStreamStats& other)
@@ -672,7 +671,8 @@
       frames_decoded(other.frames_decoded),
       key_frames_decoded(other.key_frames_decoded),
       total_decode_time(other.total_decode_time),
-      content_type(other.content_type) {}
+      content_type(other.content_type),
+      decoder_implementation(other.decoder_implementation) {}
 
 RTCInboundRTPStreamStats::~RTCInboundRTPStreamStats() {}
 
@@ -691,7 +691,8 @@
     &total_encoded_bytes_target,
     &total_packet_send_delay,
     &quality_limitation_reason,
-    &content_type)
+    &content_type,
+    &encoder_implementation)
 // clang-format on
 
 RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(const std::string& id,
@@ -713,7 +714,8 @@
       total_encoded_bytes_target("totalEncodedBytesTarget"),
       total_packet_send_delay("totalPacketSendDelay"),
       quality_limitation_reason("qualityLimitationReason"),
-      content_type("contentType") {}
+      content_type("contentType"),
+      encoder_implementation("encoderImplementation") {}
 
 RTCOutboundRTPStreamStats::RTCOutboundRTPStreamStats(
     const RTCOutboundRTPStreamStats& other)
@@ -730,7 +732,8 @@
       total_encoded_bytes_target(other.total_encoded_bytes_target),
       total_packet_send_delay(other.total_packet_send_delay),
       quality_limitation_reason(other.quality_limitation_reason),
-      content_type(other.content_type) {}
+      content_type(other.content_type),
+      encoder_implementation(other.encoder_implementation) {}
 
 RTCOutboundRTPStreamStats::~RTCOutboundRTPStreamStats() {}