// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/mac/audio_auhal_mac.h"

#include <CoreServices/CoreServices.h>

#include <algorithm>
#include <cstddef>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "media/audio/mac/audio_manager_mac.h"
#include "media/base/audio_pull_fifo.h"
#include "media/base/audio_timestamp_helper.h"

namespace media {

// Mapping from Chrome's channel layout to CoreAudio layout. This must match the
// layout of the Channels enum in |channel_layout.h|
static const AudioChannelLabel kCoreAudioChannelMapping[] = {
    kAudioChannelLabel_Left,
    kAudioChannelLabel_Right,
    kAudioChannelLabel_Center,
    kAudioChannelLabel_LFEScreen,
    kAudioChannelLabel_LeftSurround,
    kAudioChannelLabel_RightSurround,
    kAudioChannelLabel_LeftCenter,
    kAudioChannelLabel_RightCenter,
    kAudioChannelLabel_CenterSurround,
    kAudioChannelLabel_LeftSurroundDirect,
    kAudioChannelLabel_RightSurroundDirect,
};
static_assert(0 == LEFT && 1 == RIGHT && 2 == CENTER && 3 == LFE &&
                  4 == BACK_LEFT &&
                  5 == BACK_RIGHT &&
                  6 == LEFT_OF_CENTER &&
                  7 == RIGHT_OF_CENTER &&
                  8 == BACK_CENTER &&
                  9 == SIDE_LEFT &&
                  10 == SIDE_RIGHT &&
                  10 == CHANNELS_MAX,
              "Channel positions must match CoreAudio channel order.");

static void WrapBufferList(AudioBufferList* buffer_list,
                           AudioBus* bus,
                           int frames) {
  const int channels = bus->channels();
  const int buffer_list_channels = buffer_list->mNumberBuffers;
  CHECK_EQ(channels, buffer_list_channels);

  // Copy pointers from AudioBufferList.
  for (int i = 0; i < channels; ++i)
    bus->SetChannelData(i, static_cast<float*>(buffer_list->mBuffers[i].mData));

  // Finally set the actual length.
  bus->set_frames(frames);
}

// Sets the stream format on the AUHAL to PCM Float32 non-interleaved for the
// given number of channels on the given scope and element. The created stream
// description will be stored in |desc|.
static bool SetStreamFormat(int channels,
                            int sample_rate,
                            AudioUnit audio_unit,
                            AudioStreamBasicDescription* format) {
  format->mSampleRate = sample_rate;
  format->mFormatID = kAudioFormatLinearPCM;
  format->mFormatFlags =
      kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  format->mBytesPerPacket = sizeof(Float32);
  format->mFramesPerPacket = 1;
  format->mBytesPerFrame = sizeof(Float32);
  format->mChannelsPerFrame = channels;
  format->mBitsPerChannel = 32;
  format->mReserved = 0;

  // Set stream formats. See Apple's tech note for details on the peculiar way
  // that inputs and outputs are handled in the AUHAL concerning scope and bus
  // (element) numbers:
  // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html
  return AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat,
                              kAudioUnitScope_Input, AUElement::OUTPUT, format,
                              sizeof(*format)) == noErr;
}

// Converts |channel_layout| into CoreAudio format and sets up the AUHAL with
// our layout information so it knows how to remap the channels.
static void SetAudioChannelLayout(int channels,
                                  ChannelLayout channel_layout,
                                  AudioUnit audio_unit) {
  DCHECK(audio_unit);
  DCHECK_GT(channels, 0);
  DCHECK_GT(channel_layout, CHANNEL_LAYOUT_UNSUPPORTED);

  // AudioChannelLayout is structure ending in a variable length array, so we
  // can't directly allocate one. Instead compute the size and and allocate one
  // inside of a byte array.
  //
  // Code modeled after example from Apple documentation here:
  // https://developer.apple.com/library/content/qa/qa1627/_index.html
  const size_t layout_size =
      offsetof(AudioChannelLayout, mChannelDescriptions[channels]);
  std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[layout_size]);
  memset(layout_storage.get(), 0, layout_size);
  AudioChannelLayout* coreaudio_layout =
      reinterpret_cast<AudioChannelLayout*>(layout_storage.get());

  coreaudio_layout->mNumberChannelDescriptions = channels;
  coreaudio_layout->mChannelLayoutTag =
      kAudioChannelLayoutTag_UseChannelDescriptions;
  AudioChannelDescription* descriptions =
      coreaudio_layout->mChannelDescriptions;

  if (channel_layout == CHANNEL_LAYOUT_DISCRETE) {
    // For the discrete case just assume common input mappings; once we run out
    // of known channels mark them as unknown.
    for (int ch = 0; ch < channels; ++ch) {
      descriptions[ch].mChannelLabel = ch > CHANNELS_MAX
                                           ? kAudioChannelLabel_Unknown
                                           : kCoreAudioChannelMapping[ch];
      descriptions[ch].mChannelFlags = kAudioChannelFlags_AllOff;
    }
  } else if (channel_layout == CHANNEL_LAYOUT_MONO) {
    // CoreAudio has a special label for mono.
    DCHECK_EQ(channels, 1);
    descriptions[0].mChannelLabel = kAudioChannelLabel_Mono;
    descriptions[0].mChannelFlags = kAudioChannelFlags_AllOff;
  } else {
    for (int ch = 0; ch <= CHANNELS_MAX; ++ch) {
      const int order = ChannelOrder(channel_layout, static_cast<Channels>(ch));
      if (order == -1)
        continue;
      descriptions[order].mChannelLabel = kCoreAudioChannelMapping[ch];
      descriptions[order].mChannelFlags = kAudioChannelFlags_AllOff;
    }
  }

  OSStatus result = AudioUnitSetProperty(
      audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input,
      AUElement::OUTPUT, coreaudio_layout, layout_size);
  if (result != noErr) {
    OSSTATUS_DLOG(ERROR, result)
        << "Failed to set audio channel layout. Using default layout.";
  }
}

AUHALStream::AUHALStream(AudioManagerMac* manager,
                         const AudioParameters& params,
                         AudioDeviceID device,
                         const AudioManager::LogCallback& log_callback)
    : manager_(manager),
      params_(params),
      number_of_frames_(params_.frames_per_buffer()),
      number_of_frames_requested_(0),
      source_(NULL),
      device_(device),
      volume_(1),
      stopped_(true),
      current_lost_frames_(0),
      last_sample_time_(0.0),
      last_number_of_frames_(0),
      total_lost_frames_(0),
      largest_glitch_frames_(0),
      glitches_detected_(0),
      log_callback_(log_callback) {
  // We must have a manager.
  DCHECK(manager_);
  DCHECK(params_.IsValid());
  DCHECK_NE(device, kAudioObjectUnknown);
}

AUHALStream::~AUHALStream() {
  DCHECK(thread_checker_.CalledOnValidThread());
  CHECK(!audio_unit_);

  base::AutoLock al(lock_);
  ReportAndResetStats();
}

bool AUHALStream::Open() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!output_bus_);
  DCHECK(!audio_unit_);

  // The output bus will wrap the AudioBufferList given to us in
  // the Render() callback.
  output_bus_ = AudioBus::CreateWrapper(params_.channels());

  bool configured = ConfigureAUHAL();
  if (configured) {
    DCHECK(audio_unit_);
    DCHECK(audio_unit_->is_valid());
    hardware_latency_ = AudioManagerMac::GetHardwareLatency(
        audio_unit_->audio_unit(), device_, kAudioDevicePropertyScopeOutput,
        params_.sample_rate());
  }

  return configured;
}

void AUHALStream::Close() {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (audio_unit_) {
    Stop();

    // Clear the render callback to try and prevent any callbacks from coming
    // in after we've called stop. https://crbug.com/737527.
    AURenderCallbackStruct callback = {0};
    auto result = AudioUnitSetProperty(
        audio_unit_->audio_unit(), kAudioUnitProperty_SetRenderCallback,
        kAudioUnitScope_Input, AUElement::OUTPUT, &callback, sizeof(callback));
    OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
        << "Failed to clear input callback.";
  }

  audio_unit_.reset();
  // Inform the audio manager that we have been closed. This will cause our
  // destruction. Also include the device ID as a signal to the audio manager
  // that it should try to increase the native I/O buffer size after the stream
  // has been closed.
  manager_->ReleaseOutputStreamUsingRealDevice(this, device_);
}

void AUHALStream::Start(AudioSourceCallback* callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(callback);
  if (!audio_unit_) {
    DLOG(ERROR) << "Open() has not been called successfully";
    return;
  }

  if (!stopped_) {
    base::AutoLock al(lock_);
    CHECK_EQ(source_, callback);
    return;
  }

  // Check if we should defer Start() for http://crbug.com/160920.
  if (manager_->ShouldDeferStreamStart()) {
    // Use a cancellable closure so that if Stop() is called before Start()
    // actually runs, we can cancel the pending start.
    deferred_start_cb_.Reset(
        base::BindOnce(&AUHALStream::Start, base::Unretained(this), callback));
    manager_->GetTaskRunner()->PostDelayedTask(
        FROM_HERE, deferred_start_cb_.callback(),
        base::Seconds(AudioManagerMac::kStartDelayInSecsForPowerEvents));
    return;
  }

  stopped_ = false;

  {
    base::AutoLock al(lock_);
    audio_fifo_.reset();
    source_ = callback;
  }

  OSStatus result = AudioOutputUnitStart(audio_unit_->audio_unit());
  if (result == noErr)
    return;

  Stop();
  OSSTATUS_DLOG(ERROR, result) << "AudioOutputUnitStart() failed.";
  callback->OnError(AudioSourceCallback::ErrorType::kUnknown);
}

// This stream is always used with sub second buffer sizes, where it's
// sufficient to simply always flush upon Start().
void AUHALStream::Flush() {}

void AUHALStream::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  deferred_start_cb_.Cancel();
  if (stopped_)
    return;

  OSStatus result = AudioOutputUnitStop(audio_unit_->audio_unit());
  OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
      << "AudioOutputUnitStop() failed.";

  {
    base::AutoLock al(lock_);
    if (result != noErr)
      source_->OnError(AudioSourceCallback::ErrorType::kUnknown);

    ReportAndResetStats();
    source_ = nullptr;
  }

  stopped_ = true;
}

void AUHALStream::SetVolume(double volume) {
  volume_ = static_cast<float>(volume);
}

void AUHALStream::GetVolume(double* volume) {
  *volume = volume_;
}

// Pulls on our provider to get rendered audio stream.
// Note to future hackers of this function: Do not add locks which can
// be contended in the middle of stream processing here (starting and stopping
// the stream are ok) because this is running on a real-time thread.
OSStatus AUHALStream::Render(AudioUnitRenderActionFlags* flags,
                             const AudioTimeStamp* output_time_stamp,
                             UInt32 bus_number,
                             UInt32 number_of_frames,
                             AudioBufferList* data) {
  TRACE_EVENT2("audio", "AUHALStream::Render", "input buffer size",
               number_of_frames_, "output buffer size", number_of_frames);

  base::AutoLock al(lock_);

  // There's no documentation on what we should return here, but if we're here
  // something is wrong so just return an AudioUnit error that looks reasonable.
  if (!source_)
    return kAudioUnitErr_Uninitialized;

  UpdatePlayoutTimestamp(output_time_stamp);

  // If the stream parameters change for any reason, we need to insert a FIFO
  // since the OnMoreData() pipeline can't handle frame size changes.
  if (number_of_frames != number_of_frames_) {
    // Create a FIFO on the fly to handle any discrepancies in callback rates.
    if (!audio_fifo_) {
      // TODO(grunell): We'll only care about the first buffer size change,
      // any further changes will be ignored. It would be nice to have all
      // changes reflected in UMA stats.
      number_of_frames_requested_ = number_of_frames;
      DVLOG(1) << "Audio frame size changed from " << number_of_frames_
               << " to " << number_of_frames << " adding FIFO to compensate.";
      audio_fifo_ = std::make_unique<AudioPullFifo>(
          params_.channels(), number_of_frames_,
          base::BindRepeating(&AUHALStream::ProvideInput,
                              base::Unretained(this)));
    }
  }

  // Make |output_bus_| wrap the output AudioBufferList.
  WrapBufferList(data, output_bus_.get(), number_of_frames);

  current_playout_time_ = GetPlayoutTime(output_time_stamp);

  if (audio_fifo_)
    audio_fifo_->Consume(output_bus_.get(), output_bus_->frames());
  else
    ProvideInput(0, output_bus_.get());

  last_number_of_frames_ = number_of_frames;

  return noErr;
}

void AUHALStream::ProvideInput(int frame_delay, AudioBus* dest) {
  lock_.AssertAcquired();
  DCHECK(source_);

  const base::TimeTicks playout_time =
      current_playout_time_ +
      AudioTimestampHelper::FramesToTime(frame_delay, params_.sample_rate());
  const base::TimeTicks now = base::TimeTicks::Now();
  const base::TimeDelta delay = playout_time - now;

  // Supply the input data and render the output data.
  source_->OnMoreData(delay, now, current_lost_frames_, dest);
  dest->Scale(volume_);
  current_lost_frames_ = 0;
}

// AUHAL callback.
OSStatus AUHALStream::InputProc(void* user_data,
                                AudioUnitRenderActionFlags* flags,
                                const AudioTimeStamp* output_time_stamp,
                                UInt32 bus_number,
                                UInt32 number_of_frames,
                                AudioBufferList* io_data) {
  // Dispatch to our class method.
  AUHALStream* audio_output = static_cast<AUHALStream*>(user_data);
  if (!audio_output)
    return -1;

  return audio_output->Render(flags, output_time_stamp, bus_number,
                              number_of_frames, io_data);
}

base::TimeTicks AUHALStream::GetPlayoutTime(
    const AudioTimeStamp* output_time_stamp) {
  // A platform bug has been observed where the platform sometimes reports that
  // the next frames will be output at an invalid time or a time in the past.
  // Because the target playout time cannot be invalid or in the past, return
  // "now" in these cases.
  if ((output_time_stamp->mFlags & kAudioTimeStampHostTimeValid) == 0)
    return base::TimeTicks::Now();

  return std::max(base::TimeTicks::FromMachAbsoluteTime(
                      output_time_stamp->mHostTime),
                  base::TimeTicks::Now()) +
         hardware_latency_;
}

void AUHALStream::UpdatePlayoutTimestamp(const AudioTimeStamp* timestamp) {
  lock_.AssertAcquired();

  if ((timestamp->mFlags & kAudioTimeStampSampleTimeValid) == 0)
    return;

  if (last_sample_time_) {
    DCHECK_NE(0U, last_number_of_frames_);
    UInt32 diff =
        static_cast<UInt32>(timestamp->mSampleTime - last_sample_time_);
    if (diff != last_number_of_frames_) {
      DCHECK_GT(diff, last_number_of_frames_);
      // We're being asked to render samples post what we expected. Update the
      // glitch count etc and keep a record of the largest glitch.
      auto lost_frames = diff - last_number_of_frames_;
      total_lost_frames_ += lost_frames;
      current_lost_frames_ += lost_frames;
      if (lost_frames > largest_glitch_frames_)
        largest_glitch_frames_ = lost_frames;
      ++glitches_detected_;
    }
  }

  // Store the last sample time for use next time we get called back.
  last_sample_time_ = timestamp->mSampleTime;
}

void AUHALStream::ReportAndResetStats() {
  lock_.AssertAcquired();

  if (!last_sample_time_)
    return;  // No stats gathered to report.

  // A value of 0 indicates that we got the buffer size we asked for.
  UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.FramesRequested",
                          number_of_frames_requested_);
  // Even if there aren't any glitches, we want to record it to get a feel for
  // how often we get no glitches vs the alternative.
  UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Render.Glitches", glitches_detected_,
                              1, 999999, 100);

  auto lost_frames_ms = (total_lost_frames_ * 1000) / params_.sample_rate();

  std::string log_message = base::StringPrintf(
      "AU out: Total glitches=%d. Total frames lost=%d (%d ms).",
      glitches_detected_, total_lost_frames_, lost_frames_ms);

  if (!log_callback_.is_null())
    log_callback_.Run(log_message);

  if (glitches_detected_ != 0) {
    UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.LostFramesInMs",
                            lost_frames_ms);
    auto largest_glitch_ms =
        (largest_glitch_frames_ * 1000) / params_.sample_rate();
    UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.LargestGlitchMs",
                            largest_glitch_ms);
    DLOG(WARNING) << log_message;
  }

  number_of_frames_requested_ = 0;
  glitches_detected_ = 0;
  last_sample_time_ = 0;
  last_number_of_frames_ = 0;
  total_lost_frames_ = 0;
  largest_glitch_frames_ = 0;
}

bool AUHALStream::ConfigureAUHAL() {
  DCHECK(thread_checker_.CalledOnValidThread());

  std::unique_ptr<ScopedAudioUnit> local_audio_unit(
      new ScopedAudioUnit(device_, AUElement::OUTPUT));
  if (!local_audio_unit->is_valid())
    return false;

  if (!SetStreamFormat(params_.channels(), params_.sample_rate(),
                       local_audio_unit->audio_unit(), &output_format_)) {
    return false;
  }

  bool size_was_changed = false;
  size_t io_buffer_frame_size = 0;
  if (!manager_->MaybeChangeBufferSize(device_, local_audio_unit->audio_unit(),
                                       0, number_of_frames_, &size_was_changed,
                                       &io_buffer_frame_size)) {
    return false;
  }

  // Setup callback.
  AURenderCallbackStruct callback;
  callback.inputProc = InputProc;
  callback.inputProcRefCon = this;
  OSStatus result = AudioUnitSetProperty(
      local_audio_unit->audio_unit(), kAudioUnitProperty_SetRenderCallback,
      kAudioUnitScope_Input, AUElement::OUTPUT, &callback, sizeof(callback));
  if (result != noErr)
    return false;

  SetAudioChannelLayout(params_.channels(), params_.channel_layout(),
                        local_audio_unit->audio_unit());

  result = AudioUnitInitialize(local_audio_unit->audio_unit());
  if (result != noErr) {
    OSSTATUS_DLOG(ERROR, result) << "AudioUnitInitialize() failed.";
    return false;
  }

  audio_unit_ = std::move(local_audio_unit);
  return true;
}

}  // namespace media
