//
//  Copyright (c) 2020 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 "audio/voip/audio_egress.h"

#include <utility>
#include <vector>

#include "rtc_base/logging.h"

namespace webrtc {

AudioEgress::AudioEgress(RtpRtcp* rtp_rtcp,
                         Clock* clock,
                         TaskQueueFactory* task_queue_factory)
    : rtp_rtcp_(rtp_rtcp),
      rtp_sender_audio_(clock, rtp_rtcp_->RtpSender()),
      audio_coding_(AudioCodingModule::Create(AudioCodingModule::Config())),
      encoder_queue_(task_queue_factory->CreateTaskQueue(
          "AudioEncoder",
          TaskQueueFactory::Priority::NORMAL)) {
  audio_coding_->RegisterTransportCallback(this);
}

AudioEgress::~AudioEgress() {
  audio_coding_->RegisterTransportCallback(nullptr);
}

bool AudioEgress::IsSending() const {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  return rtp_rtcp_->SendingMedia();
}

void AudioEgress::SetEncoder(int payload_type,
                             const SdpAudioFormat& encoder_format,
                             std::unique_ptr<AudioEncoder> encoder) {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  RTC_DCHECK_GE(payload_type, 0);
  RTC_DCHECK_LE(payload_type, 127);

  encoder_format_ = encoder_format;

  // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
  // as well as some other things, so we collect this info and send it along.
  rtp_rtcp_->RegisterSendPayloadFrequency(payload_type,
                                          encoder->RtpTimestampRateHz());
  rtp_sender_audio_.RegisterAudioPayload("audio", payload_type,
                                         encoder->RtpTimestampRateHz(),
                                         encoder->NumChannels(), 0);

  audio_coding_->SetEncoder(std::move(encoder));
}

absl::optional<SdpAudioFormat> AudioEgress::GetEncoderFormat() const {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  return encoder_format_;
}

void AudioEgress::StartSend() {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);

  rtp_rtcp_->SetSendingMediaStatus(true);
}

void AudioEgress::StopSend() {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);

  rtp_rtcp_->SetSendingMediaStatus(false);
}

void AudioEgress::SendAudioData(std::unique_ptr<AudioFrame> audio_frame) {
  RTC_DCHECK_GT(audio_frame->samples_per_channel_, 0);
  RTC_DCHECK_LE(audio_frame->num_channels_, 8);

  encoder_queue_.PostTask(
      [this, audio_frame = std::move(audio_frame)]() mutable {
        RTC_DCHECK_RUN_ON(&encoder_queue_);
        if (!rtp_rtcp_->SendingMedia()) {
          return;
        }

        AudioFrameOperations::Mute(audio_frame.get(),
                                   encoder_context_.previously_muted_,
                                   encoder_context_.mute_);
        encoder_context_.previously_muted_ = encoder_context_.mute_;

        audio_frame->timestamp_ = encoder_context_.frame_rtp_timestamp_;

        // This call will trigger AudioPacketizationCallback::SendData if
        // encoding is done and payload is ready for packetization and
        // transmission. Otherwise, it will return without invoking the
        // callback.
        if (audio_coding_->Add10MsData(*audio_frame) < 0) {
          RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
          return;
        }

        encoder_context_.frame_rtp_timestamp_ +=
            rtc::dchecked_cast<uint32_t>(audio_frame->samples_per_channel_);
      });
}

int32_t AudioEgress::SendData(AudioFrameType frame_type,
                              uint8_t payload_type,
                              uint32_t timestamp,
                              const uint8_t* payload_data,
                              size_t payload_size) {
  RTC_DCHECK_RUN_ON(&encoder_queue_);

  rtc::ArrayView<const uint8_t> payload(payload_data, payload_size);

  // Currently we don't get a capture time from downstream modules (ADM,
  // AudioTransportImpl).
  // TODO(natim@webrtc.org): Integrate once it's ready.
  constexpr uint32_t kUndefinedCaptureTime = -1;

  // Push data from ACM to RTP/RTCP-module to deliver audio frame for
  // packetization.
  if (!rtp_rtcp_->OnSendingRtpFrame(timestamp, kUndefinedCaptureTime,
                                    payload_type,
                                    /*force_sender_report=*/false)) {
    return -1;
  }

  const uint32_t rtp_timestamp = timestamp + rtp_rtcp_->StartTimestamp();

  // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
  if (!rtp_sender_audio_.SendAudio(frame_type, payload_type, rtp_timestamp,
                                   payload.data(), payload.size())) {
    RTC_DLOG(LS_ERROR)
        << "AudioEgress::SendData() failed to send data to RTP/RTCP module";
    return -1;
  }

  return 0;
}

void AudioEgress::RegisterTelephoneEventType(int rtp_payload_type,
                                             int sample_rate_hz) {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  RTC_DCHECK_GE(rtp_payload_type, 0);
  RTC_DCHECK_LE(rtp_payload_type, 127);

  rtp_rtcp_->RegisterSendPayloadFrequency(rtp_payload_type, sample_rate_hz);
  rtp_sender_audio_.RegisterAudioPayload("telephone-event", rtp_payload_type,
                                         sample_rate_hz, 0, 0);
}

bool AudioEgress::SendTelephoneEvent(int dtmf_event, int duration_ms) {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
  RTC_DCHECK_GE(dtmf_event, 0);
  RTC_DCHECK_LE(dtmf_event, 255);
  RTC_DCHECK_GE(duration_ms, 0);
  RTC_DCHECK_LE(duration_ms, 65535);

  if (!IsSending()) {
    return false;
  }

  constexpr int kTelephoneEventAttenuationdB = 10;

  if (rtp_sender_audio_.SendTelephoneEvent(dtmf_event, duration_ms,
                                           kTelephoneEventAttenuationdB) != 0) {
    RTC_DLOG(LS_ERROR) << "SendTelephoneEvent() failed to send event";
    return false;
  }
  return true;
}

void AudioEgress::SetMute(bool mute) {
  RTC_DCHECK_RUN_ON(&worker_thread_checker_);

  encoder_queue_.PostTask([this, mute] {
    RTC_DCHECK_RUN_ON(&encoder_queue_);
    encoder_context_.mute_ = mute;
  });
}

}  // namespace webrtc
