Separate RTP object handling (senders, receivers, transceivers)

This is part of the PeerConnection disassembly project.

Bug: webrtc:11995
Change-Id: I4f207c8af39e267c4b5752c0828b84e221e1f080
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188624
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32443}
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
index d7863d7..5197a69 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -947,11 +947,17 @@
 cricket::ChannelManager* SdpOfferAnswerHandler::channel_manager() const {
   return pc_->channel_manager();
 }
-TransceiverList& SdpOfferAnswerHandler::transceivers() {
-  return pc_->transceivers_;
+TransceiverList* SdpOfferAnswerHandler::transceivers() {
+  if (!pc_->rtp_manager()) {
+    return nullptr;
+  }
+  return pc_->rtp_manager()->transceivers();
 }
-const TransceiverList& SdpOfferAnswerHandler::transceivers() const {
-  return pc_->transceivers_;
+const TransceiverList* SdpOfferAnswerHandler::transceivers() const {
+  if (!pc_->rtp_manager()) {
+    return nullptr;
+  }
+  return pc_->rtp_manager()->transceivers();
 }
 JsepTransportController* SdpOfferAnswerHandler::transport_controller() {
   return pc_->transport_controller_.get();
@@ -969,6 +975,12 @@
 const cricket::PortAllocator* SdpOfferAnswerHandler::port_allocator() const {
   return pc_->port_allocator_.get();
 }
+RtpTransmissionManager* SdpOfferAnswerHandler::rtp_manager() {
+  return pc_->rtp_manager();
+}
+const RtpTransmissionManager* SdpOfferAnswerHandler::rtp_manager() const {
+  return pc_->rtp_manager();
+}
 
 // ===================================================================
 
@@ -1211,7 +1223,7 @@
     }
     std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
     std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
-    for (const auto& transceiver : transceivers().List()) {
+    for (const auto& transceiver : transceivers()->List()) {
       if (transceiver->stopped()) {
         continue;
       }
@@ -1300,7 +1312,7 @@
   }
 
   if (IsUnifiedPlan()) {
-    for (const auto& transceiver : transceivers().List()) {
+    for (const auto& transceiver : transceivers()->List()) {
       if (transceiver->stopped()) {
         continue;
       }
@@ -1577,7 +1589,7 @@
     std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
     std::vector<rtc::scoped_refptr<MediaStreamInterface>> added_streams;
     std::vector<rtc::scoped_refptr<MediaStreamInterface>> removed_streams;
-    for (const auto& transceiver : transceivers().List()) {
+    for (const auto& transceiver : transceivers()->List()) {
       const ContentInfo* content =
           FindMediaSectionForTransceiver(transceiver, remote_description());
       if (!content) {
@@ -1597,7 +1609,7 @@
           stream_ids = media_desc->streams()[0].stream_ids();
         }
         transceivers()
-            .StableState(transceiver)
+            ->StableState(transceiver)
             ->SetRemoteStreamIdsIfUnset(transceiver->receiver()->stream_ids());
 
         RTC_LOG(LS_INFO) << "Processing the MSIDs for MID=" << content->name
@@ -2401,7 +2413,7 @@
   } else {
     RTC_DCHECK(type == SdpType::kAnswer);
     ChangeSignalingState(PeerConnectionInterface::kStable);
-    transceivers().DiscardStableStates();
+    transceivers()->DiscardStableStates();
     have_pending_rtp_data_channel_ = false;
   }
 
@@ -2492,10 +2504,10 @@
   stream_observers_.push_back(std::unique_ptr<MediaStreamObserver>(observer));
 
   for (const auto& track : local_stream->GetAudioTracks()) {
-    pc_->AddAudioTrack(track.get(), local_stream);
+    rtp_manager()->AddAudioTrack(track.get(), local_stream);
   }
   for (const auto& track : local_stream->GetVideoTracks()) {
-    pc_->AddVideoTrack(track.get(), local_stream);
+    rtp_manager()->AddVideoTrack(track.get(), local_stream);
   }
 
   pc_->stats()->AddStream(local_stream);
@@ -2511,10 +2523,10 @@
   TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream");
   if (!pc_->IsClosed()) {
     for (const auto& track : local_stream->GetAudioTracks()) {
-      pc_->RemoveAudioTrack(track.get(), local_stream);
+      rtp_manager()->RemoveAudioTrack(track.get(), local_stream);
     }
     for (const auto& track : local_stream->GetVideoTracks()) {
-      pc_->RemoveVideoTrack(track.get(), local_stream);
+      rtp_manager()->RemoveVideoTrack(track.get(), local_stream);
     }
   }
   local_streams_->RemoveStream(local_stream);
@@ -2546,7 +2558,7 @@
   std::vector<rtc::scoped_refptr<MediaStreamInterface>> all_removed_streams;
   std::vector<rtc::scoped_refptr<RtpReceiverInterface>> removed_receivers;
 
-  for (auto&& transceivers_stable_state_pair : transceivers().StableStates()) {
+  for (auto&& transceivers_stable_state_pair : transceivers()->StableStates()) {
     auto transceiver = transceivers_stable_state_pair.first;
     auto state = transceivers_stable_state_pair.second;
 
@@ -2577,7 +2589,7 @@
       if (transceiver->internal()->reused_for_addtrack()) {
         transceiver->internal()->set_created_by_addtrack(true);
       } else {
-        transceivers().Remove(transceiver);
+        transceivers()->Remove(transceiver);
       }
     }
     transceiver->internal()->sender_internal()->set_transport(nullptr);
@@ -2590,7 +2602,7 @@
     DestroyDataChannelTransport();
     have_pending_rtp_data_channel_ = false;
   }
-  transceivers().DiscardStableStates();
+  transceivers()->DiscardStableStates();
   pending_local_description_.reset();
   pending_remote_description_.reset();
   ChangeSignalingState(PeerConnectionInterface::kStable);
@@ -2742,7 +2754,7 @@
 
   // 5. For each transceiver in connection's set of transceivers, perform the
   // following checks:
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     const ContentInfo* current_local_msection =
         FindTransceiverMSection(transceiver.get(), description);
 
@@ -3060,27 +3072,27 @@
   // If this is an offer then the m= section might be recycled. If the m=
   // section is being recycled (defined as: rejected in the current local or
   // remote description and not rejected in new description), the transceiver
-  // should have been removed by RemoveStoppedTransceivers().
+  // should have been removed by RemoveStoppedtransceivers()->
   if (IsMediaSectionBeingRecycled(type, content, old_local_content,
                                   old_remote_content)) {
     const std::string& old_mid =
         (old_local_content && old_local_content->rejected)
             ? old_local_content->name
             : old_remote_content->name;
-    auto old_transceiver = transceivers().FindByMid(old_mid);
+    auto old_transceiver = transceivers()->FindByMid(old_mid);
     // The transceiver should be disassociated in RemoveStoppedTransceivers()
     RTC_DCHECK(!old_transceiver);
   }
 #endif
 
   const MediaContentDescription* media_desc = content.media_description();
-  auto transceiver = transceivers().FindByMid(content.name);
+  auto transceiver = transceivers()->FindByMid(content.name);
   if (source == cricket::CS_LOCAL) {
     // Find the RtpTransceiver that corresponds to this m= section, using the
     // mapping between transceivers and m= section indices established when
     // creating the offer.
     if (!transceiver) {
-      transceiver = transceivers().FindByMLineIndex(mline_index);
+      transceiver = transceivers()->FindByMLineIndex(mline_index);
     }
     if (!transceiver) {
       // This may happen normally when media sections are rejected.
@@ -3109,20 +3121,21 @@
       std::string sender_id = rtc::CreateRandomUuid();
       std::vector<RtpEncodingParameters> send_encodings =
           GetSendEncodingsFromRemoteDescription(*media_desc);
-      auto sender = pc_->CreateSender(media_desc->type(), sender_id, nullptr,
-                                      {}, send_encodings);
+      auto sender = rtp_manager()->CreateSender(media_desc->type(), sender_id,
+                                                nullptr, {}, send_encodings);
       std::string receiver_id;
       if (!media_desc->streams().empty()) {
         receiver_id = media_desc->streams()[0].id;
       } else {
         receiver_id = rtc::CreateRandomUuid();
       }
-      auto receiver = pc_->CreateReceiver(media_desc->type(), receiver_id);
-      transceiver = pc_->CreateAndAddTransceiver(sender, receiver);
+      auto receiver =
+          rtp_manager()->CreateReceiver(media_desc->type(), receiver_id);
+      transceiver = rtp_manager()->CreateAndAddTransceiver(sender, receiver);
       transceiver->internal()->set_direction(
           RtpTransceiverDirection::kRecvOnly);
       if (type == SdpType::kOffer) {
-        transceivers().StableState(transceiver)->set_newly_created();
+        transceivers()->StableState(transceiver)->set_newly_created();
       }
     }
 
@@ -3166,7 +3179,7 @@
                          transceiver->internal()->mline_index() != mline_index;
     if (state_changes) {
       transceivers()
-          .StableState(transceiver)
+          ->StableState(transceiver)
           ->SetMSectionIfUnset(transceiver->internal()->mid(),
                                transceiver->internal()->mline_index());
     }
@@ -3337,7 +3350,7 @@
   // the same type that were added to the PeerConnection by addTrack and are not
   // associated with any m= section and are not stopped, find the first such
   // RtpTransceiver.
-  for (auto transceiver : transceivers().List()) {
+  for (auto transceiver : transceivers()->List()) {
     if (transceiver->media_type() == media_type &&
         transceiver->internal()->created_by_addtrack() && !transceiver->mid() &&
         !transceiver->stopped()) {
@@ -3421,8 +3434,10 @@
     const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
     cricket::MediaSessionOptions* session_options) {
   // Figure out transceiver directional preferences.
-  bool send_audio = !pc_->GetAudioTransceiver()->internal()->senders().empty();
-  bool send_video = !pc_->GetVideoTransceiver()->internal()->senders().empty();
+  bool send_audio =
+      !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
+  bool send_video =
+      !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
 
   // By default, generate sendrecv/recvonly m= sections.
   bool recv_audio = true;
@@ -3496,7 +3511,7 @@
       !video_index ? nullptr
                    : &session_options->media_description_options[*video_index];
 
-  AddPlanBRtpSenderOptions(pc_->GetSendersInternal(),
+  AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
                            audio_media_description_options,
                            video_media_description_options,
                            offer_answer_options.num_simulcast_layers);
@@ -3545,7 +3560,7 @@
         media_type == cricket::MEDIA_TYPE_VIDEO) {
       // A media section is considered eligible for recycling if it is marked as
       // rejected in either the current local or current remote description.
-      auto transceiver = transceivers().FindByMid(mid);
+      auto transceiver = transceivers()->FindByMid(mid);
       if (!transceiver) {
         // No associated transceiver. The media section has been stopped.
         recycleable_mline_indices.push(i);
@@ -3599,7 +3614,7 @@
   // and not associated). Reuse media sections marked as recyclable first,
   // otherwise append to the end of the offer. New media sections should be
   // added in the order they were added to the PeerConnection.
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     if (transceiver->mid() || transceiver->stopping()) {
       continue;
     }
@@ -3670,8 +3685,10 @@
     const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options,
     cricket::MediaSessionOptions* session_options) {
   // Figure out transceiver directional preferences.
-  bool send_audio = !pc_->GetAudioTransceiver()->internal()->senders().empty();
-  bool send_video = !pc_->GetVideoTransceiver()->internal()->senders().empty();
+  bool send_audio =
+      !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty();
+  bool send_video =
+      !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty();
 
   // By default, generate sendrecv/recvonly m= sections. The direction is also
   // restricted by the direction in the offer.
@@ -3708,7 +3725,7 @@
       !video_index ? nullptr
                    : &session_options->media_description_options[*video_index];
 
-  AddPlanBRtpSenderOptions(pc_->GetSendersInternal(),
+  AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(),
                            audio_media_description_options,
                            video_media_description_options,
                            offer_answer_options.num_simulcast_layers);
@@ -3726,7 +3743,7 @@
     cricket::MediaType media_type = content.media_description()->type();
     if (media_type == cricket::MEDIA_TYPE_AUDIO ||
         media_type == cricket::MEDIA_TYPE_VIDEO) {
-      auto transceiver = transceivers().FindByMid(content.name);
+      auto transceiver = transceivers()->FindByMid(content.name);
       if (transceiver) {
         session_options->media_description_options.push_back(
             GetMediaDescriptionOptionsForTransceiver(
@@ -3855,7 +3872,7 @@
   std::vector<
       rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
       receiving_transceivers;
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     if (!transceiver->stopped() && transceiver->media_type() == media_type &&
         RtpTransceiverDirectionHasRecv(transceiver->direction())) {
       receiving_transceivers.push_back(transceiver);
@@ -3907,20 +3924,20 @@
     const std::vector<cricket::StreamParams>& streams,
     cricket::MediaType media_type) {
   RTC_DCHECK_RUN_ON(signaling_thread());
-  std::vector<PeerConnection::RtpSenderInfo>* current_senders =
-      pc_->GetLocalSenderInfos(media_type);
+  std::vector<RtpSenderInfo>* current_senders =
+      rtp_manager()->GetLocalSenderInfos(media_type);
 
   // Find removed tracks. I.e., tracks where the track id, stream id or ssrc
   // don't match the new StreamParam.
   for (auto sender_it = current_senders->begin();
        sender_it != current_senders->end();
        /* incremented manually */) {
-    const PeerConnection::RtpSenderInfo& info = *sender_it;
+    const RtpSenderInfo& info = *sender_it;
     const cricket::StreamParams* params =
         cricket::GetStreamBySsrc(streams, info.first_ssrc);
     if (!params || params->id != info.sender_id ||
         params->first_stream_id() != info.stream_id) {
-      pc_->OnLocalSenderRemoved(info, media_type);
+      rtp_manager()->OnLocalSenderRemoved(info, media_type);
       sender_it = current_senders->erase(sender_it);
     } else {
       ++sender_it;
@@ -3934,12 +3951,11 @@
     const std::string& stream_id = params.first_stream_id();
     const std::string& sender_id = params.id;
     uint32_t ssrc = params.first_ssrc();
-    const PeerConnection::RtpSenderInfo* sender_info =
-        pc_->FindSenderInfo(*current_senders, stream_id, sender_id);
+    const RtpSenderInfo* sender_info =
+        rtp_manager()->FindSenderInfo(*current_senders, stream_id, sender_id);
     if (!sender_info) {
-      current_senders->push_back(
-          PeerConnection::RtpSenderInfo(stream_id, sender_id, ssrc));
-      pc_->OnLocalSenderAdded(current_senders->back(), media_type);
+      current_senders->push_back(RtpSenderInfo(stream_id, sender_id, ssrc));
+      rtp_manager()->OnLocalSenderAdded(current_senders->back(), media_type);
     }
   }
 }
@@ -3952,15 +3968,15 @@
   RTC_DCHECK_RUN_ON(signaling_thread());
   RTC_DCHECK(!IsUnifiedPlan());
 
-  std::vector<PeerConnection::RtpSenderInfo>* current_senders =
-      pc_->GetRemoteSenderInfos(media_type);
+  std::vector<RtpSenderInfo>* current_senders =
+      rtp_manager()->GetRemoteSenderInfos(media_type);
 
   // Find removed senders. I.e., senders where the sender id or ssrc don't match
   // the new StreamParam.
   for (auto sender_it = current_senders->begin();
        sender_it != current_senders->end();
        /* incremented manually */) {
-    const PeerConnection::RtpSenderInfo& info = *sender_it;
+    const RtpSenderInfo& info = *sender_it;
     const cricket::StreamParams* params =
         cricket::GetStreamBySsrc(streams, info.first_ssrc);
     std::string params_stream_id;
@@ -3976,8 +3992,8 @@
         sender_exists) {
       ++sender_it;
     } else {
-      pc_->OnRemoteSenderRemoved(info, remote_streams_->find(info.stream_id),
-                                 media_type);
+      rtp_manager()->OnRemoteSenderRemoved(
+          info, remote_streams_->find(info.stream_id), media_type);
       sender_it = current_senders->erase(sender_it);
     }
   }
@@ -4013,12 +4029,12 @@
       new_streams->AddStream(stream);
     }
 
-    const PeerConnection::RtpSenderInfo* sender_info =
-        pc_->FindSenderInfo(*current_senders, stream_id, sender_id);
+    const RtpSenderInfo* sender_info =
+        rtp_manager()->FindSenderInfo(*current_senders, stream_id, sender_id);
     if (!sender_info) {
-      current_senders->push_back(
-          PeerConnection::RtpSenderInfo(stream_id, sender_id, ssrc));
-      pc_->OnRemoteSenderAdded(current_senders->back(), stream, media_type);
+      current_senders->push_back(RtpSenderInfo(stream_id, sender_id, ssrc));
+      rtp_manager()->OnRemoteSenderAdded(current_senders->back(), stream,
+                                         media_type);
     }
   }
 
@@ -4036,21 +4052,20 @@
     std::string default_sender_id = (media_type == cricket::MEDIA_TYPE_AUDIO)
                                         ? kDefaultAudioSenderId
                                         : kDefaultVideoSenderId;
-    const PeerConnection::RtpSenderInfo* default_sender_info =
-        pc_->FindSenderInfo(*current_senders, kDefaultStreamId,
-                            default_sender_id);
+    const RtpSenderInfo* default_sender_info = rtp_manager()->FindSenderInfo(
+        *current_senders, kDefaultStreamId, default_sender_id);
     if (!default_sender_info) {
-      current_senders->push_back(PeerConnection::RtpSenderInfo(
-          kDefaultStreamId, default_sender_id, /*ssrc=*/0));
-      pc_->OnRemoteSenderAdded(current_senders->back(), default_stream,
-                               media_type);
+      current_senders->push_back(
+          RtpSenderInfo(kDefaultStreamId, default_sender_id, /*ssrc=*/0));
+      rtp_manager()->OnRemoteSenderAdded(current_senders->back(),
+                                         default_stream, media_type);
     }
   }
 }
 
 void SdpOfferAnswerHandler::EnableSending() {
   RTC_DCHECK_RUN_ON(signaling_thread());
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     cricket::ChannelInterface* channel = transceiver->internal()->channel();
     if (channel && !channel->enabled()) {
       channel->Enable(true);
@@ -4081,7 +4096,7 @@
   }
 
   // Push down the new SDP media section for each audio/video transceiver.
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     const ContentInfo* content_info =
         FindMediaSectionForTransceiver(transceiver, sdesc);
     cricket::ChannelInterface* channel = transceiver->internal()->channel();
@@ -4178,7 +4193,7 @@
   if (!IsUnifiedPlan())
     return;
   // Traverse a copy of the transceiver list.
-  auto transceiver_list = transceivers().List();
+  auto transceiver_list = transceivers()->List();
   for (auto transceiver : transceiver_list) {
     // 3.2.10.1.1: If transceiver is stopped, associated with an m= section
     //             and the associated m= section is rejected in
@@ -4198,7 +4213,7 @@
                        << " since the media section is being recycled.";
       transceiver->internal()->set_mid(absl::nullopt);
       transceiver->internal()->set_mline_index(absl::nullopt);
-      transceivers().Remove(transceiver);
+      transceivers()->Remove(transceiver);
       continue;
     }
     if (!local_content && !remote_content) {
@@ -4206,7 +4221,7 @@
       // See https://github.com/w3c/webrtc-pc/issues/2576
       RTC_LOG(LS_INFO)
           << "Dropping stopped transceiver that was never associated";
-      transceivers().Remove(transceiver);
+      transceivers()->Remove(transceiver);
       continue;
     }
   }
@@ -4219,12 +4234,12 @@
   // voice channel.
   const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc);
   if (!video_info || video_info->rejected) {
-    DestroyTransceiverChannel(pc_->GetVideoTransceiver());
+    DestroyTransceiverChannel(rtp_manager()->GetVideoTransceiver());
   }
 
   const cricket::ContentInfo* audio_info = cricket::GetFirstAudioContent(desc);
   if (!audio_info || audio_info->rejected) {
-    DestroyTransceiverChannel(pc_->GetAudioTransceiver());
+    DestroyTransceiverChannel(rtp_manager()->GetAudioTransceiver());
   }
 
   const cricket::ContentInfo* data_info = cricket::GetFirstDataContent(desc);
@@ -4432,24 +4447,24 @@
   RTC_DCHECK_RUN_ON(signaling_thread());
   const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(&desc);
   if (voice && !voice->rejected &&
-      !pc_->GetAudioTransceiver()->internal()->channel()) {
+      !rtp_manager()->GetAudioTransceiver()->internal()->channel()) {
     cricket::VoiceChannel* voice_channel = CreateVoiceChannel(voice->name);
     if (!voice_channel) {
       LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                            "Failed to create voice channel.");
     }
-    pc_->GetAudioTransceiver()->internal()->SetChannel(voice_channel);
+    rtp_manager()->GetAudioTransceiver()->internal()->SetChannel(voice_channel);
   }
 
   const cricket::ContentInfo* video = cricket::GetFirstVideoContent(&desc);
   if (video && !video->rejected &&
-      !pc_->GetVideoTransceiver()->internal()->channel()) {
+      !rtp_manager()->GetVideoTransceiver()->internal()->channel()) {
     cricket::VideoChannel* video_channel = CreateVideoChannel(video->name);
     if (!video_channel) {
       LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                            "Failed to create video channel.");
     }
-    pc_->GetVideoTransceiver()->internal()->SetChannel(video_channel);
+    rtp_manager()->GetVideoTransceiver()->internal()->SetChannel(video_channel);
   }
 
   const cricket::ContentInfo* data = cricket::GetFirstDataContent(&desc);
@@ -4627,14 +4642,17 @@
 
 void SdpOfferAnswerHandler::DestroyAllChannels() {
   RTC_DCHECK_RUN_ON(signaling_thread());
+  if (!transceivers()) {
+    return;
+  }
   // Destroy video channels first since they may have a pointer to a voice
   // channel.
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
       DestroyTransceiverChannel(transceiver);
     }
   }
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
       DestroyTransceiverChannel(transceiver);
     }
@@ -4819,7 +4837,7 @@
   // single Invoke; necessary due to thread guards.
   std::vector<std::pair<RtpTransceiverDirection, cricket::ChannelInterface*>>
       channels_to_update;
-  for (const auto& transceiver : transceivers().List()) {
+  for (const auto& transceiver : transceivers()->List()) {
     cricket::ChannelInterface* channel = transceiver->internal()->channel();
     const ContentInfo* content =
         FindMediaSectionForTransceiver(transceiver, sdesc);