// Copyright 2017 The Fuchsia 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 "src/media/audio/audio_core/utils.h"

#include <audio-proto-utils/format-utils.h>
#include <fuchsia/scheduler/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/zx/channel.h>

#include "src/lib/fxl/logging.h"
#include "src/media/audio/audio_core/driver_utils.h"

namespace media::audio {

zx_status_t SelectBestFormat(
    const std::vector<audio_stream_format_range_t>& fmts,
    uint32_t* frames_per_second_inout, uint32_t* channels_inout,
    fuchsia::media::AudioSampleFormat* sample_format_inout) {
  if ((frames_per_second_inout == nullptr) || (channels_inout == nullptr) ||
      (sample_format_inout == nullptr)) {
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t pref_frame_rate = *frames_per_second_inout;
  uint32_t pref_channels = *channels_inout;
  audio_sample_format_t pref_sample_format;

  if (!driver_utils::AudioSampleFormatToDriverSampleFormat(
          *sample_format_inout, &pref_sample_format)) {
    FXL_LOG(WARNING) << "Failed to convert FIDL sample format ("
                     << static_cast<uint32_t>(*sample_format_inout)
                     << ") to driver sample format.";
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t best_frame_rate;
  uint32_t best_channels;
  audio_sample_format_t best_sample_format;
  uint32_t best_score = 0;
  uint32_t best_frame_rate_delta = std::numeric_limits<uint32_t>::max();

  constexpr uint32_t U8_FMT =
      AUDIO_SAMPLE_FORMAT_8BIT | AUDIO_SAMPLE_FORMAT_FLAG_UNSIGNED;
  constexpr uint32_t S16_FMT = AUDIO_SAMPLE_FORMAT_16BIT;
  constexpr uint32_t S24_FMT = AUDIO_SAMPLE_FORMAT_24BIT_IN32;
  constexpr uint32_t F32_FMT = AUDIO_SAMPLE_FORMAT_32BIT_FLOAT;

  // Users should only ask for unsigned-8, signed-16, signed-24in32 or float-32.
  // If they ask for anything else, change their preference to signed-16.
  //
  // TODO(johngro) : clean this up as part of fixing MTWN-54
  if ((pref_sample_format & AUDIO_SAMPLE_FORMAT_FLAG_INVERT_ENDIAN) ||
      (((pref_sample_format & U8_FMT) != U8_FMT) &&
       ((pref_sample_format & S16_FMT) != S16_FMT) &&
       ((pref_sample_format & S24_FMT) != S24_FMT) &&
       ((pref_sample_format & F32_FMT) != F32_FMT))) {
    pref_sample_format = AUDIO_SAMPLE_FORMAT_16BIT;
  }

  for (const auto& range : fmts) {
    // Start by scoring our sample format.  Right now, the audio core supports
    // 8-bit unsigned, 16-bit signed, 24-bit-in-32 signed and 32-bit float. If
    // this sample format range does not support any of these, just skip it for
    // now. Otherwise, 5 points if you match the requested format, 4 for
    // signed-24, 3 for signed-16, 2 for float-32, or 1 for unsigned-8.
    audio_sample_format_t this_sample_format;
    int sample_format_score;

    bool supports_u8 = (range.sample_formats & U8_FMT) == U8_FMT;
    bool supports_s16 = (range.sample_formats & S16_FMT) == S16_FMT;
    bool supports_s24 = (range.sample_formats & S24_FMT) == S24_FMT;
    bool supports_f32 = (range.sample_formats & F32_FMT) == F32_FMT;
    if ((range.sample_formats & AUDIO_SAMPLE_FORMAT_FLAG_INVERT_ENDIAN) ||
        (!supports_u8 && !supports_s16 && !supports_s24 && !supports_f32)) {
      continue;  // Otherwise skip: this isn't a sample container we understand.
    }

    if ((pref_sample_format & range.sample_formats) == pref_sample_format) {
      // Direct match.
      this_sample_format = pref_sample_format;
      sample_format_score = 5;
    } else if (supports_s24) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_24BIT_IN32;
      sample_format_score = 4;
    } else if (supports_s16) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_16BIT;
      sample_format_score = 3;
    } else if (supports_f32) {
      this_sample_format = AUDIO_SAMPLE_FORMAT_32BIT_FLOAT;
      sample_format_score = 2;
    } else {
      FXL_DCHECK(supports_u8);
      this_sample_format = static_cast<audio_sample_format_t>(U8_FMT);
      sample_format_score = 1;
    }

    // Next consider the supported channel counts.  3 points for matching the
    // requested channel count.  Otherwise, default to stereo (if supported) and
    // score 2 points.  Failing that, just pick the top end of the supported
    // channel range and score 1 point.
    uint32_t this_channels;
    int channel_count_score;
    if ((pref_channels >= range.min_channels) &&
        (pref_channels <= range.max_channels)) {
      this_channels = pref_channels;
      channel_count_score = 3;
    } else if ((2 >= range.min_channels) && (2 <= range.max_channels)) {
      this_channels = 2;
      channel_count_score = 2;
    } else {
      this_channels = range.max_channels;
      channel_count_score = 1;
    }

    // Next score based on supported frame rates.  Score 3 points for a match, 2
    // points if we have to scale up to the nearest supported rate, or 1 point
    // if we have to scale down.
    //
    if (range.min_frames_per_second > range.max_frames_per_second) {
      // Skip this frame rate range entirely if it is empty.
      FXL_LOG(INFO) << "Skipping empty frame rate range ["
                    << range.min_frames_per_second << ", "
                    << range.max_frames_per_second
                    << "] while searching for best format in driver list.";
      continue;
    }

    uint32_t this_frame_rate = 0;
    uint32_t frame_rate_delta = std::numeric_limits<uint32_t>::max();
    int frame_rate_score = 0;
    if (range.flags & ASF_RANGE_FLAG_FPS_CONTINUOUS) {
      // This is a continuous sample rate range.  If we are within the range,
      // thats a match.  Otherwise move up/down as needed to match the min/max
      // of the range as appropriate.
      if ((pref_frame_rate >= range.min_frames_per_second) &&
          (pref_frame_rate <= range.max_frames_per_second)) {
        this_frame_rate = pref_frame_rate;
        frame_rate_score = 3;
        frame_rate_delta = 0;
      } else if (pref_frame_rate < range.min_frames_per_second) {
        this_frame_rate = range.min_frames_per_second;
        frame_rate_score = 2;
        frame_rate_delta = range.min_frames_per_second - pref_frame_rate;
      } else {
        FXL_DCHECK(pref_frame_rate > range.max_frames_per_second);
        this_frame_rate = range.max_frames_per_second;
        frame_rate_score = 1;
        frame_rate_delta = pref_frame_rate - range.max_frames_per_second;
      }
    } else {
      // This is a discrete sample rate range.  Use the frame rate enumerator
      // utility class to evaluate each of the possible frame rates.
      for (const uint32_t rate : ::audio::utils::FrameRateEnumerator(range)) {
        if (pref_frame_rate == rate) {
          // We matched our preference.  No need to keep searching.
          this_frame_rate = rate;
          frame_rate_score = 3;
          frame_rate_delta = 0;
          break;
        }

        if (pref_frame_rate < rate) {
          // Scaling up; 2 points.  If this better than what we were doing
          // before, just choose it.  If we were already going to scale up,
          // pick the frame rate which is closer to our preference.
          // Otherwise, do nothing.
          if ((frame_rate_score < 2) ||
              ((frame_rate_score == 2) && (rate < this_frame_rate))) {
            this_frame_rate = rate;
            frame_rate_score = 2;
            frame_rate_delta = rate - pref_frame_rate;
          }
        } else {
          FXL_DCHECK(pref_frame_rate > rate);

          // Scaling down; 1 point.  If this better than what we were doing
          // before, just choose it.  If we were already going to scale down,
          // pick the frame rate which is closer to our preference.
          // Otherwise, do nothing.
          if ((frame_rate_score < 1) ||
              ((frame_rate_score == 1) && (rate > this_frame_rate))) {
            this_frame_rate = rate;
            frame_rate_score = 1;
            frame_rate_delta = pref_frame_rate - rate;
          }
        }
      }
    }

    // If our frame rate score is still zero, it means that we were given a
    // discrete frame range by a driver which was completely empty (even
    // though min was <= max as it should be)  Debug log a warning, then skip
    // the range entirely.
    if (frame_rate_score == 0) {
      FXL_LOG(INFO) << "Skipping empty discrete frame rate range ["
                    << range.min_frames_per_second << ", "
                    << range.max_frames_per_second << "] (flags " << range.flags
                    << ") while searching for best format";
      continue;
    }

    // OK, we have computed the best option supported by this frame rate range.
    // Weight the score, and it if it better then any of our previous best
    // score, replace our previous best with this.
    uint32_t score;
    score = (sample_format_score * 100)   // format is the most important.
            + (channel_count_score * 10)  // channel count comes second.
            + frame_rate_score;           // frame rate is the least important.

    FXL_DCHECK(score > 0);
    FXL_DCHECK(::audio::utils::FormatIsCompatible(
        this_frame_rate, this_channels, this_sample_format, range));

    // If this score is better than the current best score, or this score ties
    // the current best score but the frame rate distance is less, then this is
    // the new best format.
    if ((score > best_score) ||
        ((score == best_score) && (frame_rate_delta < best_frame_rate_delta))) {
      best_frame_rate = this_frame_rate;
      best_frame_rate_delta = frame_rate_delta;
      best_channels = this_channels;
      best_sample_format = this_sample_format;
      best_score = score;
    }
  }

  // If our score is still zero, then there must have be absolutely no supported
  // formats in the set provided by the driver.
  if (!best_score) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  __UNUSED bool convert_res =
      driver_utils::DriverSampleFormatToAudioSampleFormat(best_sample_format,
                                                          sample_format_inout);
  FXL_DCHECK(convert_res);

  *channels_inout = best_channels;
  *frames_per_second_inout = best_frame_rate;

  return ZX_OK;
}

zx_status_t AcquireHighPriorityProfile(zx::profile* profile) {
  // Use threadsafe static initialization to get our one-and-only copy of this
  // profile object. Each subsequent call will return a duplicate of that
  // profile handle to ensure sharing of thread pools.
  static zx::profile high_priority_profile;
  static zx_status_t initial_status = [](zx::profile* profile) {
    zx::channel ch0, ch1;
    zx_status_t res = zx::channel::create(0u, &ch0, &ch1);
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create channel, res=" << res;
      return res;
    }

    res = fdio_service_connect(
        (std::string("/svc/") + fuchsia::scheduler::ProfileProvider::Name_)
            .c_str(),
        ch0.get());
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to connect to ProfileProvider, res=" << res;
      return res;
    }

    fuchsia::scheduler::ProfileProvider_SyncProxy provider(std::move(ch1));

    zx_status_t fidl_status;
    zx::profile res_profile;
    res = provider.GetProfile(24 /* HIGH_PRIORITY */,
                              "src/media/audio/audio_core", &fidl_status,
                              &res_profile);
    if (res != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create profile, res=" << res;
      return res;
    }
    if (fidl_status != ZX_OK) {
      FXL_LOG(ERROR) << "Failed to create profile, fidl_status=" << fidl_status;
      return fidl_status;
    }

    *profile = std::move(res_profile);
    return ZX_OK;
  }(&high_priority_profile);

  // If the initial acquisition of the profile failed, return that status.
  if (initial_status != ZX_OK)
    return initial_status;

  // Otherwise, dupe this handle and return it.
  return high_priority_profile.duplicate(ZX_RIGHT_SAME_RIGHTS, profile);
}

}  // namespace media::audio
