/*
 *  Copyright 2004 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/channel.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/base/nullability.h"
#include "absl/cleanup/cleanup.h"
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/crypto/crypto_options.h"
#include "api/jsep.h"
#include "api/media_types.h"
#include "api/rtc_error.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "call/rtp_demuxer.h"
#include "media/base/codec.h"
#include "media/base/media_channel.h"
#include "media/base/rid_description.h"
#include "media/base/rtp_utils.h"
#include "media/base/stream_params.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "p2p/dtls/dtls_transport_internal.h"
#include "pc/channel_interface.h"
#include "pc/rtp_media_utils.h"
#include "pc/rtp_transport_internal.h"
#include "pc/session_description.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/containers/flat_set.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/logging.h"
#include "rtc_base/network/sent_packet.h"
#include "rtc_base/socket.h"
#include "rtc_base/strings/string_format.h"
#include "rtc_base/thread.h"
#include "rtc_base/trace_event.h"
#include "rtc_base/unique_id_generator.h"

namespace webrtc {
namespace {

// Finds a stream based on target's Primary SSRC or RIDs.
// This struct is used in BaseChannel::UpdateLocalStreams_w.
struct StreamFinder {
  explicit StreamFinder(const StreamParams* target) : target_(target) {
    RTC_DCHECK(target);
  }

  bool operator()(const StreamParams& sp) const {
    if (target_->has_ssrcs() && sp.has_ssrcs()) {
      return sp.has_ssrc(target_->first_ssrc());
    }

    if (!target_->has_rids() && !sp.has_rids()) {
      return false;
    }

    const std::vector<RidDescription>& target_rids = target_->rids();
    const std::vector<RidDescription>& source_rids = sp.rids();
    if (source_rids.size() != target_rids.size()) {
      return false;
    }

    // Check that all RIDs match.
    return std::equal(source_rids.begin(), source_rids.end(),
                      target_rids.begin(),
                      [](const RidDescription& lhs, const RidDescription& rhs) {
                        return lhs.rid == rhs.rid;
                      });
  }

  const StreamParams* target_;
};

void MediaChannelParametersFromMediaDescription(
    const MediaContentDescription* desc,
    const RtpHeaderExtensions& extensions,
    bool is_stream_active,
    MediaChannelParameters* params) {
  RTC_DCHECK(desc->type() == MediaType::AUDIO ||
             desc->type() == MediaType::VIDEO);
  params->is_stream_active = is_stream_active;
  params->codecs = desc->codecs();
  params->extensions = extensions;
  params->rtcp.reduced_size = desc->rtcp_reduced_size();
  params->rtcp.remote_estimate = desc->remote_estimate();
  params->rtcp_cc_ack_type = desc->preferred_rtcp_cc_ack_type();
}

void RtpSendParametersFromMediaDescription(
    const MediaContentDescription* desc,
    RtpExtension::Filter extensions_filter,
    SenderParameters* send_params) {
  RtpHeaderExtensions extensions = RtpExtension::DeduplicateHeaderExtensions(
      desc->rtp_header_extensions(), extensions_filter);
  const bool is_stream_active =
      RtpTransceiverDirectionHasRecv(desc->direction());
  MediaChannelParametersFromMediaDescription(desc, extensions, is_stream_active,
                                             send_params);
  send_params->max_bandwidth_bps = desc->bandwidth();
  send_params->extmap_allow_mixed = desc->extmap_allow_mixed();
}

// Ensure that there is a matching packetization for each codec in
// new_params. If old_params had a special packetization but the
// response in new_params has no special packetization we amend
// old_params by ignoring the packetization and fall back to standard
// packetization instead.
RTCError MaybeIgnorePacketization(const MediaChannelParameters& new_params,
                                  MediaChannelParameters& old_params) {
  flat_set<const Codec*> matched_codecs;
  for (Codec& codec : old_params.codecs) {
    if (absl::c_any_of(matched_codecs,
                       [&](const Codec* c) { return codec.Matches(*c); })) {
      continue;
    }

    std::vector<const Codec*> new_codecs =
        FindAllMatchingCodecs(new_params.codecs, codec);
    if (new_codecs.empty()) {
      continue;
    }

    bool may_ignore_packetization = false;
    bool has_matching_packetization = false;
    for (const Codec* new_codec : new_codecs) {
      if (!new_codec->packetization.has_value() &&
          codec.packetization.has_value()) {
        may_ignore_packetization = true;
      } else if (new_codec->packetization == codec.packetization) {
        has_matching_packetization = true;
        break;
      }
    }

    if (may_ignore_packetization) {
      // Note: this writes into old_params
      codec.packetization = std::nullopt;
    } else if (!has_matching_packetization) {
      return RTCError(RTCErrorType::INTERNAL_ERROR)
             << "Failed to set local answer due to incompatible codec "
             << "packetization for pt='" << codec.id << "' specified.";
    }

    if (has_matching_packetization) {
      matched_codecs.insert(&codec);
    }
  }
  return RTCError::OK();
}

}  // namespace

BaseChannel::BaseChannel(
    TaskQueueBase* absl_nonnull worker_thread,
    Thread* absl_nonnull network_thread,
    TaskQueueBase* absl_nonnull signaling_thread,
    std::unique_ptr<MediaSendChannelInterface> send_media_channel_impl,
    std::unique_ptr<MediaReceiveChannelInterface> receive_media_channel_impl,
    absl::string_view mid,
    MediaType media_type,
    bool srtp_required,
    CryptoOptions crypto_options,
    UniqueRandomIdGenerator* absl_nonnull ssrc_generator,
    ChannelCallbacks callbacks)
    : media_send_channel_(std::move(send_media_channel_impl)),
      media_receive_channel_(std::move(receive_media_channel_impl)),
      worker_thread_(worker_thread),
      network_thread_(network_thread),
      signaling_thread_(signaling_thread),
      alive_(PendingTaskSafetyFlag::Create()),
      on_first_packet_received_(std::move(callbacks.on_first_packet_received)),
      on_first_packet_sent_(std::move(callbacks.on_first_packet_sent)),
      on_packet_received_n_(std::move(callbacks.on_packet_received)),
      srtp_required_(srtp_required),
      extensions_filter_(
          crypto_options.srtp.enable_encrypted_rtp_header_extensions
              ? RtpExtension::kPreferEncryptedExtension
              : RtpExtension::kDiscardEncryptedExtension),
      mid_(std::string(mid)),
      last_recv_params_(media_type == MediaType::VIDEO
                            ? ReceiverParamsVariant(VideoReceiverParameters())
                            : ReceiverParamsVariant(AudioReceiverParameters())),
      last_send_params_(media_type == MediaType::VIDEO
                            ? SenderParamsVariant(VideoSenderParameters())
                            : SenderParamsVariant(AudioSenderParameter())),
      media_type_(media_type),
      ssrc_generator_(ssrc_generator) {
  RTC_DCHECK_RUN_ON(worker_thread_);
  RTC_DCHECK(media_send_channel_);
  RTC_DCHECK(media_receive_channel_);
  RTC_DCHECK(ssrc_generator_);
  RTC_DLOG(LS_INFO) << "Created channel: " << ToString();
}

BaseChannel::~BaseChannel() {
  TRACE_EVENT0("webrtc", "BaseChannel::~BaseChannel");
  RTC_DCHECK_RUN_ON(worker_thread_);

  DisableMedia_w();

  // Eats any outstanding messages or packets.
  alive_->SetNotAlive();
  // The channel must be disconnected from the transport before destruction.
  RTC_DCHECK(rtp_transport_ == nullptr);
}

std::string BaseChannel::ToString() const {
  return StringFormat(
      "{mid: %s, media_type: %s}", mid().c_str(),
      MediaTypeToString(media_send_channel_->media_type()).c_str());
}

bool BaseChannel::ConnectToRtpTransport_n(RtpTransportInternal* rtp_transport) {
  RTC_DCHECK(!rtp_transport_);
  RTC_DCHECK(rtp_transport);
  RTC_DCHECK(media_send_channel());

  // We don't need to call OnDemuxerCriteriaUpdatePending/Complete because
  // there's no previous criteria to worry about.
  RtpDemuxerCriteria criteria = demuxer_criteria();
  if (!rtp_transport->RegisterRtpDemuxerSink(criteria, this)) {
    return false;
  }
  rtp_transport_ = rtp_transport;
  rtp_transport_->SubscribeReadyToSend(
      this, [this](bool ready) { OnTransportReadyToSend(ready); });
  rtp_transport_->SubscribeWritableState(
      this, [this](bool state) { OnWritableState(state); });
  rtp_transport_->SubscribeSentPacket(
      this,
      [this](const SentPacketInfo& packet) { SignalSentPacket_n(packet); });
  return true;
}

void BaseChannel::DisconnectFromRtpTransport_n(bool permanent_teardown) {
  RTC_DCHECK(rtp_transport_);
  RTC_DCHECK(media_send_channel());
  rtp_transport_->UnregisterRtpDemuxerSink(this);
  rtp_transport_->UnsubscribeReadyToSend(this);
  rtp_transport_->UnsubscribeWritableState(this);
  rtp_transport_->UnsubscribeSentPacket(this);
  rtp_transport_ = nullptr;
  media_send_channel()->SetInterface(nullptr);
  if (permanent_teardown) {
    media_receive_channel()->ClearReceiveSinks_n(std::nullopt);
  }
  media_receive_channel()->SetInterface(nullptr);
}

bool BaseChannel::SetRtpTransport(RtpTransportInternal* rtp_transport) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetRtpTransport");
  RTC_DCHECK_RUN_ON(network_thread());
  if (rtp_transport == rtp_transport_) {
    return true;
  }

  if (rtp_transport_) {
    DisconnectFromRtpTransport_n(rtp_transport == nullptr);
  }

  RTC_DCHECK(!rtp_transport_);

  if (!rtp_transport) {
    return true;  // We're done.
  }

  if (!ConnectToRtpTransport_n(rtp_transport)) {
    RTC_DCHECK(!rtp_transport_);
    return false;
  }

  RTC_DCHECK_EQ(rtp_transport_, rtp_transport);

  RTC_DCHECK(!media_send_channel()->HasNetworkInterface());
  media_send_channel()->SetInterface(this);
  media_receive_channel()->SetInterface(this);

  media_send_channel()->OnReadyToSend(rtp_transport_->IsReadyToSend());
  UpdateWritableState_n();

  // Set the cached socket options.
  for (const auto& pair : socket_options_) {
    rtp_transport_->SetRtpOption(pair.first, pair.second);
  }
  if (!rtp_transport_->rtcp_mux_enabled()) {
    for (const auto& pair : rtcp_socket_options_) {
      rtp_transport_->SetRtcpOption(pair.first, pair.second);
    }
  }

  return true;
}

void BaseChannel::Enable(bool enable) {
  RTC_DCHECK_RUN_ON(signaling_thread());

  if (enable == enabled_s_)
    return;

  enabled_s_ = enable;

  worker_thread_->PostTask(SafeTask(alive_, [this, enable] {
    RTC_DCHECK_RUN_ON(worker_thread());
    // Sanity check to make sure that enabled_ and enabled_s_
    // stay in sync.
    RTC_DCHECK_NE(enabled_, enable);
    if (enable) {
      EnableMedia_w();
    } else {
      DisableMedia_w();
    }
  }));
}

RTCError BaseChannel::SetLocalContent(const MediaContentDescription* content,
                                      SdpType type) {
  RTC_DCHECK_RUN_ON(worker_thread());
  TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent");
  return SetLocalContent_w(content, type);
}

RTCError BaseChannel::SetRemoteContent(const MediaContentDescription* content,
                                       SdpType type) {
  RTC_DCHECK_RUN_ON(worker_thread());
  TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent");
  return SetRemoteContent_w(content, type);
}

bool BaseChannel::IsReadyToSendMedia_w() const {
  // Send outgoing data if we are enabled, have local and remote content,
  // and we have had some form of connectivity.
  return enabled_ &&
         RtpTransceiverDirectionHasRecv(remote_content_direction_) &&
         RtpTransceiverDirectionHasSend(local_content_direction_) &&
         was_ever_writable_;
}

bool BaseChannel::SendPacket(CopyOnWriteBuffer* packet,
                             const AsyncSocketPacketOptions& options) {
  return SendPacket(false, packet, options);
}

bool BaseChannel::SendRtcp(CopyOnWriteBuffer* packet,
                           const AsyncSocketPacketOptions& options) {
  return SendPacket(true, packet, options);
}

int BaseChannel::SetOption(SocketType type, Socket::Option opt, int value) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());
  RTC_DCHECK(rtp_transport_);
  switch (type) {
    case ST_RTP:
      socket_options_.push_back(std::pair<Socket::Option, int>(opt, value));
      return rtp_transport_->SetRtpOption(opt, value);
    case ST_RTCP:
      rtcp_socket_options_.push_back(
          std::pair<Socket::Option, int>(opt, value));
      return rtp_transport_->SetRtcpOption(opt, value);
  }
  return -1;
}

void BaseChannel::OnWritableState(bool writable) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());
  if (writable) {
    ChannelWritable_n();
  } else {
    ChannelNotWritable_n();
  }
}

void BaseChannel::OnTransportReadyToSend(bool ready) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());
  media_send_channel()->OnReadyToSend(ready);
}

bool BaseChannel::SendPacket(bool rtcp,
                             CopyOnWriteBuffer* packet,
                             const AsyncSocketPacketOptions& options) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());
  TRACE_EVENT0("webrtc", "BaseChannel::SendPacket");

  // Until all the code is migrated to use RtpPacketType instead of bool.
  RtpPacketType packet_type = rtcp ? RtpPacketType::kRtcp : RtpPacketType::kRtp;

  // Ensure we have a place to send this packet before doing anything. We might
  // get RTCP packets that we don't intend to send. If we've negotiated RTCP
  // mux, send RTCP over the RTP transport.
  if (!rtp_transport_ || !rtp_transport_->IsWritable(rtcp)) {
    return false;
  }

  // Protect ourselves against crazy data.
  if (!IsValidRtpPacketSize(packet_type, packet->size())) {
    RTC_LOG(LS_ERROR) << "Dropping outgoing " << ToString() << " "
                      << RtpPacketTypeToString(packet_type)
                      << " packet: wrong size=" << packet->size();
    return false;
  }

  if (!srtp_active()) {
    if (srtp_required_) {
      // The audio/video engines may attempt to send RTCP packets as soon as the
      // streams are created, so don't treat this as an error for RTCP.
      // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6809
      // However, there shouldn't be any RTP packets sent before SRTP is set
      // up (and SetSend(true) is called).
      RTC_DCHECK(rtcp) << "Can't send outgoing RTP packet for " << ToString()
                       << " when SRTP is inactive and crypto is required";
      return false;
    }

    RTC_DLOG(LS_WARNING) << "Sending an " << (rtcp ? "RTCP" : "RTP")
                         << " packet without encryption for " << ToString()
                         << ".";
  }

  if (on_first_packet_sent_ && options.info_signaled_after_sent.is_media) {
    std::move(on_first_packet_sent_)();
    on_first_packet_sent_ = nullptr;
  }

  return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
              : rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
}

void BaseChannel::OnRtpPacket(const RtpPacketReceived& parsed_packet) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());

  if (on_first_packet_received_) {
    std::move(on_first_packet_received_)(parsed_packet);
    on_first_packet_received_ = nullptr;
  }

  if (!srtp_active() && srtp_required_) {
    // Our session description indicates that SRTP is required, but we got a
    // packet before our SRTP filter is active. This means either that
    // a) we got SRTP packets before we received the SDES keys, in which case
    //    we can't decrypt it anyway, or
    // b) we got SRTP packets before DTLS completed on both the RTP and RTCP
    //    transports, so we haven't yet extracted keys, even if DTLS did
    //    complete on the transport that the packets are being sent on. It's
    //    really good practice to wait for both RTP and RTCP to be good to go
    //    before sending  media, to prevent weird failure modes, so it's fine
    //    for us to just eat packets here. This is all sidestepped if RTCP mux
    //    is used anyway.
    RTC_LOG(LS_WARNING) << "Can't process incoming RTP packet when "
                           "SRTP is inactive and crypto is required "
                        << ToString();
    return;
  }
  if (on_packet_received_n_) {
    on_packet_received_n_(parsed_packet);
  }
  media_receive_channel()->OnPacketReceived(parsed_packet);
}

RTCError BaseChannel::MaybeUpdateDemuxerAndRtpExtensions_w(
    bool update_demuxer,
    std::optional<flat_set<uint8_t>> payload_types,
    const RtpHeaderExtensions& extensions,
    std::optional<flat_set<uint32_t>> ssrcs) {
  const bool pending_update =
      update_demuxer || payload_types.has_value() || ssrcs.has_value();
  if (pending_update) {
    media_receive_channel()->OnDemuxerCriteriaUpdatePending();
  }
  absl::Cleanup cleanup = [this, pending_update] {
    if (pending_update) {
      media_receive_channel()->OnDemuxerCriteriaUpdateComplete();
    }
  };

  // TODO(bugs.webrtc.org/13536): See if we can do this asynchronously.
  RTCError error = network_thread()->BlockingCall([&]() -> RTCError {
    RTC_DCHECK_RUN_ON(network_thread());
    RTCError error =
        rtp_transport_
            ? rtp_transport_->RegisterRtpHeaderExtensionMap(mid(), extensions)
            : (RTCError::InvalidState() << "No transport assigned.");
    if (!error.ok()) {
      error.string_builder() << " (mid=" << mid() << ")";
      return LOG_ERROR(error);
    }

    if (payload_types) {
      if (payload_types_ != *payload_types) {
        payload_types_ = std::move(*payload_types);
        update_demuxer = true;
      }
    }

    if (ssrcs) {
      if (ssrcs_ != *ssrcs) {
        ssrcs_ = std::move(*ssrcs);
        update_demuxer = true;
      }
    }

    if (!update_demuxer)
      return RTCError::OK();

    RtpDemuxerCriteria criteria = demuxer_criteria();
    if (!rtp_transport_->RegisterRtpDemuxerSink(criteria, this)) {
      return RTCError::InvalidParameter()
             << "Failed to apply demuxer criteria for '" << mid() << "': '"
             << criteria.ToString() << "'.";
    }
    return RTCError::OK();
  });

  return error;
}

bool BaseChannel::RegisterRtpDemuxerSink_w(
    const MediaContentDescription* content,
    std::vector<uint32_t> removed_ssrcs) {
  bool clear_payload_types = false;
  if (!RtpTransceiverDirectionHasSend(content->direction())) {
    RTC_DLOG(LS_VERBOSE)
        << "RegisterRtpDemuxerSink_w: remote side will not send "
           "- disable payload type demuxing for "
        << ToString();
    clear_payload_types = true;
  }

  flat_set<uint32_t> ssrcs;
  for (const StreamParams& new_stream : content->streams()) {
    ssrcs.insert(new_stream.ssrcs.begin(), new_stream.ssrcs.end());
  }

  bool ret = network_thread_->BlockingCall([&] {
    RTC_DCHECK_RUN_ON(network_thread());
    if (!rtp_transport_) {
      // Transport was disconnected before attempting to update the
      // criteria. This can happen while setting the remote description.
      // See chromium:1295469 for an example.
      return false;
    }

    if (!removed_ssrcs.empty()) {
      media_receive_channel()->ClearReceiveSinks_n(std::move(removed_ssrcs));
    }

    bool needs_re_registration = false;

    if (clear_payload_types && !payload_types_.empty()) {
      payload_types_.clear();
      needs_re_registration = true;
    }

    if (ssrcs_ != ssrcs) {
      ssrcs_ = std::move(ssrcs);
      needs_re_registration = true;
    }
    media_receive_channel()->SetReceiveSsrcs_n(ssrcs_);

    if (!needs_re_registration) {
      return true;
    }

    // Note that RegisterRtpDemuxerSink first unregisters the sink if
    // already registered. So this will change the state of the class
    // whether the call succeeds or not.
    RtpDemuxerCriteria criteria = demuxer_criteria();
    return rtp_transport_->RegisterRtpDemuxerSink(criteria, this);
  });

  return ret;
}

RtpDemuxerCriteria BaseChannel::demuxer_criteria() const {
  RTC_DCHECK_RUN_ON(network_thread());
  RtpDemuxerCriteria criteria(mid_);
  criteria.payload_types() = payload_types_;
  criteria.ssrcs() = ssrcs_;
  return criteria;
}

void BaseChannel::EnableMedia_w() {
  if (enabled_)
    return;

  RTC_LOG(LS_INFO) << "Channel enabled: " << ToString();
  enabled_ = true;
  UpdateMediaSendRecvState_w();
}

void BaseChannel::DisableMedia_w() {
  if (!enabled_)
    return;

  RTC_LOG(LS_INFO) << "Channel disabled: " << ToString();
  enabled_ = false;
  UpdateMediaSendRecvState_w();
}

void BaseChannel::UpdateMediaSendRecvState_w() {
  RTC_DCHECK_DISALLOW_THREAD_BLOCKING_CALLS();
  bool receive =
      enabled() && RtpTransceiverDirectionHasRecv(local_content_direction());
  media_receive_channel()->SetReceive(receive);

  bool send = IsReadyToSendMedia_w();
  media_send_channel()->SetSend(send);

  RTC_LOG(LS_INFO) << "Changing state, recv=" << receive << " send=" << send
                   << " for " << ToString();
}

RTCError BaseChannel::SetLocalContent_w(const MediaContentDescription* content,
                                        SdpType type) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetLocalContent_w");
  RTC_DLOG(LS_INFO) << "Setting local description for " << ToString();

  RtpHeaderExtensions header_extensions =
      GetDeduplicatedRtpHeaderExtensions(content->rtp_header_extensions());

  std::optional<flat_set<uint8_t>> payload_types;
  if (RtpTransceiverDirectionHasRecv(content->direction())) {
    payload_types.emplace();
    for (const Codec& codec : content->codecs()) {
      payload_types->insert(codec.id);
    }
  }

  RTCError error = MaybeUpdateDemuxerAndRtpExtensions_w(
      /*update_demuxer=*/false, std::move(payload_types), header_extensions,
      /*ssrcs=*/std::nullopt);
  if (!error.ok()) {
    return error;
  }

  RTC_LOG_THREAD_BLOCK_COUNT();

  media_send_channel()->SetExtmapAllowMixed(content->extmap_allow_mixed());

  if (media_type_ == MediaType::VIDEO) {
    VideoReceiverParameters recv_params =
        std::get<VideoReceiverParameters>(last_recv_params_);
    MediaChannelParametersFromMediaDescription(
        content, header_extensions,
        RtpTransceiverDirectionHasRecv(content->direction()), &recv_params);
    recv_params.mid = mid();

    VideoSenderParameters send_params;
    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      send_params = std::get<VideoSenderParameters>(last_send_params_);
      send_params.extensions = header_extensions;
      send_params.extmap_allow_mixed = content->extmap_allow_mixed();

      error = MaybeIgnorePacketization(recv_params, send_params);
      if (!error.ok())
        return error;
    }

    if (!video_media_receive_channel()->SetReceiverParameters(recv_params)) {
      StringBuilder sb;
      sb << "Failed to set local video description recv parameters for "
            "m-section with mid='"
         << mid() << "'.";
      error = RTCError::InvalidParameter(sb.str());
      return error;
    }
    last_recv_params_ = recv_params;

    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      if (!video_media_send_channel()->SetSenderParameters(send_params)) {
        StringBuilder sb;
        sb << "Failed to set send parameters for m-section with mid='" << mid()
           << "'.";
        error = RTCError::InvalidParameter(sb.str());
        return error;
      }
      last_send_params_ = send_params;
    }
  } else {
    AudioReceiverParameters recv_params =
        std::get<AudioReceiverParameters>(last_recv_params_);
    MediaChannelParametersFromMediaDescription(
        content, header_extensions,
        RtpTransceiverDirectionHasRecv(content->direction()), &recv_params);
    recv_params.mid = mid();

    AudioSenderParameter send_params;
    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      send_params = std::get<AudioSenderParameter>(last_send_params_);
      send_params.extensions = header_extensions;
      send_params.extmap_allow_mixed = content->extmap_allow_mixed();
    }

    if (!voice_media_receive_channel()->SetReceiverParameters(recv_params)) {
      StringBuilder sb;
      sb << "Failed to set local audio description recv parameters for "
            "m-section with mid='"
         << mid() << "'.";
      error = RTCError::InvalidParameter(sb.str());
      return error;
    }
    last_recv_params_ = recv_params;

    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      if (!voice_media_send_channel()->SetSenderParameters(send_params)) {
        StringBuilder sb;
        sb << "Failed to set send parameters for m-section with mid='" << mid()
           << "'.";
        error = RTCError::InvalidParameter(sb.str());
        return error;
      }
      last_send_params_ = send_params;
    }
  }

  error = UpdateLocalStreams_w(content->streams(), type);
  if (!error.ok()) {
    return error;
  }

  set_local_content_direction(content->direction());
  UpdateMediaSendRecvState_w();

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);

  return RTCError::OK();
}

RTCError BaseChannel::SetRemoteContent_w(const MediaContentDescription* content,
                                         SdpType type) {
  TRACE_EVENT0("webrtc", "BaseChannel::SetRemoteContent_w");
  RTC_LOG(LS_INFO) << "Setting remote description for " << ToString();

  RtpHeaderExtensions header_extensions =
      GetDeduplicatedRtpHeaderExtensions(content->rtp_header_extensions());

  RTCError error = MaybeUpdateDemuxerAndRtpExtensions_w(
      /*update_demuxer=*/false, /*payload_types=*/std::nullopt,
      header_extensions, /*ssrcs=*/std::nullopt);
  if (!error.ok()) {
    return error;
  }

  RTC_LOG_THREAD_BLOCK_COUNT();

  if (media_type_ == MediaType::VIDEO) {
    VideoSenderParameters send_params =
        std::get<VideoSenderParameters>(last_send_params_);
    RtpSendParametersFromMediaDescription(content, extensions_filter(),
                                          &send_params);
    send_params.mid = mid();
    send_params.conference_mode = content->conference_mode();

    VideoReceiverParameters recv_params;
    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      recv_params = std::get<VideoReceiverParameters>(last_recv_params_);
      recv_params.extensions = send_params.extensions;
      recv_params.rtcp.reduced_size = send_params.rtcp.reduced_size;

      error = MaybeIgnorePacketization(send_params, recv_params);
      if (!error.ok())
        return error;
    }

    if (!video_media_send_channel()->SetSenderParameters(send_params)) {
      StringBuilder sb;
      sb << "Failed to set remote video description send parameters for "
            "m-section with mid='"
         << mid() << "'.";
      return RTCError::InvalidParameter(sb.str());
    }
    last_send_params_ = send_params;

    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      if (!video_media_receive_channel()->SetReceiverParameters(recv_params)) {
        StringBuilder sb;
        sb << "Failed to set recv parameters for m-section with mid='" << mid()
           << "'.";
        return RTCError::InvalidParameter(sb.str());
      }
      last_recv_params_ = recv_params;
    }
  } else {
    AudioSenderParameter send_params =
        std::get<AudioSenderParameter>(last_send_params_);
    RtpSendParametersFromMediaDescription(content, extensions_filter(),
                                          &send_params);
    send_params.mid = mid();

    AudioReceiverParameters recv_params;
    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      recv_params = std::get<AudioReceiverParameters>(last_recv_params_);
      recv_params.extensions = send_params.extensions;
    }

    if (!voice_media_send_channel()->SetSenderParameters(send_params)) {
      StringBuilder sb;
      sb << "Failed to set remote audio description send parameters for "
            "m-section with mid='"
         << mid() << "'.";
      return RTCError::InvalidParameter(sb.str());
    }
    last_send_params_ = send_params;

    if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
      if (!voice_media_receive_channel()->SetReceiverParameters(recv_params)) {
        StringBuilder sb;
        sb << "Failed to set recv parameters for m-section with mid='" << mid()
           << "'.";
        return RTCError::InvalidParameter(sb.str());
      }
      last_recv_params_ = recv_params;
    }
  }

  if (media_type_ == MediaType::AUDIO) {
    voice_media_receive_channel()->SetRtcpMode(content->rtcp_reduced_size()
                                                   ? RtcpMode::kReducedSize
                                                   : RtcpMode::kCompound);
    voice_media_receive_channel()->SetReceiveNackEnabled(
        voice_media_send_channel()->SenderNackEnabled());
    voice_media_receive_channel()->SetReceiveNonSenderRttEnabled(
        voice_media_send_channel()->SenderNonSenderRttEnabled());
  }

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);

  error = UpdateRemoteStreams_w(content, type);

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);

  return error;
}

void BaseChannel::UpdateWritableState_n() {
  TRACE_EVENT0("webrtc", "BaseChannel::UpdateWritableState_n");
  if (rtp_transport_->IsWritable(/*rtcp=*/true) &&
      rtp_transport_->IsWritable(/*rtcp=*/false)) {
    ChannelWritable_n();
  } else {
    ChannelNotWritable_n();
  }
}

void BaseChannel::ChannelWritable_n() {
  TRACE_EVENT0("webrtc", "BaseChannel::ChannelWritable_n");
  if (writable_) {
    return;
  }
  writable_ = true;
  RTC_LOG(LS_INFO) << "Channel writable (" << ToString() << ")"
                   << (was_ever_writable_n_ ? "" : " for the first time");
  // We only have to do this PostTask once, when first transitioning to
  // writable.
  if (!was_ever_writable_n_) {
    worker_thread_->PostTask(SafeTask(alive_, [this] {
      RTC_DCHECK_RUN_ON(worker_thread());
      was_ever_writable_ = true;
      UpdateMediaSendRecvState_w();
    }));
  }
  was_ever_writable_n_ = true;
}

void BaseChannel::ChannelNotWritable_n() {
  TRACE_EVENT0("webrtc", "BaseChannel::ChannelNotWritable_n");
  if (!writable_) {
    return;
  }
  writable_ = false;
  RTC_LOG(LS_INFO) << "Channel not writable (" << ToString() << ")";
}

RTCError BaseChannel::UpdateLocalStreams_w(
    const std::vector<StreamParams>& streams,
    SdpType type) {
  RTC_DCHECK_DISALLOW_THREAD_BLOCKING_CALLS();
  // In the case of RIDs (where SSRCs are not negotiated), this method will
  // generate an SSRC for each layer in StreamParams. That representation will
  // be stored internally in `local_streams_`.
  // In subsequent offers, the same stream can appear in `streams` again
  // (without the SSRCs), so it should be looked up using RIDs (if available)
  // and then by primary SSRC.
  // In both scenarios, it is safe to assume that the media channel will be
  // created with a StreamParams object with SSRCs. However, it is not safe to
  // assume that `local_streams_` will always have SSRCs as there are scenarios
  // in which niether SSRCs or RIDs are negotiated.

  // Check for streams that have been removed.
  for (const StreamParams& old_stream : local_streams_) {
    if (!old_stream.has_ssrcs() ||
        GetStream(streams, StreamFinder(&old_stream))) {
      continue;
    }
    if (!media_send_channel()->RemoveSendStream(old_stream.first_ssrc())) {
      return RTCError::InvalidParameter()
             << "Failed to remove send stream with ssrc "
             << old_stream.first_ssrc() << " from m-section with mid='" << mid()
             << "'.";
    }
  }
  // Check for new streams.
  std::vector<StreamParams> all_streams;
  for (const StreamParams& stream : streams) {
    StreamParams* existing = GetStream(local_streams_, StreamFinder(&stream));
    if (existing) {
      // Parameters cannot change for an existing stream.
      all_streams.push_back(*existing);
      continue;
    }

    all_streams.push_back(stream);
    StreamParams& new_stream = all_streams.back();

    if (!new_stream.has_ssrcs() && !new_stream.has_rids()) {
      continue;
    }

    RTC_DCHECK(new_stream.has_ssrcs() || new_stream.has_rids());
    if (new_stream.has_ssrcs() && new_stream.has_rids()) {
      return RTCError::InvalidParameter()
             << "Failed to add send stream: " << new_stream.first_ssrc()
             << " into m-section with mid='" << mid()
             << "'. Stream has both SSRCs and RIDs.";
    }

    // At this point we use the legacy simulcast group in StreamParams to
    // indicate that we want multiple layers to the media channel.
    if (!new_stream.has_ssrcs()) {
      // TODO(bugs.webrtc.org/10250): Indicate if flex is desired here.
      new_stream.GenerateSsrcs(new_stream.rids().size(), /* rtx = */ true,
                               /* flex_fec = */ false, ssrc_generator_);
    }

    if (media_send_channel()->AddSendStream(new_stream)) {
      RTC_LOG(LS_INFO) << "Add send stream ssrc: " << new_stream.first_ssrc()
                       << " into " << ToString();
    } else {
      return RTCError::InvalidParameter()
             << "Failed to add send stream ssrc: " << new_stream.first_ssrc()
             << " into m-section with mid='" << mid() << "'";
    }
  }
  local_streams_ = all_streams;
  return RTCError::OK();
}

RTCError BaseChannel::UpdateRemoteStreams_w(
    const MediaContentDescription* content,
    SdpType type) {
  RTC_LOG_THREAD_BLOCK_COUNT();
  media_receive_channel()->OnDemuxerCriteriaUpdatePending();
  absl::Cleanup cleanup = [this] {
    media_receive_channel()->OnDemuxerCriteriaUpdateComplete();
  };

  const std::vector<StreamParams>& streams = content->streams();
  const bool new_has_unsignaled_ssrcs = HasStreamWithNoSsrcs(streams);
  const bool old_has_unsignaled_ssrcs = HasStreamWithNoSsrcs(remote_streams_);

  // Check for streams that have been removed.
  std::vector<uint32_t> removed_ssrcs;
  bool reset_unsignaled_streams = false;
  for (const StreamParams& old_stream : remote_streams_) {
    // If we no longer have an unsignaled stream, we would like to remove
    // the unsignaled stream params that are cached.
    if (!old_stream.has_ssrcs() && !new_has_unsignaled_ssrcs) {
      if (!reset_unsignaled_streams) {
        reset_unsignaled_streams = true;
        std::vector<uint32_t> unsignaled =
            media_receive_channel()->GetUnsignaledSsrcs();
        removed_ssrcs.insert(removed_ssrcs.end(), unsignaled.begin(),
                             unsignaled.end());
        RTC_LOG(LS_INFO) << "Reset unsignaled remote stream for " << ToString()
                         << ".";
      }
    } else if (old_stream.has_ssrcs() &&
               !GetStreamBySsrc(streams, old_stream.first_ssrc())) {
      removed_ssrcs.push_back(old_stream.first_ssrc());
    }
  }

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);

  // Re-register the sink to update after changing the demuxer criteria first.
  if (!RegisterRtpDemuxerSink_w(content, std::move(removed_ssrcs))) {
    return RTCError::InvalidParameter()
           << "Failed to set up audio demuxing for mid='" << mid() << "'.";
  }

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);

  if (reset_unsignaled_streams) {
    media_receive_channel()->ResetUnsignaledRecvStream();
  }

  // Now remove the old streams on the worker thread.
  for (const StreamParams& old_stream : remote_streams_) {
    if (old_stream.has_ssrcs() &&
        !GetStreamBySsrc(streams, old_stream.first_ssrc())) {
      if (media_receive_channel()->RemoveRecvStream(old_stream.first_ssrc())) {
        RTC_LOG(LS_INFO) << "Remove remote ssrc: " << old_stream.first_ssrc()
                         << " from " << ToString() << ".";
      } else {
        return RTCError::InvalidParameter()
               << "Failed to remove remote stream with ssrc "
               << old_stream.first_ssrc() << " from m-section with mid='"
               << mid() << "'.";
      }
    }
  }

  // Check for new streams.
  for (const StreamParams& new_stream : streams) {
    // We allow a StreamParams with an empty list of SSRCs, in which case the
    // MediaChannel will cache the parameters and use them for any unsignaled
    // stream received later.
    if ((!new_stream.has_ssrcs() && !old_has_unsignaled_ssrcs) ||
        !GetStreamBySsrc(remote_streams_, new_stream.first_ssrc())) {
      if (media_receive_channel()->AddRecvStream(new_stream)) {
        RTC_LOG(LS_INFO) << "Add remote ssrc: "
                         << (new_stream.has_ssrcs()
                                 ? std::to_string(new_stream.first_ssrc())
                                 : "unsignaled")
                         << " to " << ToString();
      } else {
        return RTCError::InvalidParameter()
               << "Failed to add remote stream ssrc: "
               << (new_stream.has_ssrcs()
                       ? std::to_string(new_stream.first_ssrc())
                       : "unsignaled")
               << " to " << ToString();
      }
    }
  }

  remote_streams_ = streams;

  set_remote_content_direction(content->direction());
  UpdateMediaSendRecvState_w();

  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);

  return RTCError::OK();
}

RtpHeaderExtensions BaseChannel::GetDeduplicatedRtpHeaderExtensions(
    const RtpHeaderExtensions& extensions) {
  return RtpExtension::DeduplicateHeaderExtensions(extensions,
                                                   extensions_filter_);
}

void BaseChannel::SignalSentPacket_n(const SentPacketInfo& sent_packet) {
  RTC_DCHECK_RUN_ON(network_thread());
  RTC_DCHECK(network_initialized());
  media_send_channel()->OnPacketSent(sent_packet);
}

}  // namespace webrtc
