/*
 *  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/channel_send_frame_transformer_delegate.h"

#include <utility>

namespace webrtc {
namespace {

class TransformableAudioFrame : public TransformableFrameInterface {
 public:
  TransformableAudioFrame(AudioFrameType frame_type,
                          uint8_t payload_type,
                          uint32_t rtp_timestamp,
                          const uint8_t* payload_data,
                          size_t payload_size,
                          int64_t absolute_capture_timestamp_ms,
                          uint32_t ssrc)
      : frame_type_(frame_type),
        payload_type_(payload_type),
        rtp_timestamp_(rtp_timestamp),
        payload_(payload_data, payload_size),
        absolute_capture_timestamp_ms_(absolute_capture_timestamp_ms),
        ssrc_(ssrc) {}
  ~TransformableAudioFrame() override = default;
  rtc::ArrayView<const uint8_t> GetData() const override { return payload_; }
  void SetData(rtc::ArrayView<const uint8_t> data) override {
    payload_.SetData(data.data(), data.size());
  }
  uint32_t GetTimestamp() const override { return rtp_timestamp_; }
  uint32_t GetSsrc() const override { return ssrc_; }

  AudioFrameType GetFrameType() const { return frame_type_; }
  uint8_t GetPayloadType() const { return payload_type_; }
  int64_t GetAbsoluteCaptureTimestampMs() const {
    return absolute_capture_timestamp_ms_;
  }

 private:
  AudioFrameType frame_type_;
  uint8_t payload_type_;
  uint32_t rtp_timestamp_;
  rtc::Buffer payload_;
  int64_t absolute_capture_timestamp_ms_;
  uint32_t ssrc_;
};
}  // namespace

ChannelSendFrameTransformerDelegate::ChannelSendFrameTransformerDelegate(
    SendFrameCallback send_frame_callback,
    rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
    rtc::TaskQueue* encoder_queue)
    : send_frame_callback_(send_frame_callback),
      frame_transformer_(std::move(frame_transformer)),
      encoder_queue_(encoder_queue) {}

void ChannelSendFrameTransformerDelegate::Init() {
  frame_transformer_->RegisterTransformedFrameCallback(
      rtc::scoped_refptr<TransformedFrameCallback>(this));
}

void ChannelSendFrameTransformerDelegate::Reset() {
  frame_transformer_->UnregisterTransformedFrameCallback();
  frame_transformer_ = nullptr;

  rtc::CritScope lock(&send_lock_);
  send_frame_callback_ = SendFrameCallback();
}

void ChannelSendFrameTransformerDelegate::Transform(
    AudioFrameType frame_type,
    uint8_t payload_type,
    uint32_t rtp_timestamp,
    const uint8_t* payload_data,
    size_t payload_size,
    int64_t absolute_capture_timestamp_ms,
    uint32_t ssrc) {
  frame_transformer_->Transform(std::make_unique<TransformableAudioFrame>(
      frame_type, payload_type, rtp_timestamp, payload_data, payload_size,
      absolute_capture_timestamp_ms, ssrc));
}

void ChannelSendFrameTransformerDelegate::OnTransformedFrame(
    std::unique_ptr<TransformableFrameInterface> frame) {
  rtc::CritScope lock(&send_lock_);
  if (!send_frame_callback_)
    return;
  rtc::scoped_refptr<ChannelSendFrameTransformerDelegate> delegate = this;
  encoder_queue_->PostTask(
      [delegate = std::move(delegate), frame = std::move(frame)]() mutable {
        delegate->SendFrame(std::move(frame));
      });
}

void ChannelSendFrameTransformerDelegate::SendFrame(
    std::unique_ptr<TransformableFrameInterface> frame) const {
  rtc::CritScope lock(&send_lock_);
  RTC_DCHECK_RUN_ON(encoder_queue_);
  if (!send_frame_callback_)
    return;
  auto* transformed_frame = static_cast<TransformableAudioFrame*>(frame.get());
  send_frame_callback_(
      transformed_frame->GetFrameType(), transformed_frame->GetPayloadType(),
      transformed_frame->GetTimestamp(), transformed_frame->GetData(),
      transformed_frame->GetAbsoluteCaptureTimestampMs());
}

}  // namespace webrtc
