/*
 *  Copyright 2017 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 "webrtc/ortc/rtptransportcontrolleradapter.h"

#include <algorithm>  // For "remove", "find".
#include <set>
#include <sstream>
#include <unordered_map>
#include <utility>  // For std::move.

#include "webrtc/api/proxy.h"
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/ortc/ortcrtpreceiveradapter.h"
#include "webrtc/ortc/ortcrtpsenderadapter.h"
#include "webrtc/ortc/rtpparametersconversion.h"
#include "webrtc/ortc/rtptransportadapter.h"
#include "webrtc/rtc_base/checks.h"

namespace webrtc {

// Note: It's assumed that each individual list doesn't have conflicts, since
// they should have been detected already by rtpparametersconversion.cc. This
// only needs to detect conflicts *between* A and B.
template <typename C1, typename C2>
static RTCError CheckForIdConflicts(
    const std::vector<C1>& codecs_a,
    const cricket::RtpHeaderExtensions& extensions_a,
    const cricket::StreamParamsVec& streams_a,
    const std::vector<C2>& codecs_b,
    const cricket::RtpHeaderExtensions& extensions_b,
    const cricket::StreamParamsVec& streams_b) {
  std::ostringstream oss;
  // Since it's assumed that C1 and C2 are different types, codecs_a and
  // codecs_b should never contain the same payload type, and thus we can just
  // use a set.
  std::set<int> seen_payload_types;
  for (const C1& codec : codecs_a) {
    seen_payload_types.insert(codec.id);
  }
  for (const C2& codec : codecs_b) {
    if (!seen_payload_types.insert(codec.id).second) {
      oss << "Same payload type used for audio and video codecs: " << codec.id;
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, oss.str());
    }
  }
  // Audio and video *may* use the same header extensions, so use a map.
  std::unordered_map<int, std::string> seen_extensions;
  for (const webrtc::RtpExtension& extension : extensions_a) {
    seen_extensions[extension.id] = extension.uri;
  }
  for (const webrtc::RtpExtension& extension : extensions_b) {
    if (seen_extensions.find(extension.id) != seen_extensions.end() &&
        seen_extensions.at(extension.id) != extension.uri) {
      oss << "Same ID used for different RTP header extensions: "
          << extension.id;
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, oss.str());
    }
  }
  std::set<uint32_t> seen_ssrcs;
  for (const cricket::StreamParams& stream : streams_a) {
    seen_ssrcs.insert(stream.ssrcs.begin(), stream.ssrcs.end());
  }
  for (const cricket::StreamParams& stream : streams_b) {
    for (uint32_t ssrc : stream.ssrcs) {
      if (!seen_ssrcs.insert(ssrc).second) {
        oss << "Same SSRC used for audio and video senders: " << ssrc;
        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, oss.str());
      }
    }
  }
  return RTCError::OK();
}

BEGIN_OWNED_PROXY_MAP(RtpTransportController)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_CONSTMETHOD0(std::vector<RtpTransportInterface*>, GetTransports)
protected:
RtpTransportControllerAdapter* GetInternal() override {
  return internal();
}
END_PROXY_MAP()

// static
std::unique_ptr<RtpTransportControllerInterface>
RtpTransportControllerAdapter::CreateProxied(
    const cricket::MediaConfig& config,
    cricket::ChannelManager* channel_manager,
    webrtc::RtcEventLog* event_log,
    rtc::Thread* signaling_thread,
    rtc::Thread* worker_thread) {
  std::unique_ptr<RtpTransportControllerAdapter> wrapped(
      new RtpTransportControllerAdapter(config, channel_manager, event_log,
                                        signaling_thread, worker_thread));
  return RtpTransportControllerProxyWithInternal<
      RtpTransportControllerAdapter>::Create(signaling_thread, worker_thread,
                                             std::move(wrapped));
}

RtpTransportControllerAdapter::~RtpTransportControllerAdapter() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  if (!transport_proxies_.empty()) {
    LOG(LS_ERROR)
        << "Destroying RtpTransportControllerAdapter while RtpTransports "
           "are still using it; this is unsafe.";
  }
  if (voice_channel_) {
    // This would mean audio RTP senders/receivers that are using us haven't
    // been destroyed. This isn't safe (see error log above).
    DestroyVoiceChannel();
  }
  if (voice_channel_) {
    // This would mean video RTP senders/receivers that are using us haven't
    // been destroyed. This isn't safe (see error log above).
    DestroyVideoChannel();
  }
  // Call must be destroyed on the worker thread.
  worker_thread_->Invoke<void>(
      RTC_FROM_HERE,
      rtc::Bind(&RtpTransportControllerAdapter::Close_w, this));
}

RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
RtpTransportControllerAdapter::CreateProxiedRtpTransport(
    const RtpTransportParameters& parameters,
    PacketTransportInterface* rtp,
    PacketTransportInterface* rtcp) {
  if (!transport_proxies_.empty() && (parameters.keepalive != keepalive_)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                         "Cannot create RtpTransport with different keep-alive "
                         "from the RtpTransports already associated with this "
                         "transport controller.");
  }
  auto result = RtpTransportAdapter::CreateProxied(parameters, rtp, rtcp, this);
  if (result.ok()) {
    transport_proxies_.push_back(result.value().get());
    transport_proxies_.back()->GetInternal()->SignalDestroyed.connect(
        this, &RtpTransportControllerAdapter::OnRtpTransportDestroyed);
  }
  return result;
}

RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
RtpTransportControllerAdapter::CreateProxiedSrtpTransport(
    const RtpTransportParameters& parameters,
    PacketTransportInterface* rtp,
    PacketTransportInterface* rtcp) {
  auto result =
      RtpTransportAdapter::CreateSrtpProxied(parameters, rtp, rtcp, this);
  if (result.ok()) {
    transport_proxies_.push_back(result.value().get());
    transport_proxies_.back()->GetInternal()->SignalDestroyed.connect(
        this, &RtpTransportControllerAdapter::OnRtpTransportDestroyed);
  }
  return result;
}

RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
RtpTransportControllerAdapter::CreateProxiedRtpSender(
    cricket::MediaType kind,
    RtpTransportInterface* transport_proxy) {
  RTC_DCHECK(transport_proxy);
  RTC_DCHECK(std::find(transport_proxies_.begin(), transport_proxies_.end(),
                       transport_proxy) != transport_proxies_.end());
  std::unique_ptr<OrtcRtpSenderAdapter> new_sender(
      new OrtcRtpSenderAdapter(kind, transport_proxy, this));
  RTCError err;
  switch (kind) {
    case cricket::MEDIA_TYPE_AUDIO:
      err = AttachAudioSender(new_sender.get(), transport_proxy->GetInternal());
      break;
    case cricket::MEDIA_TYPE_VIDEO:
      err = AttachVideoSender(new_sender.get(), transport_proxy->GetInternal());
      break;
    case cricket::MEDIA_TYPE_DATA:
      RTC_NOTREACHED();
  }
  if (!err.ok()) {
    return std::move(err);
  }

  return OrtcRtpSenderAdapter::CreateProxy(std::move(new_sender));
}

RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
RtpTransportControllerAdapter::CreateProxiedRtpReceiver(
    cricket::MediaType kind,
    RtpTransportInterface* transport_proxy) {
  RTC_DCHECK(transport_proxy);
  RTC_DCHECK(std::find(transport_proxies_.begin(), transport_proxies_.end(),
                       transport_proxy) != transport_proxies_.end());
  std::unique_ptr<OrtcRtpReceiverAdapter> new_receiver(
      new OrtcRtpReceiverAdapter(kind, transport_proxy, this));
  RTCError err;
  switch (kind) {
    case cricket::MEDIA_TYPE_AUDIO:
      err = AttachAudioReceiver(new_receiver.get(),
                                transport_proxy->GetInternal());
      break;
    case cricket::MEDIA_TYPE_VIDEO:
      err = AttachVideoReceiver(new_receiver.get(),
                                transport_proxy->GetInternal());
      break;
    case cricket::MEDIA_TYPE_DATA:
      RTC_NOTREACHED();
  }
  if (!err.ok()) {
    return std::move(err);
  }

  return OrtcRtpReceiverAdapter::CreateProxy(std::move(new_receiver));
}

std::vector<RtpTransportInterface*>
RtpTransportControllerAdapter::GetTransports() const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  return transport_proxies_;
}

RTCError RtpTransportControllerAdapter::SetRtpTransportParameters(
    const RtpTransportParameters& parameters,
    RtpTransportInterface* inner_transport) {
  if ((video_channel_ != nullptr || voice_channel_ != nullptr) &&
      (parameters.keepalive != keepalive_)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
                         "Cannot change keep-alive settings after creating "
                         "media streams or additional transports for the same "
                         "transport controller.");
  }
  // Call must be configured on the worker thread.
  worker_thread_->Invoke<void>(
      RTC_FROM_HERE,
      rtc::Bind(&RtpTransportControllerAdapter::SetRtpTransportParameters_w,
                this, parameters));

  do {
    if (inner_transport == inner_audio_transport_) {
      CopyRtcpParametersToDescriptions(parameters.rtcp,
                                       &local_audio_description_,
                                       &remote_audio_description_);
      if (!voice_channel_->SetLocalContent(&local_audio_description_,
                                           cricket::CA_OFFER, nullptr)) {
        break;
      }
      if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
                                            cricket::CA_ANSWER, nullptr)) {
        break;
      }
    } else if (inner_transport == inner_video_transport_) {
      CopyRtcpParametersToDescriptions(parameters.rtcp,
                                       &local_video_description_,
                                       &remote_video_description_);
      if (!video_channel_->SetLocalContent(&local_video_description_,
                                           cricket::CA_OFFER, nullptr)) {
        break;
      }
      if (!video_channel_->SetRemoteContent(&remote_video_description_,
                                            cricket::CA_ANSWER, nullptr)) {
        break;
      }
    }
    return RTCError::OK();
  } while (false);
  LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                       "Failed to apply new RTCP parameters.");
}

void RtpTransportControllerAdapter::SetRtpTransportParameters_w(
    const RtpTransportParameters& parameters) {
  call_send_rtp_transport_controller_->SetKeepAliveConfig(parameters.keepalive);
}

RTCError RtpTransportControllerAdapter::ValidateAndApplyAudioSenderParameters(
    const RtpParameters& parameters,
    uint32_t* primary_ssrc) {
  RTC_DCHECK(voice_channel_);
  RTC_DCHECK(have_audio_sender_);

  auto codecs_result = ToCricketCodecs<cricket::AudioCodec>(parameters.codecs);
  if (!codecs_result.ok()) {
    return codecs_result.MoveError();
  }

  auto extensions_result =
      ToCricketRtpHeaderExtensions(parameters.header_extensions);
  if (!extensions_result.ok()) {
    return extensions_result.MoveError();
  }

  auto stream_params_result = MakeSendStreamParamsVec(
      parameters.encodings, inner_audio_transport_->GetParameters().rtcp.cname,
      local_audio_description_);
  if (!stream_params_result.ok()) {
    return stream_params_result.MoveError();
  }

  // Check that audio/video sender aren't using the same IDs to refer to
  // different things, if they share the same transport.
  if (inner_audio_transport_ == inner_video_transport_) {
    RTCError err = CheckForIdConflicts(
        codecs_result.value(), extensions_result.value(),
        stream_params_result.value(), remote_video_description_.codecs(),
        remote_video_description_.rtp_header_extensions(),
        local_video_description_.streams());
    if (!err.ok()) {
      return err;
    }
  }

  cricket::RtpTransceiverDirection local_direction =
      cricket::RtpTransceiverDirection::FromMediaContentDirection(
          local_audio_description_.direction());
  int bandwidth = cricket::kAutoBandwidth;
  if (parameters.encodings.size() == 1u) {
    if (parameters.encodings[0].max_bitrate_bps) {
      bandwidth = *parameters.encodings[0].max_bitrate_bps;
    }
    local_direction.send = parameters.encodings[0].active;
  } else {
    local_direction.send = false;
  }
  if (primary_ssrc && !stream_params_result.value().empty()) {
    *primary_ssrc = stream_params_result.value()[0].first_ssrc();
  }

  // Validation is done, so we can attempt applying the descriptions. Sent
  // codecs and header extensions go in remote description, streams go in
  // local.
  //
  // If there are no codecs or encodings, just leave the previous set of
  // codecs. The media engine doesn't like an empty set of codecs.
  if (local_audio_description_.streams().empty() &&
      remote_audio_description_.codecs().empty()) {
  } else {
    remote_audio_description_.set_codecs(codecs_result.MoveValue());
  }
  remote_audio_description_.set_rtp_header_extensions(
      extensions_result.MoveValue());
  remote_audio_description_.set_bandwidth(bandwidth);
  local_audio_description_.mutable_streams() = stream_params_result.MoveValue();
  // Direction set based on encoding "active" flag.
  local_audio_description_.set_direction(
      local_direction.ToMediaContentDirection());
  remote_audio_description_.set_direction(
      local_direction.Reversed().ToMediaContentDirection());

  // Set remote content first, to ensure the stream is created with the correct
  // codec.
  if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
                                        cricket::CA_OFFER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply remote parameters to media channel.");
  }
  if (!voice_channel_->SetLocalContent(&local_audio_description_,
                                       cricket::CA_ANSWER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply local parameters to media channel.");
  }
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::ValidateAndApplyVideoSenderParameters(
    const RtpParameters& parameters,
    uint32_t* primary_ssrc) {
  RTC_DCHECK(video_channel_);
  RTC_DCHECK(have_video_sender_);

  auto codecs_result = ToCricketCodecs<cricket::VideoCodec>(parameters.codecs);
  if (!codecs_result.ok()) {
    return codecs_result.MoveError();
  }

  auto extensions_result =
      ToCricketRtpHeaderExtensions(parameters.header_extensions);
  if (!extensions_result.ok()) {
    return extensions_result.MoveError();
  }

  auto stream_params_result = MakeSendStreamParamsVec(
      parameters.encodings, inner_video_transport_->GetParameters().rtcp.cname,
      local_video_description_);
  if (!stream_params_result.ok()) {
    return stream_params_result.MoveError();
  }

  // Check that audio/video sender aren't using the same IDs to refer to
  // different things, if they share the same transport.
  if (inner_audio_transport_ == inner_video_transport_) {
    RTCError err = CheckForIdConflicts(
        codecs_result.value(), extensions_result.value(),
        stream_params_result.value(), remote_audio_description_.codecs(),
        remote_audio_description_.rtp_header_extensions(),
        local_audio_description_.streams());
    if (!err.ok()) {
      return err;
    }
  }

  cricket::RtpTransceiverDirection local_direction =
      cricket::RtpTransceiverDirection::FromMediaContentDirection(
          local_video_description_.direction());
  int bandwidth = cricket::kAutoBandwidth;
  if (parameters.encodings.size() == 1u) {
    if (parameters.encodings[0].max_bitrate_bps) {
      bandwidth = *parameters.encodings[0].max_bitrate_bps;
    }
    local_direction.send = parameters.encodings[0].active;
  } else {
    local_direction.send = false;
  }
  if (primary_ssrc && !stream_params_result.value().empty()) {
    *primary_ssrc = stream_params_result.value()[0].first_ssrc();
  }

  // Validation is done, so we can attempt applying the descriptions. Sent
  // codecs and header extensions go in remote description, streams go in
  // local.
  //
  // If there are no codecs or encodings, just leave the previous set of
  // codecs. The media engine doesn't like an empty set of codecs.
  if (local_video_description_.streams().empty() &&
      remote_video_description_.codecs().empty()) {
  } else {
    remote_video_description_.set_codecs(codecs_result.MoveValue());
  }
  remote_video_description_.set_rtp_header_extensions(
      extensions_result.MoveValue());
  remote_video_description_.set_bandwidth(bandwidth);
  local_video_description_.mutable_streams() = stream_params_result.MoveValue();
  // Direction set based on encoding "active" flag.
  local_video_description_.set_direction(
      local_direction.ToMediaContentDirection());
  remote_video_description_.set_direction(
      local_direction.Reversed().ToMediaContentDirection());

  // Set remote content first, to ensure the stream is created with the correct
  // codec.
  if (!video_channel_->SetRemoteContent(&remote_video_description_,
                                        cricket::CA_OFFER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply remote parameters to media channel.");
  }
  if (!video_channel_->SetLocalContent(&local_video_description_,
                                       cricket::CA_ANSWER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply local parameters to media channel.");
  }
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::ValidateAndApplyAudioReceiverParameters(
    const RtpParameters& parameters) {
  RTC_DCHECK(voice_channel_);
  RTC_DCHECK(have_audio_receiver_);

  auto codecs_result = ToCricketCodecs<cricket::AudioCodec>(parameters.codecs);
  if (!codecs_result.ok()) {
    return codecs_result.MoveError();
  }

  auto extensions_result =
      ToCricketRtpHeaderExtensions(parameters.header_extensions);
  if (!extensions_result.ok()) {
    return extensions_result.MoveError();
  }

  cricket::RtpTransceiverDirection local_direction =
      cricket::RtpTransceiverDirection::FromMediaContentDirection(
          local_audio_description_.direction());
  auto stream_params_result = ToCricketStreamParamsVec(parameters.encodings);
  if (!stream_params_result.ok()) {
    return stream_params_result.MoveError();
  }

  // Check that audio/video receive aren't using the same IDs to refer to
  // different things, if they share the same transport.
  if (inner_audio_transport_ == inner_video_transport_) {
    RTCError err = CheckForIdConflicts(
        codecs_result.value(), extensions_result.value(),
        stream_params_result.value(), local_video_description_.codecs(),
        local_video_description_.rtp_header_extensions(),
        remote_video_description_.streams());
    if (!err.ok()) {
      return err;
    }
  }

  local_direction.recv =
      !parameters.encodings.empty() && parameters.encodings[0].active;

  // Validation is done, so we can attempt applying the descriptions. Received
  // codecs and header extensions go in local description, streams go in
  // remote.
  //
  // If there are no codecs or encodings, just leave the previous set of
  // codecs. The media engine doesn't like an empty set of codecs.
  if (remote_audio_description_.streams().empty() &&
      local_audio_description_.codecs().empty()) {
  } else {
    local_audio_description_.set_codecs(codecs_result.MoveValue());
  }
  local_audio_description_.set_rtp_header_extensions(
      extensions_result.MoveValue());
  remote_audio_description_.mutable_streams() =
      stream_params_result.MoveValue();
  // Direction set based on encoding "active" flag.
  local_audio_description_.set_direction(
      local_direction.ToMediaContentDirection());
  remote_audio_description_.set_direction(
      local_direction.Reversed().ToMediaContentDirection());

  if (!voice_channel_->SetLocalContent(&local_audio_description_,
                                       cricket::CA_OFFER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply local parameters to media channel.");
  }
  if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
                                        cricket::CA_ANSWER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply remote parameters to media channel.");
  }
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::ValidateAndApplyVideoReceiverParameters(
    const RtpParameters& parameters) {
  RTC_DCHECK(video_channel_);
  RTC_DCHECK(have_video_receiver_);

  auto codecs_result = ToCricketCodecs<cricket::VideoCodec>(parameters.codecs);
  if (!codecs_result.ok()) {
    return codecs_result.MoveError();
  }

  auto extensions_result =
      ToCricketRtpHeaderExtensions(parameters.header_extensions);
  if (!extensions_result.ok()) {
    return extensions_result.MoveError();
  }

  cricket::RtpTransceiverDirection local_direction =
      cricket::RtpTransceiverDirection::FromMediaContentDirection(
          local_video_description_.direction());
  int bandwidth = cricket::kAutoBandwidth;
  auto stream_params_result = ToCricketStreamParamsVec(parameters.encodings);
  if (!stream_params_result.ok()) {
    return stream_params_result.MoveError();
  }

  // Check that audio/video receiver aren't using the same IDs to refer to
  // different things, if they share the same transport.
  if (inner_audio_transport_ == inner_video_transport_) {
    RTCError err = CheckForIdConflicts(
        codecs_result.value(), extensions_result.value(),
        stream_params_result.value(), local_audio_description_.codecs(),
        local_audio_description_.rtp_header_extensions(),
        remote_audio_description_.streams());
    if (!err.ok()) {
      return err;
    }
  }

  local_direction.recv =
      !parameters.encodings.empty() && parameters.encodings[0].active;

  // Validation is done, so we can attempt applying the descriptions. Received
  // codecs and header extensions go in local description, streams go in
  // remote.
  //
  // If there are no codecs or encodings, just leave the previous set of
  // codecs. The media engine doesn't like an empty set of codecs.
  if (remote_video_description_.streams().empty() &&
      local_video_description_.codecs().empty()) {
  } else {
    local_video_description_.set_codecs(codecs_result.MoveValue());
  }
  local_video_description_.set_rtp_header_extensions(
      extensions_result.MoveValue());
  local_video_description_.set_bandwidth(bandwidth);
  remote_video_description_.mutable_streams() =
      stream_params_result.MoveValue();
  // Direction set based on encoding "active" flag.
  local_video_description_.set_direction(
      local_direction.ToMediaContentDirection());
  remote_video_description_.set_direction(
      local_direction.Reversed().ToMediaContentDirection());

  if (!video_channel_->SetLocalContent(&local_video_description_,
                                       cricket::CA_OFFER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply local parameters to media channel.");
  }
  if (!video_channel_->SetRemoteContent(&remote_video_description_,
                                        cricket::CA_ANSWER, nullptr)) {
    LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
                         "Failed to apply remote parameters to media channel.");
  }
  return RTCError::OK();
}

RtpTransportControllerAdapter::RtpTransportControllerAdapter(
    const cricket::MediaConfig& config,
    cricket::ChannelManager* channel_manager,
    webrtc::RtcEventLog* event_log,
    rtc::Thread* signaling_thread,
    rtc::Thread* worker_thread)
    : signaling_thread_(signaling_thread),
      worker_thread_(worker_thread),
      media_config_(config),
      channel_manager_(channel_manager),
      event_log_(event_log),
      call_send_rtp_transport_controller_(nullptr) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  RTC_DCHECK(channel_manager_);
  // Add "dummy" codecs to the descriptions, because the media engines
  // currently reject empty lists of codecs. Note that these codecs will never
  // actually be used, because when parameters are set, the dummy codecs will
  // be replaced by actual codecs before any send/receive streams are created.
  static const cricket::AudioCodec dummy_audio(0, cricket::kPcmuCodecName, 8000,
                                               0, 1);
  static const cricket::VideoCodec dummy_video(96, cricket::kVp8CodecName);
  local_audio_description_.AddCodec(dummy_audio);
  remote_audio_description_.AddCodec(dummy_audio);
  local_video_description_.AddCodec(dummy_video);
  remote_video_description_.AddCodec(dummy_video);

  worker_thread_->Invoke<void>(
      RTC_FROM_HERE,
      rtc::Bind(&RtpTransportControllerAdapter::Init_w, this));
}

// TODO(nisse): Duplicates corresponding method in PeerConnection (used
// to be in MediaController).
void RtpTransportControllerAdapter::Init_w() {
  RTC_DCHECK(worker_thread_->IsCurrent());
  RTC_DCHECK(!call_);

  const int kMinBandwidthBps = 30000;
  const int kStartBandwidthBps = 300000;
  const int kMaxBandwidthBps = 2000000;

  webrtc::Call::Config call_config(event_log_);
  call_config.audio_state = channel_manager_->media_engine()->GetAudioState();
  call_config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
  call_config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
  call_config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;

  call_send_rtp_transport_controller_ =
      new RtpTransportControllerSend(Clock::GetRealTimeClock(), event_log_);
  call_.reset(webrtc::Call::Create(
      call_config, std::unique_ptr<RtpTransportControllerSendInterface>(
                       call_send_rtp_transport_controller_)));
}

void RtpTransportControllerAdapter::Close_w() {
  call_.reset();
  call_send_rtp_transport_controller_ = nullptr;
}

RTCError RtpTransportControllerAdapter::AttachAudioSender(
    OrtcRtpSenderAdapter* sender,
    RtpTransportInterface* inner_transport) {
  if (have_audio_sender_) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using two audio RtpSenders with the same "
                         "RtpTransportControllerAdapter is not currently "
                         "supported.");
  }
  if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using different transports for the audio "
                         "RtpSender and RtpReceiver is not currently "
                         "supported.");
  }
  RTCError err = MaybeSetCryptos(inner_transport, &local_audio_description_,
                                 &remote_audio_description_);
  if (!err.ok()) {
    return err;
  }
  // If setting new transport, extract its RTCP parameters and create voice
  // channel.
  if (!inner_audio_transport_) {
    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                     &local_audio_description_,
                                     &remote_audio_description_);
    inner_audio_transport_ = inner_transport;
    CreateVoiceChannel();
  }
  have_audio_sender_ = true;
  sender->SignalDestroyed.connect(
      this, &RtpTransportControllerAdapter::OnAudioSenderDestroyed);
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::AttachVideoSender(
    OrtcRtpSenderAdapter* sender,
    RtpTransportInterface* inner_transport) {
  if (have_video_sender_) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using two video RtpSenders with the same "
                         "RtpTransportControllerAdapter is not currently "
                         "supported.");
  }
  if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using different transports for the video "
                         "RtpSender and RtpReceiver is not currently "
                         "supported.");
  }
  RTCError err = MaybeSetCryptos(inner_transport, &local_video_description_,
                                 &remote_video_description_);
  if (!err.ok()) {
    return err;
  }
  // If setting new transport, extract its RTCP parameters and create video
  // channel.
  if (!inner_video_transport_) {
    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                     &local_video_description_,
                                     &remote_video_description_);
    inner_video_transport_ = inner_transport;
    CreateVideoChannel();
  }
  have_video_sender_ = true;
  sender->SignalDestroyed.connect(
      this, &RtpTransportControllerAdapter::OnVideoSenderDestroyed);
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::AttachAudioReceiver(
    OrtcRtpReceiverAdapter* receiver,
    RtpTransportInterface* inner_transport) {
  if (have_audio_receiver_) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using two audio RtpReceivers with the same "
                         "RtpTransportControllerAdapter is not currently "
                         "supported.");
  }
  if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using different transports for the audio "
                         "RtpReceiver and RtpReceiver is not currently "
                         "supported.");
  }
  RTCError err = MaybeSetCryptos(inner_transport, &local_audio_description_,
                                 &remote_audio_description_);
  if (!err.ok()) {
    return err;
  }
  // If setting new transport, extract its RTCP parameters and create voice
  // channel.
  if (!inner_audio_transport_) {
    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                     &local_audio_description_,
                                     &remote_audio_description_);
    inner_audio_transport_ = inner_transport;
    CreateVoiceChannel();
  }
  have_audio_receiver_ = true;
  receiver->SignalDestroyed.connect(
      this, &RtpTransportControllerAdapter::OnAudioReceiverDestroyed);
  return RTCError::OK();
}

RTCError RtpTransportControllerAdapter::AttachVideoReceiver(
    OrtcRtpReceiverAdapter* receiver,
    RtpTransportInterface* inner_transport) {
  if (have_video_receiver_) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using two video RtpReceivers with the same "
                         "RtpTransportControllerAdapter is not currently "
                         "supported.");
  }
  if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
    LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
                         "Using different transports for the video "
                         "RtpReceiver and RtpReceiver is not currently "
                         "supported.");
  }
  RTCError err = MaybeSetCryptos(inner_transport, &local_video_description_,
                                 &remote_video_description_);
  if (!err.ok()) {
    return err;
  }
  // If setting new transport, extract its RTCP parameters and create video
  // channel.
  if (!inner_video_transport_) {
    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                     &local_video_description_,
                                     &remote_video_description_);
    inner_video_transport_ = inner_transport;
    CreateVideoChannel();
  }
  have_video_receiver_ = true;
  receiver->SignalDestroyed.connect(
      this, &RtpTransportControllerAdapter::OnVideoReceiverDestroyed);
  return RTCError::OK();
}

void RtpTransportControllerAdapter::OnRtpTransportDestroyed(
    RtpTransportAdapter* transport) {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  auto it = std::find_if(transport_proxies_.begin(), transport_proxies_.end(),
                         [transport](RtpTransportInterface* proxy) {
                           return proxy->GetInternal() == transport;
                         });
  if (it == transport_proxies_.end()) {
    RTC_NOTREACHED();
    return;
  }
  transport_proxies_.erase(it);
}

void RtpTransportControllerAdapter::OnAudioSenderDestroyed() {
  if (!have_audio_sender_) {
    RTC_NOTREACHED();
    return;
  }
  // Empty parameters should result in sending being stopped.
  RTCError err =
      ValidateAndApplyAudioSenderParameters(RtpParameters(), nullptr);
  RTC_DCHECK(err.ok());
  have_audio_sender_ = false;
  if (!have_audio_receiver_) {
    DestroyVoiceChannel();
  }
}

void RtpTransportControllerAdapter::OnVideoSenderDestroyed() {
  if (!have_video_sender_) {
    RTC_NOTREACHED();
    return;
  }
  // Empty parameters should result in sending being stopped.
  RTCError err =
      ValidateAndApplyVideoSenderParameters(RtpParameters(), nullptr);
  RTC_DCHECK(err.ok());
  have_video_sender_ = false;
  if (!have_video_receiver_) {
    DestroyVideoChannel();
  }
}

void RtpTransportControllerAdapter::OnAudioReceiverDestroyed() {
  if (!have_audio_receiver_) {
    RTC_NOTREACHED();
    return;
  }
  // Empty parameters should result in receiving being stopped.
  RTCError err = ValidateAndApplyAudioReceiverParameters(RtpParameters());
  RTC_DCHECK(err.ok());
  have_audio_receiver_ = false;
  if (!have_audio_sender_) {
    DestroyVoiceChannel();
  }
}

void RtpTransportControllerAdapter::OnVideoReceiverDestroyed() {
  if (!have_video_receiver_) {
    RTC_NOTREACHED();
    return;
  }
  // Empty parameters should result in receiving being stopped.
  RTCError err = ValidateAndApplyVideoReceiverParameters(RtpParameters());
  RTC_DCHECK(err.ok());
  have_video_receiver_ = false;
  if (!have_video_sender_) {
    DestroyVideoChannel();
  }
}

void RtpTransportControllerAdapter::CreateVoiceChannel() {
  voice_channel_ = channel_manager_->CreateVoiceChannel(
      call_.get(), media_config_,
      inner_audio_transport_->GetRtpPacketTransport()->GetInternal(),
      inner_audio_transport_->GetRtcpPacketTransport()
          ? inner_audio_transport_->GetRtcpPacketTransport()->GetInternal()
          : nullptr,
      signaling_thread_, "audio", false, cricket::AudioOptions());
  RTC_DCHECK(voice_channel_);
  voice_channel_->Enable(true);
}

void RtpTransportControllerAdapter::CreateVideoChannel() {
  video_channel_ = channel_manager_->CreateVideoChannel(
      call_.get(), media_config_,
      inner_video_transport_->GetRtpPacketTransport()->GetInternal(),
      inner_video_transport_->GetRtcpPacketTransport()
          ? inner_video_transport_->GetRtcpPacketTransport()->GetInternal()
          : nullptr,
      signaling_thread_, "video", false, cricket::VideoOptions());
  RTC_DCHECK(video_channel_);
  video_channel_->Enable(true);
}

void RtpTransportControllerAdapter::DestroyVoiceChannel() {
  RTC_DCHECK(voice_channel_);
  channel_manager_->DestroyVoiceChannel(voice_channel_);
  voice_channel_ = nullptr;
  inner_audio_transport_ = nullptr;
}

void RtpTransportControllerAdapter::DestroyVideoChannel() {
  RTC_DCHECK(video_channel_);
  channel_manager_->DestroyVideoChannel(video_channel_);
  video_channel_ = nullptr;
  inner_video_transport_ = nullptr;
}

void RtpTransportControllerAdapter::CopyRtcpParametersToDescriptions(
    const RtcpParameters& params,
    cricket::MediaContentDescription* local,
    cricket::MediaContentDescription* remote) {
  local->set_rtcp_mux(params.mux);
  remote->set_rtcp_mux(params.mux);
  local->set_rtcp_reduced_size(params.reduced_size);
  remote->set_rtcp_reduced_size(params.reduced_size);
  for (cricket::StreamParams& stream_params : local->mutable_streams()) {
    stream_params.cname = params.cname;
  }
}

uint32_t RtpTransportControllerAdapter::GenerateUnusedSsrc(
    std::set<uint32_t>* new_ssrcs) const {
  uint32_t ssrc;
  do {
    ssrc = rtc::CreateRandomNonZeroId();
  } while (
      cricket::GetStreamBySsrc(local_audio_description_.streams(), ssrc) ||
      cricket::GetStreamBySsrc(remote_audio_description_.streams(), ssrc) ||
      cricket::GetStreamBySsrc(local_video_description_.streams(), ssrc) ||
      cricket::GetStreamBySsrc(remote_video_description_.streams(), ssrc) ||
      !new_ssrcs->insert(ssrc).second);
  return ssrc;
}

RTCErrorOr<cricket::StreamParamsVec>
RtpTransportControllerAdapter::MakeSendStreamParamsVec(
    std::vector<RtpEncodingParameters> encodings,
    const std::string& cname,
    const cricket::MediaContentDescription& description) const {
  if (encodings.size() > 1u) {
    LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::UNSUPPORTED_PARAMETER,
                         "ORTC API implementation doesn't currently "
                         "support simulcast or layered encodings.");
  } else if (encodings.empty()) {
    return cricket::StreamParamsVec();
  }
  RtpEncodingParameters& encoding = encodings[0];
  std::set<uint32_t> new_ssrcs;
  if (encoding.ssrc) {
    new_ssrcs.insert(*encoding.ssrc);
  }
  if (encoding.rtx && encoding.rtx->ssrc) {
    new_ssrcs.insert(*encoding.rtx->ssrc);
  }
  // May need to fill missing SSRCs with generated ones.
  if (!encoding.ssrc) {
    if (!description.streams().empty()) {
      encoding.ssrc.emplace(description.streams()[0].first_ssrc());
    } else {
      encoding.ssrc.emplace(GenerateUnusedSsrc(&new_ssrcs));
    }
  }
  if (encoding.rtx && !encoding.rtx->ssrc) {
    uint32_t existing_rtx_ssrc;
    if (!description.streams().empty() &&
        description.streams()[0].GetFidSsrc(
            description.streams()[0].first_ssrc(), &existing_rtx_ssrc)) {
      encoding.rtx->ssrc.emplace(existing_rtx_ssrc);
    } else {
      encoding.rtx->ssrc.emplace(GenerateUnusedSsrc(&new_ssrcs));
    }
  }

  auto result = ToCricketStreamParamsVec(encodings);
  if (!result.ok()) {
    return result.MoveError();
  }
  // If conversion was successful, there should be one StreamParams.
  RTC_DCHECK_EQ(1u, result.value().size());
  result.value()[0].cname = cname;
  return result;
}

RTCError RtpTransportControllerAdapter::MaybeSetCryptos(
    RtpTransportInterface* rtp_transport,
    cricket::MediaContentDescription* local_description,
    cricket::MediaContentDescription* remote_description) {
  if (rtp_transport->GetInternal()->is_srtp_transport()) {
    if (!rtp_transport->GetInternal()->send_key() ||
        !rtp_transport->GetInternal()->receive_key()) {
      LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::UNSUPPORTED_PARAMETER,
                           "The SRTP send key or receive key is not set.")
    }
    std::vector<cricket::CryptoParams> cryptos;
    cryptos.push_back(*(rtp_transport->GetInternal()->receive_key()));
    local_description->set_cryptos(cryptos);

    cryptos.clear();
    cryptos.push_back(*(rtp_transport->GetInternal()->send_key()));
    remote_description->set_cryptos(cryptos);
  }
  return RTCError::OK();
}

}  // namespace webrtc
