/*
 *  Copyright (c) 2018 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 "api/audio/audio_frame.h"

#include <string.h>

#include "rtc_base/checks.h"
#include "rtc_base/time_utils.h"

namespace webrtc {

AudioFrame::AudioFrame() {
  // Visual Studio doesn't like this in the class definition.
  static_assert(sizeof(data_) == kMaxDataSizeBytes, "kMaxDataSizeBytes");
}

AudioFrame::AudioFrame(int sample_rate_hz,
                       size_t num_channels,
                       ChannelLayout layout /*= CHANNEL_LAYOUT_UNSUPPORTED*/)
    : samples_per_channel_(SampleRateToDefaultChannelSize(sample_rate_hz)),
      sample_rate_hz_(sample_rate_hz),
      num_channels_(num_channels),
      channel_layout_(layout == CHANNEL_LAYOUT_UNSUPPORTED
                          ? GuessChannelLayout(num_channels)
                          : layout) {
  RTC_DCHECK_LE(num_channels_, kMaxConcurrentChannels);
  RTC_DCHECK_GT(sample_rate_hz_, 0);
  RTC_DCHECK_GT(samples_per_channel_, 0u);
}

void AudioFrame::Reset() {
  ResetWithoutMuting();
  muted_ = true;
}

void AudioFrame::ResetWithoutMuting() {
  // TODO(wu): Zero is a valid value for `timestamp_`. We should initialize
  // to an invalid value, or add a new member to indicate invalidity.
  timestamp_ = 0;
  elapsed_time_ms_ = -1;
  ntp_time_ms_ = -1;
  samples_per_channel_ = 0;
  sample_rate_hz_ = 0;
  num_channels_ = 0;
  channel_layout_ = CHANNEL_LAYOUT_NONE;
  speech_type_ = kUndefined;
  vad_activity_ = kVadUnknown;
  profile_timestamp_ms_ = 0;
  packet_infos_ = RtpPacketInfos();
  absolute_capture_timestamp_ms_ = absl::nullopt;
}

void AudioFrame::UpdateFrame(uint32_t timestamp,
                             const int16_t* data,
                             size_t samples_per_channel,
                             int sample_rate_hz,
                             SpeechType speech_type,
                             VADActivity vad_activity,
                             size_t num_channels) {
  RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
  timestamp_ = timestamp;
  samples_per_channel_ = samples_per_channel;
  sample_rate_hz_ = sample_rate_hz;
  speech_type_ = speech_type;
  vad_activity_ = vad_activity;
  num_channels_ = num_channels;
  channel_layout_ = GuessChannelLayout(num_channels);
  if (channel_layout_ != CHANNEL_LAYOUT_UNSUPPORTED) {
    RTC_DCHECK_EQ(num_channels, ChannelLayoutToChannelCount(channel_layout_));
  }

  const size_t length = samples_per_channel * num_channels;
  RTC_CHECK_LE(length, kMaxDataSizeSamples);
  if (data != nullptr) {
    memcpy(data_, data, sizeof(int16_t) * length);
    muted_ = false;
  } else {
    muted_ = true;
  }
}

void AudioFrame::CopyFrom(const AudioFrame& src) {
  if (this == &src)
    return;

  timestamp_ = src.timestamp_;
  elapsed_time_ms_ = src.elapsed_time_ms_;
  ntp_time_ms_ = src.ntp_time_ms_;
  packet_infos_ = src.packet_infos_;
  muted_ = src.muted();
  samples_per_channel_ = src.samples_per_channel_;
  sample_rate_hz_ = src.sample_rate_hz_;
  speech_type_ = src.speech_type_;
  vad_activity_ = src.vad_activity_;
  num_channels_ = src.num_channels_;
  channel_layout_ = src.channel_layout_;
  absolute_capture_timestamp_ms_ = src.absolute_capture_timestamp_ms();

  const size_t length = samples_per_channel_ * num_channels_;
  RTC_CHECK_LE(length, kMaxDataSizeSamples);
  if (!src.muted()) {
    memcpy(data_, src.data(), sizeof(int16_t) * length);
    muted_ = false;
  }
}

void AudioFrame::UpdateProfileTimeStamp() {
  profile_timestamp_ms_ = rtc::TimeMillis();
}

int64_t AudioFrame::ElapsedProfileTimeMs() const {
  if (profile_timestamp_ms_ == 0) {
    // Profiling has not been activated.
    return -1;
  }
  return rtc::TimeSince(profile_timestamp_ms_);
}

const int16_t* AudioFrame::data() const {
  return muted_ ? zeroed_data().begin() : data_;
}

rtc::ArrayView<const int16_t> AudioFrame::data_view() const {
  const auto samples = samples_per_channel_ * num_channels_;
  // If you get a nullptr from `data_view()`, it's likely because the
  // samples_per_channel_ and/or num_channels_ haven't been properly set.
  // Since `data_view()` returns an rtc::ArrayView<>, we inherit the behavior
  // in ArrayView when the view size is 0 that ArrayView<>::data() will always
  // return nullptr. So, even when an AudioFrame is muted and we want to
  // return `zeroed_data()`, if samples_per_channel_ or  num_channels_ is 0,
  // the view will point to nullptr.
  return muted_ ? zeroed_data().subview(0, samples)
                : rtc::ArrayView<const int16_t>(&data_[0], samples);
}

int16_t* AudioFrame::mutable_data() {
  // TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
  // Consider instead if we should rather zero the buffer when `muted_` is set
  // to `true`.
  if (muted_) {
    memset(data_, 0, kMaxDataSizeBytes);
    muted_ = false;
  }
  return data_;
}

rtc::ArrayView<int16_t> AudioFrame::mutable_data(size_t samples_per_channel,
                                                 size_t num_channels) {
  const size_t total_samples = samples_per_channel * num_channels;
  RTC_CHECK_LE(total_samples, kMaxDataSizeSamples);
  RTC_CHECK_LE(num_channels, kMaxConcurrentChannels);
  // Sanity check for valid argument values during development.
  // If `samples_per_channel` is <= kMaxConcurrentChannels but larger than 0,
  // then chances are the order of arguments is incorrect.
  RTC_DCHECK((samples_per_channel == 0 && num_channels == 0) ||
             samples_per_channel > kMaxConcurrentChannels);

  // TODO: bugs.webrtc.org/5647 - Can we skip zeroing the buffer?
  // Consider instead if we should rather zero the whole buffer when `muted_` is
  // set to `true`.
  if (muted_) {
    memset(data_, 0, total_samples * sizeof(int16_t));
    muted_ = false;
  }
  samples_per_channel_ = samples_per_channel;
  num_channels_ = num_channels;
  return rtc::ArrayView<int16_t>(&data_[0], total_samples);
}

void AudioFrame::Mute() {
  muted_ = true;
}

bool AudioFrame::muted() const {
  return muted_;
}

void AudioFrame::SetLayoutAndNumChannels(ChannelLayout layout,
                                         size_t num_channels) {
  channel_layout_ = layout;
  num_channels_ = num_channels;
#if RTC_DCHECK_IS_ON
  // Do a sanity check that the layout and num_channels match.
  // If this lookup yield 0u, then the layout is likely CHANNEL_LAYOUT_DISCRETE.
  auto expected_num_channels = ChannelLayoutToChannelCount(layout);
  if (expected_num_channels) {  // If expected_num_channels is 0
    RTC_DCHECK_EQ(expected_num_channels, num_channels_);
  }
#endif
  RTC_CHECK_LE(samples_per_channel_ * num_channels_, kMaxDataSizeSamples);
}

void AudioFrame::SetSampleRateAndChannelSize(int sample_rate) {
  sample_rate_hz_ = sample_rate;
  // We could call `AudioProcessing::GetFrameSize()` here, but that requires
  // adding a dependency on the ":audio_processing" build target, which can
  // complicate the dependency tree. Some refactoring is probably in order to
  // get some consistency around this since there are many places across the
  // code that assume this default buffer size.
  samples_per_channel_ = SampleRateToDefaultChannelSize(sample_rate_hz_);
}

// static
rtc::ArrayView<const int16_t> AudioFrame::zeroed_data() {
  static int16_t* null_data = new int16_t[kMaxDataSizeSamples]();
  return rtc::ArrayView<const int16_t>(null_data, kMaxDataSizeSamples);
}

}  // namespace webrtc
