blob: 93f885f49b27417c444e13d5cb529c017e220e25 [file] [log] [blame]
// Copyright 2020 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/ultrasound_renderer.h"
#include "src/media/audio/lib/clock/utils.h"
namespace media::audio {
namespace {
const PipelineConfig::MixGroup* FindUltrasoundGroup(const PipelineConfig::MixGroup& group) {
auto& inputs = group.input_streams;
if (std::find(inputs.begin(), inputs.end(), RenderUsage::ULTRASOUND) != inputs.end()) {
return &group;
}
for (auto& child : group.inputs) {
auto result = FindUltrasoundGroup(child);
if (result) {
return result;
}
}
return nullptr;
}
} // namespace
UltrasoundRenderer::UltrasoundRenderer(
fidl::InterfaceRequest<fuchsia::media::AudioRenderer> request, Context* context,
fuchsia::ultrasound::Factory::CreateRendererCallback callback)
: BaseRenderer(std::move(request), context), create_callback_(std::move(callback)) {
FX_DCHECK(create_callback_);
reporter().SetUsage(RenderUsage::ULTRASOUND);
}
fit::result<std::shared_ptr<ReadableStream>, zx_status_t> UltrasoundRenderer::InitializeDestLink(
const AudioObject& dest) {
if (!create_callback_) {
return fit::error(ZX_ERR_BAD_STATE);
}
uint32_t channels;
uint32_t frames_per_second;
// UltrasoundRenderers use FLOAT samples, but the frame rate and channel count
// are defined by the output pipeline we are connected to.
auto pipeline_config = dest.pipeline_config();
if (pipeline_config) {
auto group = FindUltrasoundGroup(pipeline_config->root());
if (!group) {
FX_LOGS(ERROR) << "PipelineConfig missing ULTRASOUND group";
return fit::error(ZX_ERR_BAD_STATE);
}
channels = group->output_channels;
frames_per_second = group->output_rate;
} else {
auto format = dest.format();
if (!format) {
return fit::error(ZX_ERR_BAD_STATE);
}
channels = format->channels();
frames_per_second = format->frames_per_second();
}
format_ = Format::Create({
.sample_format = fuchsia::media::AudioSampleFormat::FLOAT,
.channels = channels,
.frames_per_second = frames_per_second,
})
.take_value();
auto reference_clock_result = reference_clock().DuplicateClockReadOnly();
if (reference_clock_result.is_error()) {
return fit::error(reference_clock_result.error());
}
reporter().SetFormat(*format_);
create_callback_(reference_clock_result.take_value(), format_->stream_type());
create_callback_ = nullptr;
return BaseRenderer::InitializeDestLink(dest);
}
void UltrasoundRenderer::CleanupDestLink(const AudioObject& dest) {
// Ultrasound renderers do not support being re-linked. If we become unlinked then we will just
// close the client channel.
binding().Close(ZX_OK);
BaseRenderer::CleanupDestLink(dest);
}
// Some unsupported methods on ultrasound renderers.
void UltrasoundRenderer::SetPcmStreamType(fuchsia::media::AudioStreamType format) {
FX_LOGS(ERROR) << "Unsupported method SetPcmStreamType on ultrasound renderer";
binding().Close(ZX_ERR_NOT_SUPPORTED);
}
void UltrasoundRenderer::SetUsage(fuchsia::media::AudioRenderUsage usage) {
FX_LOGS(ERROR) << "Unsupported method SetUsage on ultrasound renderer";
binding().Close(ZX_ERR_NOT_SUPPORTED);
}
void UltrasoundRenderer::BindGainControl(
fidl::InterfaceRequest<fuchsia::media::audio::GainControl> request) {
FX_LOGS(ERROR) << "Unsupported method BindGainControl on ultrasound renderer";
binding().Close(ZX_ERR_NOT_SUPPORTED);
}
void UltrasoundRenderer::SetReferenceClock(zx::clock ref_clock) {
FX_LOGS(ERROR) << "Unsupported method SetReferenceClock on ultrasound renderer";
binding().Close(ZX_ERR_NOT_SUPPORTED);
}
} // namespace media::audio