Prevent RTCStatsCollector crash for stopped transceivers

Prevent a crash in RTCStatsCollector that occurs when attempting to
process transceivers with a stopped direction.

When gathering statistics, the collector iterates through all available
transceivers. If a transceiver's current direction is set to kStopped,
the internal mapping for media information is not created during the
preparation phase and there was a missing check for that.

Bug: b/494115682
Change-Id: I0748c9d627d886aaa12118411fa94e2ab8575269
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/458680
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47221}
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index 6a2325b..8030dd4 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -1862,6 +1862,10 @@
       continue;
     }
 
+    if (stats.current_direction == RtpTransceiverDirection::kStopped) {
+      continue;
+    }
+
     if (stats.media_type == MediaType::AUDIO) {
       ProduceAudioRTPStreamStats_s(timestamp, stats, call_stats,
                                    audio_device_stats, report);
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index c044f87..2b5e4b0 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -68,6 +68,7 @@
 #include "pc/media_stream.h"
 #include "pc/peer_connection_internal.h"
 #include "pc/rtp_sender.h"
+#include "pc/rtp_transceiver.h"
 #include "pc/sctp_data_channel.h"
 #include "pc/stream_collection.h"
 #include "pc/test/fake_audio_track.h"
@@ -102,6 +103,9 @@
 #include "test/time_controller/simulated_time_controller.h"
 
 using ::testing::_;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::NotNull;
 using ::testing::Return;
 
 namespace webrtc {
@@ -900,6 +904,34 @@
   EXPECT_EQ(report->size(), json_value.size());
 }
 
+TEST_P(RTCStatsCollectorTest, ProduceRTPStreamStatsWithStoppedTransceiver) {
+  const char kTransportName[] = "transport";
+  const char kMid[] = "VideoMid";
+
+  VideoMediaInfo video_media_info;
+  video_media_info.senders.emplace_back();
+  video_media_info.senders[0].add_ssrc(1);
+
+  RTC_ALLOW_PLAN_B_DEPRECATION_BEGIN();
+  pc_->AddVideoChannel(kMid, kTransportName, video_media_info);
+  RTC_ALLOW_PLAN_B_DEPRECATION_END();
+
+  // Get the transceiver and set it to stopped.
+  std::vector<scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
+      transceivers = pc_->GetTransceiversInternal();
+  ASSERT_THAT(transceivers, Not(IsEmpty()));
+  scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>> transceiver =
+      transceivers[0];
+  ASSERT_TRUE(transceiver);
+  transceiver->internal()->set_current_direction(
+      RtpTransceiverDirection::kStopped);
+
+  // This should not crash.
+  scoped_refptr<const RTCStatsReport> report =
+      stats_->GetStatsReport(main_thread_);
+  EXPECT_THAT(report, NotNull());
+}
+
 TEST_P(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
   const char kTransportName[] = "transport";