Fix data race on channel_ in RtpTransceiver

Capture raw pointer to channel in SetRtpTransportState callback to avoid
reading channel_ member on network thread. Unsubscribe on network thread
before destruction on worker thread ensures lifetime safety.

Caught here: https://chromium-swarm.appspot.com/task?id=77f695c1d91f3911

Bug: webrtc:42224170
Change-Id: I3736870ea6cbc3a7b880d0d6afec2688ea8de7a8
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/468640
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47586}
diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc
index 9554f20..ca6809d 100644
--- a/pc/rtp_transceiver.cc
+++ b/pc/rtp_transceiver.cc
@@ -1398,10 +1398,16 @@
   RTC_DCHECK(!rtp_transport_);
   rtp_transport_ = transport;
   if (rtp_transport_) {
+    // Safe to capture raw pointer to channel because we unsubscribe on the
+    // network thread (via GetClearChannelNetworkTask) before the channel is
+    // destroyed on the worker thread (via GetDeleteChannelWorkerTask).
+    // Capturing raw pointer avoids reading `channel_` member on the network
+    // thread, which races with signaling thread moving it during teardown.
     rtp_transport_->SubscribeNetworkRouteChanged(
-        this, [this](std::optional<NetworkRoute> route) {
+        this,
+        [this, channel = channel_.get()](std::optional<NetworkRoute> route) {
           RTC_DCHECK_RUN_ON(context()->network_thread());
-          OnNetworkRouteChanged(route);
+          OnNetworkRouteChanged(channel, route);
         });
   }
 }
@@ -1426,11 +1432,12 @@
 }
 
 void RtpTransceiver::OnNetworkRouteChanged(
+    ChannelInterface* channel,
     std::optional<NetworkRoute> network_route) {
   RTC_DCHECK_RUN_ON(context()->network_thread());
-  if (channel_ && rtp_transport_) {
-    RTC_LOG(LS_INFO) << "Network route changed for mid=" << channel_->mid();
-    channel_->media_send_channel()->OnNetworkRouteChanged(
+  if (channel && rtp_transport_) {
+    RTC_LOG(LS_INFO) << "Network route changed for mid=" << channel->mid();
+    channel->media_send_channel()->OnNetworkRouteChanged(
         rtp_transport_->transport_name(),
         network_route.value_or(NetworkRoute()));
   }
diff --git a/pc/rtp_transceiver.h b/pc/rtp_transceiver.h
index 6ffbe33..fe51e86 100644
--- a/pc/rtp_transceiver.h
+++ b/pc/rtp_transceiver.h
@@ -450,7 +450,8 @@
   RTCErrorOr<std::optional<std::string>> InitializeOnNetworkThread(
       absl::AnyInvocable<RtpTransportInternal*() &&> transport_lookup)
       RTC_RUN_ON(context()->network_thread());
-  void OnNetworkRouteChanged(std::optional<NetworkRoute> network_route)
+  void OnNetworkRouteChanged(ChannelInterface* channel,
+                             std::optional<NetworkRoute> network_route)
       RTC_RUN_ON(context()->network_thread());
   void ClearRtpTransportState() RTC_RUN_ON(context()->network_thread());
   void SetRtpTransportState(RtpTransportInternal* transport)