/*
 *  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 "api/sequence_checker.h"
#include "rtc_base/logging.h"

namespace webrtc {

AudioEgress::AudioEgress(const Environment& env, RtpRtcpInterface* rtp_rtcp)
    : rtp_rtcp_(rtp_rtcp),
      rtp_sender_audio_(&env.clock(), rtp_rtcp_->RtpSender()),
      audio_coding_(AudioCodingModule::Create()),
      encoder_queue_(env.task_queue_factory().CreateTaskQueue(
          "AudioEncoder",
          TaskQueueFactory::Priority::NORMAL)),
      encoder_queue_checker_(encoder_queue_.get()) {
  audio_coding_->RegisterTransportCallback(this);
}

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

  // Delete first to ensure that there are no running tasks when the other
  // members are destroyed.
  encoder_queue_ = nullptr;
}

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

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

  SetEncoderFormat(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));
}

bool AudioEgress::StartSend() {
  if (!GetEncoderFormat()) {
    RTC_DLOG(LS_WARNING) << "Send codec has not been set yet";
    return false;
  }
  rtp_rtcp_->SetSendingMediaStatus(true);
  return true;
}

void AudioEgress::StopSend() {
  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_checker_);
        if (!rtp_rtcp_->SendingMedia()) {
          return;
        }

        double duration_seconds =
            static_cast<double>(audio_frame->samples_per_channel_) /
            audio_frame->sample_rate_hz_;

        input_audio_level_.ComputeLevel(*audio_frame, duration_seconds);

        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_checker_);

  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({.type = frame_type,
                                    .payload = payload,
                                    .payload_id = payload_type,
                                    .rtp_timestamp = rtp_timestamp})) {
    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_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_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) {
  encoder_queue_->PostTask([this, mute] {
    RTC_DCHECK_RUN_ON(&encoder_queue_checker_);
    encoder_context_.mute_ = mute;
  });
}

}  // namespace webrtc
