blob: 9bfba7089b6d77a9070a587ddcb63d6b2deaa6c0 [file] [log] [blame]
// 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.
#ifndef SRC_MEDIA_AUDIO_AUDIO_CORE_DRIVER_OUTPUT_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_DRIVER_OUTPUT_H_
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include "src/media/audio/audio_core/audio_driver.h"
#include "src/media/audio/audio_core/audio_output.h"
#include "src/media/audio/audio_core/mixer/output_producer.h"
#include "src/media/audio/lib/wav_writer/wav_writer.h"
namespace media::audio {
constexpr bool kEnableFinalMixWavWriter = false;
class DriverOutput : public AudioOutput {
public:
// TODO(13550): Revert these to 20/30 instead of 50/60. In the long term, get these into the
// range of 5/10.
static constexpr zx::duration kDefaultLowWaterNsec = zx::msec(50);
static constexpr zx::duration kDefaultHighWaterNsec = zx::msec(60);
static std::shared_ptr<AudioOutput> Create(zx::channel channel, ThreadingModel* threading_model,
DeviceRegistry* registry, LinkMatrix* link_matrix);
DriverOutput(ThreadingModel* threading_model, DeviceRegistry* registry,
zx::channel initial_stream_channel, LinkMatrix* link_matrix);
~DriverOutput();
protected:
// AudioOutput implementation
zx_status_t Init() FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token()) override;
void OnWakeup() FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token()) override;
std::optional<MixStage::FrameSpan> StartMixJob(zx::time process_start)
FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token()) override;
void FinishMixJob(const MixStage::FrameSpan& span, float* buffer)
FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token()) override;
// AudioDevice implementation
void ApplyGainLimits(fuchsia::media::AudioGainInfo* in_out_info, uint32_t set_flags) override;
private:
enum class State {
Uninitialized,
FormatsUnknown,
FetchingFormats,
Configuring,
Starting,
Started,
Shutdown,
};
void ScheduleNextLowWaterWakeup();
// Callbacks triggered by our driver object as it completes various
// asynchronous tasks.
void OnDriverInfoFetched() override FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token());
void OnDriverConfigComplete() override FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token());
void OnDriverStartComplete() override FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token());
// Uses |writer| to populate the frames specified by |span|.
//
// Writer will be called iteratively with a |offset| frame, a |length| (also in frames), and
// a |dest_buf|, which is the pointer into the ring buffer for the frame |start|.
//
// Note: here |offset| is relative to |span.start|. The absolute frame for the write is simply
// |span.start + offset|.
void WriteToRing(const MixStage::FrameSpan& span,
fit::function<void(uint64_t offset, uint32_t length, void* dest_buf)> writer)
FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token());
void FillRingWithSilence(const MixStage::FrameSpan& span)
FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain().token());
State state_ = State::Uninitialized;
zx::channel initial_stream_channel_;
int64_t frames_sent_ = 0;
int64_t low_water_frames_ = 0;
TimelineFunction clock_monotonic_to_output_frame_;
GenerationId clock_monotonic_to_output_frame_generation_;
zx::time underflow_start_time_;
zx::time underflow_cooldown_deadline_;
// Details about the final output format
std::unique_ptr<OutputProducer> output_producer_;
std::optional<PipelineConfig> pipeline_config_;
// This atomic is only used when the final-mix wave-writer is enabled --
// specifically to generate unique ids for each final-mix WAV file.
static std::atomic<uint32_t> final_mix_instance_num_;
WavWriter<kEnableFinalMixWavWriter> wav_writer_;
};
} // namespace media::audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_DRIVER_OUTPUT_H_