// Copyright 2016 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.

#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_THROTTLE_OUTPUT_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_THROTTLE_OUTPUT_H_

#include <fuchsia/media/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>

#include <fbl/ref_ptr.h>

#include "src/lib/fxl/synchronization/thread_annotations.h"
#include "src/media/audio/audio_core/audio_clock.h"
#include "src/media/audio/audio_core/audio_output.h"
#include "src/media/audio/audio_core/pipeline_config.h"
#include "src/media/audio/lib/clock/clone_mono.h"
#include "src/media/audio/lib/clock/utils.h"

namespace media::audio {

static constexpr zx::duration TRIM_PERIOD = zx::msec(10);

// Throttle output may only be owned on the FIDL thread.
class ThrottleOutput : public AudioOutput {
 public:
  static std::shared_ptr<AudioOutput> Create(ThreadingModel* threading_model,
                                             DeviceRegistry* registry, LinkMatrix* link_matrix) {
    return std::make_shared<ThrottleOutput>(threading_model, registry, link_matrix);
  }

  // Establish an audio clock (clone of monotonic) and override the default reference_clock()
  // implementation that calls into the AudioDriver, because we don't have an associated driver.
  ThrottleOutput(ThreadingModel* threading_model, DeviceRegistry* registry, LinkMatrix* link_matrix)
      : AudioOutput("throttle", threading_model, registry, link_matrix),
        audio_clock_(AudioClock::DeviceFixed(audio::clock::CloneOfMonotonic(),
                                             AudioClock::kMonotonicDomain)) {
    const auto ref_now = reference_clock().Read();
    const auto fps = PipelineConfig::kDefaultMixGroupRate;
    ref_time_to_frac_presentation_frame_ =
        TimelineFunction(0, ref_now.get(), Fixed(fps).raw_value(), zx::sec(1).get());
    ref_time_to_frac_safe_read_or_write_frame_ =
        TimelineFunction(0, ref_now.get(), Fixed(fps).raw_value(), zx::sec(1).get());

    // This is just some placeholder format that we can use to instantiate a mix
    // stage for us. Since we never return a value from |StartMixJob|, we'll only
    // ever trim on this mix stage, so the format here is not particularly
    // important.
    //
    // Longer term we should just have something like a 'NullMixStage' that only
    // has this trim capability.

    // This must be non-0, but it doesn't actually matter much since we'll never mix with a throttle
    // output.
    static const uint32_t kMaxBatchSize = PAGE_SIZE;
    SetupMixTask(DeviceConfig::OutputDeviceProfile(), kMaxBatchSize,
                 driver_ref_time_to_frac_presentation_frame());
  }

  ~ThrottleOutput() override = default;

  AudioClock& reference_clock() override { return audio_clock_; }

 protected:
  // AudioOutput Implementation
  void OnWakeup() FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token()) override {
    if (uninitialized_) {
      last_sched_time_mono_ = async::Now(mix_domain().dispatcher());

      UpdatePlugState(true, zx::time(0));
      Process();
      uninitialized_ = false;
    }
  }

  std::optional<AudioOutput::FrameSpan> StartMixJob(zx::time ref_time) override {
    // Compute the next callback time; check whether trimming is falling behind.
    last_sched_time_mono_ = last_sched_time_mono_ + TRIM_PERIOD;
    auto mono_time = reference_clock().MonotonicTimeFromReferenceTime(ref_time);

    if (mono_time > last_sched_time_mono_) {
      // TODO(mpuryear): Trimming is falling behind. We should tell someone.
      last_sched_time_mono_ = mono_time + TRIM_PERIOD;
    }

    // TODO(mpuryear): Optimize Trim by scheduling at the end of our first pending packet, instead
    // of polling. This will also make our timing in returning packets more consistent.
    //
    // To do this, we would need wake and recompute, whenever an AudioRenderer client changes its
    // rate transformation. For now, just polling is simpler.
    SetNextSchedTimeMono(last_sched_time_mono_);

    // Throttle outputs don't actually mix; they provide backpressure to the
    // pipeline by holding AudioPacket references until they are presented. We
    // only need to schedule our next callback to keep things running, and let
    // the base class implementation handle trimming the output.
    return std::nullopt;
  }

  void FinishMixJob(const AudioOutput::FrameSpan& span, const float* buffer) override {
    // Since we never start any jobs, this should never be called.
    FX_DCHECK(false);
  }

  zx::duration MixDeadline() const override {
    // Since we never actually mix (StartMixJob always returns nullopt), this number doesn't matter.
    // Return infinity to avoid spurious "underflow" messages.
    return zx::duration::infinite();
  }

  // AudioDevice implementation.
  // No one should ever be trying to apply gain limits for a throttle output.
  void ApplyGainLimits(fuchsia::media::AudioGainInfo* in_out_info,
                       fuchsia::media::AudioGainValidFlags set_flags) override {
    FX_DCHECK(false);
  }
  virtual zx::time last_sched_time_mono() { return last_sched_time_mono_; }

  // Override these since we don't have a real driver.
  const TimelineFunction& driver_ref_time_to_frac_presentation_frame() const override {
    return ref_time_to_frac_presentation_frame_;
  }
  const TimelineFunction& driver_ref_time_to_frac_safe_read_or_write_frame() const override {
    return ref_time_to_frac_safe_read_or_write_frame_;
  }

 private:
  zx::time last_sched_time_mono_;

  bool uninitialized_ = true;
  TimelineFunction ref_time_to_frac_presentation_frame_;
  TimelineFunction ref_time_to_frac_safe_read_or_write_frame_;
  AudioClock audio_clock_;
};

}  // namespace media::audio

#endif  // SRC_MEDIA_AUDIO_AUDIO_CORE_THROTTLE_OUTPUT_H_
