stats: add transportId to codec stats

BUG=webrtc:12181

Change-Id: Ib8e38f19ef2ddcb98455356087781f146af8c6b5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/193280
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32618}
diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h
index 7d8f5f5..ee3d707 100644
--- a/api/stats/rtcstats_objects.h
+++ b/api/stats/rtcstats_objects.h
@@ -115,6 +115,7 @@
   RTCCodecStats(const RTCCodecStats& other);
   ~RTCCodecStats() override;
 
+  RTCStatsMember<std::string> transport_id;
   RTCStatsMember<uint32_t> payload_type;
   RTCStatsMember<std::string> mime_type;
   RTCStatsMember<uint32_t> clock_rate;
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index aaeb721..5292008 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -228,6 +228,7 @@
 std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
     uint64_t timestamp_us,
     const std::string& mid,
+    const std::string& transport_id,
     bool inbound,
     const RtpCodecParameters& codec_params) {
   RTC_DCHECK_GE(codec_params.payload_type, 0);
@@ -250,6 +251,7 @@
   if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
     codec_stats->sdp_fmtp_line = fmtp.Release();
   }
+  codec_stats->transport_id = transport_id;
   return codec_stats;
 }
 
@@ -1282,6 +1284,9 @@
     if (!stats.mid) {
       continue;
     }
+    std::string transport_id = RTCTransportStatsIDFromTransportChannel(
+        *stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+
     const cricket::VoiceMediaInfo* voice_media_info =
         stats.track_media_info_map->voice_media_info();
     const cricket::VideoMediaInfo* video_media_info =
@@ -1291,12 +1296,12 @@
       // Inbound
       for (const auto& pair : voice_media_info->receive_codecs) {
         report->AddStats(CodecStatsFromRtpCodecParameters(
-            timestamp_us, *stats.mid, true, pair.second));
+            timestamp_us, *stats.mid, transport_id, true, pair.second));
       }
       // Outbound
       for (const auto& pair : voice_media_info->send_codecs) {
         report->AddStats(CodecStatsFromRtpCodecParameters(
-            timestamp_us, *stats.mid, false, pair.second));
+            timestamp_us, *stats.mid, transport_id, false, pair.second));
       }
     }
     // Video
@@ -1304,12 +1309,12 @@
       // Inbound
       for (const auto& pair : video_media_info->receive_codecs) {
         report->AddStats(CodecStatsFromRtpCodecParameters(
-            timestamp_us, *stats.mid, true, pair.second));
+            timestamp_us, *stats.mid, transport_id, true, pair.second));
       }
       // Outbound
       for (const auto& pair : video_media_info->send_codecs) {
         report->AddStats(CodecStatsFromRtpCodecParameters(
-            timestamp_us, *stats.mid, false, pair.second));
+            timestamp_us, *stats.mid, transport_id, false, pair.second));
       }
     }
   }
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index 7c19c3c..73579ff 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -874,6 +874,7 @@
   expected_inbound_audio_codec.clock_rate = 1337;
   expected_inbound_audio_codec.channels = 1;
   expected_inbound_audio_codec.sdp_fmtp_line = "minptime=10;useinbandfec=1";
+  expected_inbound_audio_codec.transport_id = "RTCTransport_TransportName_1";
 
   RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
                                               report->timestamp_us());
@@ -881,6 +882,7 @@
   expected_outbound_audio_codec.mime_type = "audio/isac";
   expected_outbound_audio_codec.clock_rate = 1338;
   expected_outbound_audio_codec.channels = 2;
+  expected_outbound_audio_codec.transport_id = "RTCTransport_TransportName_1";
 
   RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
                                              report->timestamp_us());
@@ -889,12 +891,14 @@
   expected_inbound_video_codec.clock_rate = 1339;
   expected_inbound_video_codec.sdp_fmtp_line =
       "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f";
+  expected_inbound_video_codec.transport_id = "RTCTransport_TransportName_1";
 
   RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
                                               report->timestamp_us());
   expected_outbound_video_codec.payload_type = 4;
   expected_outbound_video_codec.mime_type = "video/VP8";
   expected_outbound_video_codec.clock_rate = 1340;
+  expected_outbound_video_codec.transport_id = "RTCTransport_TransportName_1";
 
   ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
   EXPECT_EQ(
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc
index e627d45..ee68ec9 100644
--- a/pc/rtc_stats_integrationtest.cc
+++ b/pc/rtc_stats_integrationtest.cc
@@ -442,6 +442,8 @@
 
   bool VerifyRTCCodecStats(const RTCCodecStats& codec) {
     RTCStatsVerifier verifier(report_, &codec);
+    verifier.TestMemberIsIDReference(codec.transport_id,
+                                     RTCTransportStats::kType);
     verifier.TestMemberIsDefined(codec.payload_type);
     verifier.TestMemberIsDefined(codec.mime_type);
     verifier.TestMemberIsPositive<uint32_t>(codec.clock_rate);
diff --git a/pc/rtc_stats_traversal.cc b/pc/rtc_stats_traversal.cc
index c08643e..aa53dde 100644
--- a/pc/rtc_stats_traversal.cc
+++ b/pc/rtc_stats_traversal.cc
@@ -76,7 +76,8 @@
     const auto& certificate = static_cast<const RTCCertificateStats&>(stats);
     AddIdIfDefined(certificate.issuer_certificate_id, &neighbor_ids);
   } else if (type == RTCCodecStats::kType) {
-    // RTCCodecStats does not have any neighbor references.
+    const auto& codec = static_cast<const RTCCodecStats&>(stats);
+    AddIdIfDefined(codec.transport_id, &neighbor_ids);
   } else if (type == RTCDataChannelStats::kType) {
     // RTCDataChannelStats does not have any neighbor references.
   } else if (type == RTCIceCandidatePairStats::kType) {
diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc
index 2fe8546..5a803de 100644
--- a/stats/rtcstats_objects.cc
+++ b/stats/rtcstats_objects.cc
@@ -92,6 +92,7 @@
 
 // clang-format off
 WEBRTC_RTCSTATS_IMPL(RTCCodecStats, RTCStats, "codec",
+    &transport_id,
     &payload_type,
     &mime_type,
     &clock_rate,
@@ -104,6 +105,7 @@
 
 RTCCodecStats::RTCCodecStats(std::string&& id, int64_t timestamp_us)
     : RTCStats(std::move(id), timestamp_us),
+      transport_id("transportId"),
       payload_type("payloadType"),
       mime_type("mimeType"),
       clock_rate("clockRate"),
@@ -112,6 +114,7 @@
 
 RTCCodecStats::RTCCodecStats(const RTCCodecStats& other)
     : RTCStats(other.id(), other.timestamp_us()),
+      transport_id(other.transport_id),
       payload_type(other.payload_type),
       mime_type(other.mime_type),
       clock_rate(other.clock_rate),