blob: d5a788af5ed4b88525cd65f756e0949b3a7de36d [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_UTILS_H_
#define SRC_MEDIA_AUDIO_AUDIO_CORE_UTILS_H_
#include <fuchsia/hardware/audio/cpp/fidl.h>
#include <fuchsia/media/cpp/fidl.h>
#include <lib/fit/function.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/zx/profile.h>
#include <lib/zx/thread.h>
#include <stdint.h>
#include <zircon/device/audio.h>
#include <zircon/types.h>
#include <atomic>
#include <vector>
#include <fbl/ref_counted.h>
#include "src/media/audio/audio_core/mixer/constants.h"
#include "src/media/audio/audio_core/pin_executable_memory.h"
namespace media::audio {
class GenerationId {
public:
uint32_t get() const { return id_; }
uint32_t Next() {
uint32_t ret;
do {
ret = ++id_;
} while (ret == kInvalidGenerationId);
return ret;
}
private:
uint32_t id_ = kInvalidGenerationId + 1;
};
class AtomicGenerationId {
public:
AtomicGenerationId() : id_(kInvalidGenerationId + 1) {}
uint32_t get() const { return id_.load(); }
uint32_t Next() {
uint32_t ret;
do {
ret = id_.fetch_add(1);
} while (ret == kInvalidGenerationId);
return ret;
}
private:
std::atomic<uint32_t> id_;
};
// Given a preferred format and a list of driver supported formats, select
// the "best" form and update the in/out parameters, then return ZX_OK. If no
// formats exist, or all format ranges get completely rejected, return an error
// and leave the in/out params as they were.
zx_status_t SelectBestFormat(const std::vector<fuchsia::hardware::audio::PcmSupportedFormats>& fmts,
uint32_t* frames_per_second_inout, uint32_t* channels_inout,
fuchsia::media::AudioSampleFormat* sample_format_inout);
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);
// Given a format and a list of driver supported formats, if the format is found in
// the driver supported list then return true, otherwise return false.
bool IsFormatInSupported(
const fuchsia::media::AudioStreamType& stream_type,
const std::vector<fuchsia::hardware::audio::PcmSupportedFormats>& supported_formats);
// A simple extension to the libfzl VmoMapper which mixes in ref counting state
// to allow for shared VmoMapper semantics.
class RefCountedVmoMapper : public PinExecutableMemory::VmoMapper,
public fbl::RefCounted<PinExecutableMemory::VmoMapper> {};
zx_status_t AcquireHighPriorityProfile(zx::profile* profile);
void AcquireAudioCoreImplProfile(sys::ComponentContext* context,
fit::function<void(zx_status_t, zx::profile)> callback);
void AcquireRelativePriorityProfile(uint32_t priority, sys::ComponentContext* context,
fit::function<void(zx_status_t, zx::profile)> callback);
// A timer which computes the amount of time the current thread spends scheduled
// (running) on a CPU, or queued.
class ThreadCpuTimer {
public:
// Start running the timer on the current thread.
void Start() {
thread_ = zx::thread::self();
start_status_ =
thread_->get_info(ZX_INFO_TASK_RUNTIME, &start_, sizeof(start_), nullptr, nullptr);
end_status_ = ZX_ERR_BAD_STATE;
}
// Stop running the timer.
void Stop() {
end_status_ = thread_->get_info(ZX_INFO_TASK_RUNTIME, &end_, sizeof(end_), nullptr, nullptr);
}
// Reports how long the current thread spent running on a CPU. See ZX_INFO_TASK_RUNTIME.
// Cannot be called while the timer is running; the timer must be stopped.
zx::duration cpu() const {
if (start_status_ != ZX_OK || end_status_ != ZX_OK) {
return zx::duration::infinite_past();
}
return zx::duration(end_.cpu_time) - zx::duration(start_.cpu_time);
}
// Reports how long the current thread spent waiting to run. See ZX_INFO_TASK_RUNTIME.
// Does not include time spent blocked; only includes time the thread is "ready" but waiting.
// Cannot be called while the timer is running; the timer must be stopped.
zx::duration queue() const {
if (start_status_ != ZX_OK || end_status_ != ZX_OK) {
return zx::duration::infinite_past();
}
return zx::duration(end_.queue_time) - zx::duration(start_.queue_time);
}
private:
zx::unowned_thread thread_;
zx_info_task_runtime_t start_;
zx_info_task_runtime_t end_;
zx_status_t start_status_;
zx_status_t end_status_;
};
} // namespace media::audio
#endif // SRC_MEDIA_AUDIO_AUDIO_CORE_UTILS_H_