blob: 25c660b9430ed9117eae8abbbbe7d2f6b3de2595 [file] [log] [blame]
// Copyright 2021 The Chromium 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 "services/audio/sync_mixing_graph_input.h"
#include "base/trace_event/trace_event.h"
#include "media/base/audio_pull_fifo.h"
#include "media/base/audio_timestamp_helper.h"
namespace audio {
SyncMixingGraphInput::SyncMixingGraphInput(MixingGraph* graph,
const media::AudioParameters& params)
: graph_(graph), params_(params) {
DCHECK(graph);
CHECK(params_.IsValid());
}
SyncMixingGraphInput::~SyncMixingGraphInput() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
}
// Either calls Render() directly to produce the requested input audio, or - in
// the case of a frames per buffer mismatch - pulls audio from the |fifo_| which
// in turn calls Render() as needed.
double SyncMixingGraphInput::ProvideInput(media::AudioBus* audio_bus,
uint32_t frames_delayed) {
DCHECK_EQ(audio_bus->channels(), params_.channels());
TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("audio"),
"SyncMixingGraphInput::ProvideInput", "frames_delayed",
frames_delayed, "bus frames", audio_bus->frames());
if (!fifo_ && audio_bus->frames() != params_.frames_per_buffer()) {
fifo_ = std::make_unique<media::AudioPullFifo>(
params_.channels(), params_.frames_per_buffer(),
base::BindRepeating(&SyncMixingGraphInput::Render,
base::Unretained(this)));
}
// Used by Render() for delay calculation.
converter_render_frame_delay_ = frames_delayed;
if (fifo_)
fifo_->Consume(audio_bus, audio_bus->frames());
else
Render(0, audio_bus);
converter_render_frame_delay_ = 0;
return volume_;
}
const media::AudioParameters& SyncMixingGraphInput::GetParams() const {
return params_;
}
void SyncMixingGraphInput::SetVolume(double volume) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
volume_ = volume;
}
void SyncMixingGraphInput::Start(
media::AudioOutputStream::AudioSourceCallback* source_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
DCHECK(!fifo_);
DCHECK(!source_callback_);
source_callback_ = source_callback;
graph_->AddInput(this);
}
void SyncMixingGraphInput::Stop() {
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
graph_->RemoveInput(this);
if (fifo_)
fifo_.reset();
source_callback_ = nullptr;
}
void SyncMixingGraphInput::Render(int fifo_frame_delay,
media::AudioBus* audio_bus) {
DCHECK(source_callback_);
TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("audio"),
"SyncMixingGraphInput::Render", "this",
static_cast<void*>(this));
base::TimeDelta delay = media::AudioTimestampHelper::FramesToTime(
converter_render_frame_delay_ + fifo_frame_delay, params_.sample_rate());
source_callback_->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus);
TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("audio"),
"SyncMixingGraphInput::Render", "total frames delay",
converter_render_frame_delay_ + fifo_frame_delay,
"bus frames", audio_bus->frames());
}
} // namespace audio