blob: bb7dbd0ecc4bf11b40971ac860931f07b3c5734b [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_RING_BUFFER_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_RING_BUFFER_H_
#include <lib/zx/vmo.h>
#include <memory>
#include "src/media/audio/audio_core/stream.h"
#include "src/media/audio/audio_core/utils.h"
#include "src/media/audio/audio_core/versioned_timeline_function.h"
namespace media::audio {
class RingBuffer : public Stream {
public:
// Creates a RingBuffer stream for a buffer backed by the given |vmo|.
//
// If |endpoint| is |kReadable|, then this ring buffer will function as if there is an AudioInput
// device populating the |vmo| with audio frames conforming to |format|. Essentially the ring will
// consider frames |frame_count| frames before |reference_clock_to_fractional_frames(now)| to
// be valid.
//
// Conversely, if |endpoint| is |kWritable|, then this Stream will vend out empty buffers that are
// up to |frame_count| frames ahead of |reference_clock_to_fractional_frames(now)|. With the
// expectation there is a hardware device consuming frames at the trailing edge.
//
// |offset_frames| determines how logical frame numbers are mapped to physical frame locations in
// the ring buffer. Ex: if |offset_frames| is 5, then frame 0 will be located at frame 5 in the
// ring buffer.
enum class Endpoint {
kReadable,
kWritable,
};
enum class VmoMapping {
kReadOnly,
kReadWrite,
};
static std::shared_ptr<RingBuffer> CreateHardwareBuffer(
const Format& format,
fbl::RefPtr<VersionedTimelineFunction> reference_clock_to_fractional_frames, zx::vmo vmo,
uint32_t frame_count, VmoMapping vmo_mapping, Endpoint endpoint, uint32_t offset_frames);
// An allocating variant of |Create|.
struct Endpoints {
std::shared_ptr<RingBuffer> reader;
std::shared_ptr<RingBuffer> writer;
};
static Endpoints AllocateSoftwareBuffer(
const Format& format,
fbl::RefPtr<VersionedTimelineFunction> reference_clock_to_fractional_frames,
uint32_t frame_count, uint32_t frame_offset = 0);
// |media::audio::Stream|
void UnlockBuffer(bool release_buffer) override {}
void Trim(zx::time trim_threshold) override {}
TimelineFunctionSnapshot ReferenceClockToFractionalFrames() const override;
Endpoint endpoint() const { return endpoint_; }
uint64_t size() const { return vmo_mapper_->size(); }
uint32_t frames() const { return frames_; }
uint32_t frame_size() const { return format().bytes_per_frame(); }
uint8_t* virt() const { return reinterpret_cast<uint8_t*>(vmo_mapper_->start()); }
protected:
RingBuffer(const Format& format,
fbl::RefPtr<VersionedTimelineFunction> reference_clock_to_fractional_frames,
fbl::RefPtr<RefCountedVmoMapper> vmo_mapper, uint32_t frame_count, Endpoint endpoint,
uint32_t offset_frames);
uint32_t offset_frames() const { return offset_frames_; }
private:
const Endpoint endpoint_;
const fbl::RefPtr<RefCountedVmoMapper> vmo_mapper_;
const uint32_t frames_ = 0;
const fbl::RefPtr<VersionedTimelineFunction> reference_clock_to_fractional_frame_;
const uint32_t offset_frames_;
};
} // namespace media::audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_RING_BUFFER_H_