Commit 5d123b36 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Move chromium to AudioOut interface

AudioRenderer interface is being replaced with AudioOut. Updated
//media and //chromecast to use the new interface. Also fixed a crash
in FIDL interface handler.

Bug: 873676
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Ib0f9963fb7b39033bb89a0945a4b8eb5616594cc
Reviewed-on: https://chromium-review.googlesource.com/1175240Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Reviewed-by: default avatarKenneth MacKay <kmackay@chromium.org>
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583789}
parent a3a58b3a
......@@ -28,6 +28,11 @@ constexpr base::TimeDelta kTargetWritePeriod =
// MixerOutputStreamFuchsia::Write().
constexpr int kMaxOutputBufferSizeFrames = 4096;
// Current AudioOut implementation allows only one buffer with id=0.
// TODO(sergeyu): Replace with an incrementing buffer id once AddPayloadBuffer()
// and RemovePayloadBuffer() are implemented properly in AudioOut.
const uint32_t kBufferId = 0;
// static
std::unique_ptr<MixerOutputStream> MixerOutputStream::Create() {
return std::make_unique<MixerOutputStreamFuchsia>();
......@@ -37,7 +42,7 @@ MixerOutputStreamFuchsia::MixerOutputStreamFuchsia() = default;
MixerOutputStreamFuchsia::~MixerOutputStreamFuchsia() = default;
bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
DCHECK(!audio_renderer_);
DCHECK(!audio_out_);
DCHECK(reference_time_.is_null());
sample_rate_ = requested_sample_rate;
......@@ -45,12 +50,12 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
target_packet_size_ = ::media::AudioTimestampHelper::TimeToFrames(
kTargetWritePeriod, sample_rate_);
// Connect |audio_renderer_|.
// Connect |audio_out_|.
fuchsia::media::AudioPtr audio_server =
base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::media::Audio>();
audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest());
audio_renderer_.set_error_handler(
audio_server->CreateAudioOut(audio_out_.NewRequest());
audio_out_.set_error_handler(
fit::bind_member(this, &MixerOutputStreamFuchsia::OnRendererError));
// Configure the renderer.
......@@ -58,13 +63,13 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
format.channels = channels_;
format.frames_per_second = sample_rate_;
audio_renderer_->SetPcmStreamType(std::move(format));
audio_out_->SetPcmStreamType(std::move(format));
// Use number of samples to specify media position.
audio_renderer_->SetPtsUnits(sample_rate_, 1);
audio_out_->SetPtsUnits(sample_rate_, 1);
audio_renderer_->EnableMinLeadTimeEvents(true);
audio_renderer_.events().OnMinLeadTimeChanged =
audio_out_->EnableMinLeadTimeEvents(true);
audio_out_.events().OnMinLeadTimeChanged =
fit::bind_member(this, &MixerOutputStreamFuchsia::OnMinLeadTimeChanged);
return true;
......@@ -93,7 +98,7 @@ int MixerOutputStreamFuchsia::OptimalWriteFramesCount() {
bool MixerOutputStreamFuchsia::Write(const float* data,
int data_size,
bool* out_playback_interrupted) {
if (!audio_renderer_)
if (!audio_out_)
return false;
DCHECK_EQ(data_size % channels_, 0);
......@@ -125,12 +130,13 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
data, packet_size);
// Send a new packet.
fuchsia::media::AudioPacket packet;
packet.timestamp = stream_position_samples_;
fuchsia::media::StreamPacket packet;
packet.pts = stream_position_samples_;
packet.payload_buffer_id = kBufferId;
packet.payload_offset = payload_buffer_pos_;
packet.payload_size = packet_size;
packet.flags = 0;
audio_renderer_->SendPacketNoReply(std::move(packet));
audio_out_->SendPacketNoReply(std::move(packet));
// Update stream position.
int frames = data_size / channels_;
......@@ -139,7 +145,7 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
if (reference_time_.is_null()) {
reference_time_ = now + min_lead_time_;
audio_renderer_->PlayNoReply(reference_time_.ToZxTime(),
audio_out_->PlayNoReply(reference_time_.ToZxTime(),
stream_position_samples_ - frames);
} else {
// Block the thread to limit amount of buffered data. Currently
......@@ -162,7 +168,7 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
void MixerOutputStreamFuchsia::Stop() {
reference_time_ = base::TimeTicks();
audio_renderer_.Unbind();
audio_out_.Unbind();
}
size_t MixerOutputStreamFuchsia::GetMinBufferSize() {
......@@ -184,8 +190,8 @@ bool MixerOutputStreamFuchsia::InitializePayloadBuffer() {
}
payload_buffer_pos_ = 0;
audio_renderer_->SetPayloadBuffer(
zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
audio_out_->AddPayloadBuffer(
kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
return true;
}
......
......@@ -37,7 +37,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream {
base::TimeTicks GetCurrentStreamTime();
// Event handlers for |audio_renderer_|.
// Event handlers for |audio_out_|.
void OnRendererError();
void OnMinLeadTimeChanged(int64_t min_lead_time);
......@@ -48,7 +48,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream {
int target_packet_size_ = 0;
// Audio renderer connection.
fuchsia::media::AudioRenderer2Ptr audio_renderer_;
fuchsia::media::AudioOutPtr audio_out_;
base::SharedMemory payload_buffer_;
size_t payload_buffer_pos_ = 0;
......
......@@ -98,13 +98,7 @@ TEST_F(AudioOutputTest, StopTwice) {
}
// This test produces actual audio for .25 seconds on the default device.
#if defined(OS_FUCHSIA)
// TODO(https://crbug.com/873676): Test flakes started when SDK rolled.
#define MAYBE_Play200HzTone DISABLED_Play200HzTone
#else
#define MAYBE_Play200HzTone Play200HzTone
#endif
TEST_F(AudioOutputTest, MAYBE_Play200HzTone) {
TEST_F(AudioOutputTest, Play200HzTone) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
stream_params_ =
......
......@@ -13,6 +13,11 @@
namespace media {
// Current AudioOut implementation allows only one buffer with id=0.
// TODO(sergeyu): Replace with an incrementing buffer id once AddPayloadBuffer()
// and RemovePayloadBuffer() are implemented properly in AudioOut.
const uint32_t kBufferId = 0;
AudioOutputStreamFuchsia::AudioOutputStreamFuchsia(
AudioManagerFuchsia* manager,
const AudioParameters& parameters)
......@@ -22,36 +27,36 @@ AudioOutputStreamFuchsia::AudioOutputStreamFuchsia(
AudioOutputStreamFuchsia::~AudioOutputStreamFuchsia() {
// Close() must be called first.
DCHECK(!audio_renderer_);
DCHECK(!audio_out_);
}
bool AudioOutputStreamFuchsia::Open() {
DCHECK(!audio_renderer_);
DCHECK(!audio_out_);
// Connect |audio_renderer_| to the audio service.
// Connect |audio_out_| to the audio service.
fuchsia::media::AudioPtr audio_server =
base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::media::Audio>();
audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest());
audio_renderer_.set_error_handler(
audio_server->CreateAudioOut(audio_out_.NewRequest());
audio_out_.set_error_handler(
fit::bind_member(this, &AudioOutputStreamFuchsia::OnRendererError));
// Inform the |audio_renderer_| of the format required by the caller.
// Inform the |audio_out_| of the format required by the caller.
fuchsia::media::AudioStreamType format;
format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
format.channels = parameters_.channels();
format.frames_per_second = parameters_.sample_rate();
audio_renderer_->SetPcmStreamType(std::move(format));
audio_out_->SetPcmStreamType(std::move(format));
// Use number of samples to specify media position.
audio_renderer_->SetPtsUnits(parameters_.sample_rate(), 1);
audio_out_->SetPtsUnits(parameters_.sample_rate(), 1);
// Setup OnMinLeadTimeChanged event listener. This event is used to get
// |min_lead_time_|, which indicates how far ahead audio samples need to be
// sent to the renderer.
audio_renderer_.events().OnMinLeadTimeChanged =
audio_out_.events().OnMinLeadTimeChanged =
fit::bind_member(this, &AudioOutputStreamFuchsia::OnMinLeadTimeChanged);
audio_renderer_->EnableMinLeadTimeEvents(true);
audio_out_->EnableMinLeadTimeEvents(true);
// The renderer may fail initialization asynchronously, which is handled in
// OnRendererError().
......@@ -70,7 +75,7 @@ void AudioOutputStreamFuchsia::Start(AudioSourceCallback* callback) {
void AudioOutputStreamFuchsia::Stop() {
callback_ = nullptr;
reference_time_ = base::TimeTicks();
audio_renderer_->FlushNoReply();
audio_out_->PauseNoReply();
timer_.Stop();
}
......@@ -85,7 +90,7 @@ void AudioOutputStreamFuchsia::GetVolume(double* volume) {
void AudioOutputStreamFuchsia::Close() {
Stop();
audio_renderer_.Unbind();
audio_out_.Unbind();
// Signal to the manager that we're closed and can be removed. This should be
// the last call in the function as it deletes |this|.
......@@ -119,8 +124,8 @@ bool AudioOutputStreamFuchsia::InitializePayloadBuffer() {
}
payload_buffer_pos_ = 0;
audio_renderer_->SetPayloadBuffer(
zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
audio_out_->AddPayloadBuffer(
kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
return true;
}
......@@ -140,18 +145,23 @@ void AudioOutputStreamFuchsia::OnMinLeadTimeChanged(int64_t min_lead_time) {
}
void AudioOutputStreamFuchsia::OnRendererError() {
LOG(WARNING) << "AudioRenderer has failed.";
Stop();
LOG(WARNING) << "AudioOut has failed.";
ReportError();
}
void AudioOutputStreamFuchsia::ReportError() {
reference_time_ = base::TimeTicks();
timer_.Stop();
if (callback_)
callback_->OnError();
}
void AudioOutputStreamFuchsia::PumpSamples() {
DCHECK(audio_renderer_);
DCHECK(audio_out_);
// Allocate payload buffer if necessary.
if (!payload_buffer_.mapped_size() && !InitializePayloadBuffer()) {
Stop();
callback_->OnError();
ReportError();
return;
}
......@@ -186,20 +196,21 @@ void AudioOutputStreamFuchsia::PumpSamples() {
reinterpret_cast<uint8_t*>(payload_buffer_.memory()) +
payload_buffer_pos_));
fuchsia::media::AudioPacket packet;
packet.timestamp = stream_position_samples_;
fuchsia::media::StreamPacket packet;
packet.pts = stream_position_samples_;
packet.payload_buffer_id = kBufferId;
packet.payload_offset = payload_buffer_pos_;
packet.payload_size = packet_size;
packet.flags = 0;
audio_renderer_->SendPacketNoReply(std::move(packet));
audio_out_->SendPacketNoReply(std::move(packet));
stream_position_samples_ += frames_filled;
payload_buffer_pos_ =
(payload_buffer_pos_ + packet_size) % payload_buffer_.mapped_size();
if (reference_time_.is_null()) {
audio_renderer_->Play(
audio_out_->Play(
fuchsia::media::NO_TIMESTAMP, stream_position_samples_ - frames_filled,
[this](int64_t reference_time, int64_t media_time) {
if (!callback_)
......
......@@ -41,12 +41,15 @@ class AudioOutputStreamFuchsia : public AudioOutputStream {
base::TimeTicks GetCurrentStreamTime();
// Event handler for |audio_renderer_|.
// Event handler for |audio_out_|.
void OnMinLeadTimeChanged(int64_t min_lead_time);
// Error handler for |audio_renderer_|.
// Error handler for |audio_out_|.
void OnRendererError();
// Resets internal state and reports an error to |callback_|.
void ReportError();
// Requests data from AudioSourceCallback, passes it to the mixer and
// schedules |timer_| for the next call.
void PumpSamples();
......@@ -58,8 +61,7 @@ class AudioOutputStreamFuchsia : public AudioOutputStream {
AudioManagerFuchsia* manager_;
AudioParameters parameters_;
// Audio renderer connection.
fuchsia::media::AudioRenderer2Ptr audio_renderer_;
fuchsia::media::AudioOutPtr audio_out_;
// |audio_bus_| is used only in PumpSamples(). It is kept here to avoid
// reallocating the memory every time.
......
......@@ -219,6 +219,7 @@ fuchsia_sdk_fidl_pkg("media") {
sources = [
"audio.fidl",
"audio_device_enumerator.fidl",
"audio_in.fidl",
"audio_out.fidl",
"audio_renderer.fidl",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment