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 = ...@@ -28,6 +28,11 @@ constexpr base::TimeDelta kTargetWritePeriod =
// MixerOutputStreamFuchsia::Write(). // MixerOutputStreamFuchsia::Write().
constexpr int kMaxOutputBufferSizeFrames = 4096; 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 // static
std::unique_ptr<MixerOutputStream> MixerOutputStream::Create() { std::unique_ptr<MixerOutputStream> MixerOutputStream::Create() {
return std::make_unique<MixerOutputStreamFuchsia>(); return std::make_unique<MixerOutputStreamFuchsia>();
...@@ -37,7 +42,7 @@ MixerOutputStreamFuchsia::MixerOutputStreamFuchsia() = default; ...@@ -37,7 +42,7 @@ MixerOutputStreamFuchsia::MixerOutputStreamFuchsia() = default;
MixerOutputStreamFuchsia::~MixerOutputStreamFuchsia() = default; MixerOutputStreamFuchsia::~MixerOutputStreamFuchsia() = default;
bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) { bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
DCHECK(!audio_renderer_); DCHECK(!audio_out_);
DCHECK(reference_time_.is_null()); DCHECK(reference_time_.is_null());
sample_rate_ = requested_sample_rate; sample_rate_ = requested_sample_rate;
...@@ -45,12 +50,12 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) { ...@@ -45,12 +50,12 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
target_packet_size_ = ::media::AudioTimestampHelper::TimeToFrames( target_packet_size_ = ::media::AudioTimestampHelper::TimeToFrames(
kTargetWritePeriod, sample_rate_); kTargetWritePeriod, sample_rate_);
// Connect |audio_renderer_|. // Connect |audio_out_|.
fuchsia::media::AudioPtr audio_server = fuchsia::media::AudioPtr audio_server =
base::fuchsia::ComponentContext::GetDefault() base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::media::Audio>(); ->ConnectToService<fuchsia::media::Audio>();
audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest()); audio_server->CreateAudioOut(audio_out_.NewRequest());
audio_renderer_.set_error_handler( audio_out_.set_error_handler(
fit::bind_member(this, &MixerOutputStreamFuchsia::OnRendererError)); fit::bind_member(this, &MixerOutputStreamFuchsia::OnRendererError));
// Configure the renderer. // Configure the renderer.
...@@ -58,13 +63,13 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) { ...@@ -58,13 +63,13 @@ bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) {
format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT; format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
format.channels = channels_; format.channels = channels_;
format.frames_per_second = sample_rate_; 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. // 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_out_->EnableMinLeadTimeEvents(true);
audio_renderer_.events().OnMinLeadTimeChanged = audio_out_.events().OnMinLeadTimeChanged =
fit::bind_member(this, &MixerOutputStreamFuchsia::OnMinLeadTimeChanged); fit::bind_member(this, &MixerOutputStreamFuchsia::OnMinLeadTimeChanged);
return true; return true;
...@@ -93,7 +98,7 @@ int MixerOutputStreamFuchsia::OptimalWriteFramesCount() { ...@@ -93,7 +98,7 @@ int MixerOutputStreamFuchsia::OptimalWriteFramesCount() {
bool MixerOutputStreamFuchsia::Write(const float* data, bool MixerOutputStreamFuchsia::Write(const float* data,
int data_size, int data_size,
bool* out_playback_interrupted) { bool* out_playback_interrupted) {
if (!audio_renderer_) if (!audio_out_)
return false; return false;
DCHECK_EQ(data_size % channels_, 0); DCHECK_EQ(data_size % channels_, 0);
...@@ -125,12 +130,13 @@ bool MixerOutputStreamFuchsia::Write(const float* data, ...@@ -125,12 +130,13 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
data, packet_size); data, packet_size);
// Send a new packet. // Send a new packet.
fuchsia::media::AudioPacket packet; fuchsia::media::StreamPacket packet;
packet.timestamp = stream_position_samples_; packet.pts = stream_position_samples_;
packet.payload_buffer_id = kBufferId;
packet.payload_offset = payload_buffer_pos_; packet.payload_offset = payload_buffer_pos_;
packet.payload_size = packet_size; packet.payload_size = packet_size;
packet.flags = 0; packet.flags = 0;
audio_renderer_->SendPacketNoReply(std::move(packet)); audio_out_->SendPacketNoReply(std::move(packet));
// Update stream position. // Update stream position.
int frames = data_size / channels_; int frames = data_size / channels_;
...@@ -139,8 +145,8 @@ bool MixerOutputStreamFuchsia::Write(const float* data, ...@@ -139,8 +145,8 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
if (reference_time_.is_null()) { if (reference_time_.is_null()) {
reference_time_ = now + min_lead_time_; reference_time_ = now + min_lead_time_;
audio_renderer_->PlayNoReply(reference_time_.ToZxTime(), audio_out_->PlayNoReply(reference_time_.ToZxTime(),
stream_position_samples_ - frames); stream_position_samples_ - frames);
} else { } else {
// Block the thread to limit amount of buffered data. Currently // Block the thread to limit amount of buffered data. Currently
// MixerOutputStreamAlsa uses blocking Write() and StreamMixer relies on // MixerOutputStreamAlsa uses blocking Write() and StreamMixer relies on
...@@ -162,7 +168,7 @@ bool MixerOutputStreamFuchsia::Write(const float* data, ...@@ -162,7 +168,7 @@ bool MixerOutputStreamFuchsia::Write(const float* data,
void MixerOutputStreamFuchsia::Stop() { void MixerOutputStreamFuchsia::Stop() {
reference_time_ = base::TimeTicks(); reference_time_ = base::TimeTicks();
audio_renderer_.Unbind(); audio_out_.Unbind();
} }
size_t MixerOutputStreamFuchsia::GetMinBufferSize() { size_t MixerOutputStreamFuchsia::GetMinBufferSize() {
...@@ -184,8 +190,8 @@ bool MixerOutputStreamFuchsia::InitializePayloadBuffer() { ...@@ -184,8 +190,8 @@ bool MixerOutputStreamFuchsia::InitializePayloadBuffer() {
} }
payload_buffer_pos_ = 0; payload_buffer_pos_ = 0;
audio_renderer_->SetPayloadBuffer( audio_out_->AddPayloadBuffer(
zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
return true; return true;
} }
......
...@@ -37,7 +37,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream { ...@@ -37,7 +37,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream {
base::TimeTicks GetCurrentStreamTime(); base::TimeTicks GetCurrentStreamTime();
// Event handlers for |audio_renderer_|. // Event handlers for |audio_out_|.
void OnRendererError(); void OnRendererError();
void OnMinLeadTimeChanged(int64_t min_lead_time); void OnMinLeadTimeChanged(int64_t min_lead_time);
...@@ -48,7 +48,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream { ...@@ -48,7 +48,7 @@ class MixerOutputStreamFuchsia : public MixerOutputStream {
int target_packet_size_ = 0; int target_packet_size_ = 0;
// Audio renderer connection. // Audio renderer connection.
fuchsia::media::AudioRenderer2Ptr audio_renderer_; fuchsia::media::AudioOutPtr audio_out_;
base::SharedMemory payload_buffer_; base::SharedMemory payload_buffer_;
size_t payload_buffer_pos_ = 0; size_t payload_buffer_pos_ = 0;
......
...@@ -98,13 +98,7 @@ TEST_F(AudioOutputTest, StopTwice) { ...@@ -98,13 +98,7 @@ TEST_F(AudioOutputTest, StopTwice) {
} }
// This test produces actual audio for .25 seconds on the default device. // This test produces actual audio for .25 seconds on the default device.
#if defined(OS_FUCHSIA) TEST_F(AudioOutputTest, Play200HzTone) {
// 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) {
ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices());
stream_params_ = stream_params_ =
......
...@@ -13,6 +13,11 @@ ...@@ -13,6 +13,11 @@
namespace media { 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( AudioOutputStreamFuchsia::AudioOutputStreamFuchsia(
AudioManagerFuchsia* manager, AudioManagerFuchsia* manager,
const AudioParameters& parameters) const AudioParameters& parameters)
...@@ -22,36 +27,36 @@ AudioOutputStreamFuchsia::AudioOutputStreamFuchsia( ...@@ -22,36 +27,36 @@ AudioOutputStreamFuchsia::AudioOutputStreamFuchsia(
AudioOutputStreamFuchsia::~AudioOutputStreamFuchsia() { AudioOutputStreamFuchsia::~AudioOutputStreamFuchsia() {
// Close() must be called first. // Close() must be called first.
DCHECK(!audio_renderer_); DCHECK(!audio_out_);
} }
bool AudioOutputStreamFuchsia::Open() { 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 = fuchsia::media::AudioPtr audio_server =
base::fuchsia::ComponentContext::GetDefault() base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::media::Audio>(); ->ConnectToService<fuchsia::media::Audio>();
audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest()); audio_server->CreateAudioOut(audio_out_.NewRequest());
audio_renderer_.set_error_handler( audio_out_.set_error_handler(
fit::bind_member(this, &AudioOutputStreamFuchsia::OnRendererError)); 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; fuchsia::media::AudioStreamType format;
format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT; format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
format.channels = parameters_.channels(); format.channels = parameters_.channels();
format.frames_per_second = parameters_.sample_rate(); 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. // 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 // Setup OnMinLeadTimeChanged event listener. This event is used to get
// |min_lead_time_|, which indicates how far ahead audio samples need to be // |min_lead_time_|, which indicates how far ahead audio samples need to be
// sent to the renderer. // sent to the renderer.
audio_renderer_.events().OnMinLeadTimeChanged = audio_out_.events().OnMinLeadTimeChanged =
fit::bind_member(this, &AudioOutputStreamFuchsia::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 // The renderer may fail initialization asynchronously, which is handled in
// OnRendererError(). // OnRendererError().
...@@ -70,7 +75,7 @@ void AudioOutputStreamFuchsia::Start(AudioSourceCallback* callback) { ...@@ -70,7 +75,7 @@ void AudioOutputStreamFuchsia::Start(AudioSourceCallback* callback) {
void AudioOutputStreamFuchsia::Stop() { void AudioOutputStreamFuchsia::Stop() {
callback_ = nullptr; callback_ = nullptr;
reference_time_ = base::TimeTicks(); reference_time_ = base::TimeTicks();
audio_renderer_->FlushNoReply(); audio_out_->PauseNoReply();
timer_.Stop(); timer_.Stop();
} }
...@@ -85,7 +90,7 @@ void AudioOutputStreamFuchsia::GetVolume(double* volume) { ...@@ -85,7 +90,7 @@ void AudioOutputStreamFuchsia::GetVolume(double* volume) {
void AudioOutputStreamFuchsia::Close() { void AudioOutputStreamFuchsia::Close() {
Stop(); Stop();
audio_renderer_.Unbind(); audio_out_.Unbind();
// Signal to the manager that we're closed and can be removed. This should be // 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|. // the last call in the function as it deletes |this|.
...@@ -119,8 +124,8 @@ bool AudioOutputStreamFuchsia::InitializePayloadBuffer() { ...@@ -119,8 +124,8 @@ bool AudioOutputStreamFuchsia::InitializePayloadBuffer() {
} }
payload_buffer_pos_ = 0; payload_buffer_pos_ = 0;
audio_renderer_->SetPayloadBuffer( audio_out_->AddPayloadBuffer(
zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle()));
return true; return true;
} }
...@@ -140,18 +145,23 @@ void AudioOutputStreamFuchsia::OnMinLeadTimeChanged(int64_t min_lead_time) { ...@@ -140,18 +145,23 @@ void AudioOutputStreamFuchsia::OnMinLeadTimeChanged(int64_t min_lead_time) {
} }
void AudioOutputStreamFuchsia::OnRendererError() { void AudioOutputStreamFuchsia::OnRendererError() {
LOG(WARNING) << "AudioRenderer has failed."; LOG(WARNING) << "AudioOut has failed.";
Stop(); ReportError();
callback_->OnError(); }
void AudioOutputStreamFuchsia::ReportError() {
reference_time_ = base::TimeTicks();
timer_.Stop();
if (callback_)
callback_->OnError();
} }
void AudioOutputStreamFuchsia::PumpSamples() { void AudioOutputStreamFuchsia::PumpSamples() {
DCHECK(audio_renderer_); DCHECK(audio_out_);
// Allocate payload buffer if necessary. // Allocate payload buffer if necessary.
if (!payload_buffer_.mapped_size() && !InitializePayloadBuffer()) { if (!payload_buffer_.mapped_size() && !InitializePayloadBuffer()) {
Stop(); ReportError();
callback_->OnError();
return; return;
} }
...@@ -186,20 +196,21 @@ void AudioOutputStreamFuchsia::PumpSamples() { ...@@ -186,20 +196,21 @@ void AudioOutputStreamFuchsia::PumpSamples() {
reinterpret_cast<uint8_t*>(payload_buffer_.memory()) + reinterpret_cast<uint8_t*>(payload_buffer_.memory()) +
payload_buffer_pos_)); payload_buffer_pos_));
fuchsia::media::AudioPacket packet; fuchsia::media::StreamPacket packet;
packet.timestamp = stream_position_samples_; packet.pts = stream_position_samples_;
packet.payload_buffer_id = kBufferId;
packet.payload_offset = payload_buffer_pos_; packet.payload_offset = payload_buffer_pos_;
packet.payload_size = packet_size; packet.payload_size = packet_size;
packet.flags = 0; packet.flags = 0;
audio_renderer_->SendPacketNoReply(std::move(packet)); audio_out_->SendPacketNoReply(std::move(packet));
stream_position_samples_ += frames_filled; stream_position_samples_ += frames_filled;
payload_buffer_pos_ = payload_buffer_pos_ =
(payload_buffer_pos_ + packet_size) % payload_buffer_.mapped_size(); (payload_buffer_pos_ + packet_size) % payload_buffer_.mapped_size();
if (reference_time_.is_null()) { if (reference_time_.is_null()) {
audio_renderer_->Play( audio_out_->Play(
fuchsia::media::NO_TIMESTAMP, stream_position_samples_ - frames_filled, fuchsia::media::NO_TIMESTAMP, stream_position_samples_ - frames_filled,
[this](int64_t reference_time, int64_t media_time) { [this](int64_t reference_time, int64_t media_time) {
if (!callback_) if (!callback_)
......
...@@ -41,12 +41,15 @@ class AudioOutputStreamFuchsia : public AudioOutputStream { ...@@ -41,12 +41,15 @@ class AudioOutputStreamFuchsia : public AudioOutputStream {
base::TimeTicks GetCurrentStreamTime(); base::TimeTicks GetCurrentStreamTime();
// Event handler for |audio_renderer_|. // Event handler for |audio_out_|.
void OnMinLeadTimeChanged(int64_t min_lead_time); void OnMinLeadTimeChanged(int64_t min_lead_time);
// Error handler for |audio_renderer_|. // Error handler for |audio_out_|.
void OnRendererError(); void OnRendererError();
// Resets internal state and reports an error to |callback_|.
void ReportError();
// Requests data from AudioSourceCallback, passes it to the mixer and // Requests data from AudioSourceCallback, passes it to the mixer and
// schedules |timer_| for the next call. // schedules |timer_| for the next call.
void PumpSamples(); void PumpSamples();
...@@ -58,8 +61,7 @@ class AudioOutputStreamFuchsia : public AudioOutputStream { ...@@ -58,8 +61,7 @@ class AudioOutputStreamFuchsia : public AudioOutputStream {
AudioManagerFuchsia* manager_; AudioManagerFuchsia* manager_;
AudioParameters parameters_; AudioParameters parameters_;
// Audio renderer connection. fuchsia::media::AudioOutPtr audio_out_;
fuchsia::media::AudioRenderer2Ptr audio_renderer_;
// |audio_bus_| is used only in PumpSamples(). It is kept here to avoid // |audio_bus_| is used only in PumpSamples(). It is kept here to avoid
// reallocating the memory every time. // reallocating the memory every time.
......
...@@ -219,6 +219,7 @@ fuchsia_sdk_fidl_pkg("media") { ...@@ -219,6 +219,7 @@ fuchsia_sdk_fidl_pkg("media") {
sources = [ sources = [
"audio.fidl", "audio.fidl",
"audio_device_enumerator.fidl",
"audio_in.fidl", "audio_in.fidl",
"audio_out.fidl", "audio_out.fidl",
"audio_renderer.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