Commit a1ad2994 authored by alokp's avatar alokp Committed by Commit bot

[chromecast] Simplify CastAudioOutputStream.

https://codereview.chromium.org/1908423006/ makes CastAudioManager
run on CMA thread. Now there is no need to post tasks when using
CMA backend in CastAudioAoutputStream.

BUG=594234

Review URL: https://codereview.chromium.org/1913973003

Cr-Commit-Position: refs/heads/master@{#389813}
parent c2e43c5c
...@@ -35,8 +35,7 @@ class CastAudioManager : public ::media::AudioManagerBase { ...@@ -35,8 +35,7 @@ class CastAudioManager : public ::media::AudioManagerBase {
::media::AudioParameters GetInputStreamParameters( ::media::AudioParameters GetInputStreamParameters(
const std::string& device_id) override; const std::string& device_id) override;
// This must be called on cast media thread. // This must be called on audio thread.
// See chromecast::media::MediaMessageLoop.
virtual std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend( virtual std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend(
const MediaPipelineDeviceParams& params); const MediaPipelineDeviceParams& params);
......
...@@ -4,88 +4,42 @@ ...@@ -4,88 +4,42 @@
#include "chromecast/media/audio/cast_audio_output_stream.h" #include "chromecast/media/audio/cast_audio_output_stream.h"
#include <stdint.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_checker.h"
#include "chromecast/base/metrics/cast_metrics_helper.h" #include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/base/task_runner_impl.h" #include "chromecast/base/task_runner_impl.h"
#include "chromecast/media/audio/cast_audio_manager.h" #include "chromecast/media/audio/cast_audio_manager.h"
#include "chromecast/media/base/media_message_loop.h"
#include "chromecast/media/cma/base/decoder_buffer_adapter.h" #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
#include "chromecast/public/media/decoder_config.h" #include "chromecast/public/media/decoder_config.h"
#include "chromecast/public/media/decrypt_context.h"
#include "chromecast/public/media/media_pipeline_backend.h" #include "chromecast/public/media/media_pipeline_backend.h"
#include "chromecast/public/media/media_pipeline_device_params.h" #include "chromecast/public/media/media_pipeline_device_params.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/decoder_buffer.h" #include "media/base/decoder_buffer.h"
namespace chromecast {
namespace media {
namespace { namespace {
const int kMaxQueuedDataMs = 1000; const int kMaxQueuedDataMs = 1000;
MediaPipelineBackend::AudioDecoder* InitializeBackend(
const ::media::AudioParameters& audio_params,
MediaPipelineBackend* backend,
MediaPipelineBackend::Decoder::Delegate* delegate) {
DCHECK(backend);
DCHECK(delegate);
MediaPipelineBackend::AudioDecoder* decoder = backend->CreateAudioDecoder();
if (!decoder)
return nullptr;
decoder->SetDelegate(delegate);
AudioConfig audio_config;
audio_config.codec = kCodecPCM;
audio_config.sample_format = kSampleFormatS16;
audio_config.bytes_per_channel = audio_params.bits_per_sample() / 8;
audio_config.channel_number = audio_params.channels();
audio_config.samples_per_second = audio_params.sample_rate();
if (!decoder->SetConfig(audio_config))
return nullptr;
if (!backend->Initialize())
return nullptr;
return decoder;
}
} // namespace } // namespace
// Backend represents a MediaPipelineBackend adapter that runs on cast namespace chromecast {
// media thread (media::MediaMessageLoop::GetTaskRunner). namespace media {
// It can be created and destroyed on any thread, but all other member functions
// must be called on a single thread. // Backend represents a MediaPipelineBackend adapter.
// It can be created and destroyed on any thread,
// but all other member functions must be called on a single thread.
class CastAudioOutputStream::Backend class CastAudioOutputStream::Backend
: public MediaPipelineBackend::Decoder::Delegate { : public MediaPipelineBackend::Decoder::Delegate {
public: public:
using PushBufferCompletionCallback = base::Callback<void(bool)>; using PushBufferCompletionCallback = base::Callback<void(bool)>;
Backend(const ::media::AudioParameters& audio_params) Backend() : decoder_(nullptr), first_start_(true), error_(false) {
: audio_params_(audio_params),
decoder_(nullptr),
first_start_(true),
error_(false),
weak_factory_(this) {
thread_checker_.DetachFromThread(); thread_checker_.DetachFromThread();
} }
~Backend() override {} ~Backend() override {}
void Open(CastAudioManager* audio_manager, bool Open(const ::media::AudioParameters& audio_params,
bool* success, CastAudioManager* audio_manager) {
base::WaitableEvent* completion_event) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(backend_ == nullptr);
DCHECK(audio_manager); DCHECK(audio_manager);
DCHECK(success); DCHECK(backend_ == nullptr);
DCHECK(completion_event);
backend_task_runner_.reset(new TaskRunnerImpl()); backend_task_runner_.reset(new TaskRunnerImpl());
MediaPipelineDeviceParams device_params( MediaPipelineDeviceParams device_params(
...@@ -93,10 +47,24 @@ class CastAudioOutputStream::Backend ...@@ -93,10 +47,24 @@ class CastAudioOutputStream::Backend
MediaPipelineDeviceParams::kAudioStreamSoundEffects, MediaPipelineDeviceParams::kAudioStreamSoundEffects,
backend_task_runner_.get()); backend_task_runner_.get());
backend_ = audio_manager->CreateMediaPipelineBackend(device_params); backend_ = audio_manager->CreateMediaPipelineBackend(device_params);
if (backend_) if (!backend_)
decoder_ = InitializeBackend(audio_params_, backend_.get(), this); return false;
*success = decoder_ != nullptr;
completion_event->Signal(); decoder_ = backend_->CreateAudioDecoder();
if (!decoder_)
return false;
decoder_->SetDelegate(this);
AudioConfig audio_config;
audio_config.codec = kCodecPCM;
audio_config.sample_format = kSampleFormatS16;
audio_config.bytes_per_channel = audio_params.bits_per_sample() / 8;
audio_config.channel_number = audio_params.channels();
audio_config.samples_per_second = audio_params.sample_rate();
if (!decoder_->SetConfig(audio_config))
return false;
return backend_->Initialize();
} }
void Close() { void Close() {
...@@ -139,7 +107,6 @@ class CastAudioOutputStream::Backend ...@@ -139,7 +107,6 @@ class CastAudioOutputStream::Backend
} }
backend_buffer_ = decoder_buffer; backend_buffer_ = decoder_buffer;
completion_cb_ = completion_cb; completion_cb_ = completion_cb;
BufferStatus status = decoder_->PushBuffer(backend_buffer_.get()); BufferStatus status = decoder_->PushBuffer(backend_buffer_.get());
if (status != MediaPipelineBackend::kBufferPending) if (status != MediaPipelineBackend::kBufferPending)
...@@ -152,6 +119,7 @@ class CastAudioOutputStream::Backend ...@@ -152,6 +119,7 @@ class CastAudioOutputStream::Backend
decoder_->SetVolume(volume); decoder_->SetVolume(volume);
} }
private:
// MediaPipelineBackend::Decoder::Delegate implementation // MediaPipelineBackend::Decoder::Delegate implementation
void OnPushBufferComplete(BufferStatus status) override { void OnPushBufferComplete(BufferStatus status) override {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
...@@ -168,6 +136,7 @@ class CastAudioOutputStream::Backend ...@@ -168,6 +136,7 @@ class CastAudioOutputStream::Backend
void OnEndOfStream() override {} void OnEndOfStream() override {}
void OnDecoderError() override { void OnDecoderError() override {
DCHECK(thread_checker_.CalledOnValidThread());
error_ = true; error_ = true;
if (!completion_cb_.is_null()) if (!completion_cb_.is_null())
OnPushBufferComplete(MediaPipelineBackend::kBufferFailed); OnPushBufferComplete(MediaPipelineBackend::kBufferFailed);
...@@ -179,12 +148,6 @@ class CastAudioOutputStream::Backend ...@@ -179,12 +148,6 @@ class CastAudioOutputStream::Backend
void OnVideoResolutionChanged(const Size& size) override {} void OnVideoResolutionChanged(const Size& size) override {}
base::WeakPtr<CastAudioOutputStream::Backend> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
const ::media::AudioParameters audio_params_;
std::unique_ptr<MediaPipelineBackend> backend_; std::unique_ptr<MediaPipelineBackend> backend_;
std::unique_ptr<TaskRunnerImpl> backend_task_runner_; std::unique_ptr<TaskRunnerImpl> backend_task_runner_;
MediaPipelineBackend::AudioDecoder* decoder_; MediaPipelineBackend::AudioDecoder* decoder_;
...@@ -193,7 +156,6 @@ class CastAudioOutputStream::Backend ...@@ -193,7 +156,6 @@ class CastAudioOutputStream::Backend
bool error_; bool error_;
scoped_refptr<DecoderBufferBase> backend_buffer_; scoped_refptr<DecoderBufferBase> backend_buffer_;
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
base::WeakPtrFactory<CastAudioOutputStream::Backend> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Backend); DISALLOW_COPY_AND_ASSIGN(Backend);
}; };
...@@ -206,22 +168,19 @@ CastAudioOutputStream::CastAudioOutputStream( ...@@ -206,22 +168,19 @@ CastAudioOutputStream::CastAudioOutputStream(
audio_manager_(audio_manager), audio_manager_(audio_manager),
volume_(1.0), volume_(1.0),
source_callback_(nullptr), source_callback_(nullptr),
backend_(new Backend(audio_params)), backend_(new Backend()),
buffer_duration_(audio_params.GetBufferDuration()), buffer_duration_(audio_params.GetBufferDuration()),
push_in_progress_(false), push_in_progress_(false),
audio_task_runner_(audio_manager->GetTaskRunner()),
backend_task_runner_(media::MediaMessageLoop::GetTaskRunner()),
weak_factory_(this) { weak_factory_(this) {
VLOG(1) << "CastAudioOutputStream " << this << " created with " VLOG(1) << "CastAudioOutputStream " << this << " created with "
<< audio_params_.AsHumanReadableString(); << audio_params_.AsHumanReadableString();
} }
CastAudioOutputStream::~CastAudioOutputStream() { CastAudioOutputStream::~CastAudioOutputStream() {
backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
} }
bool CastAudioOutputStream::Open() { bool CastAudioOutputStream::Open() {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
::media::AudioParameters::Format format = audio_params_.format(); ::media::AudioParameters::Format format = audio_params_.format();
DCHECK((format == ::media::AudioParameters::AUDIO_PCM_LINEAR) || DCHECK((format == ::media::AudioParameters::AUDIO_PCM_LINEAR) ||
...@@ -236,21 +195,11 @@ bool CastAudioOutputStream::Open() { ...@@ -236,21 +195,11 @@ bool CastAudioOutputStream::Open() {
DCHECK_GE(audio_params_.channels(), 1); DCHECK_GE(audio_params_.channels(), 1);
DCHECK_LE(audio_params_.channels(), 2); DCHECK_LE(audio_params_.channels(), 2);
{ if (!backend_->Open(audio_params_, audio_manager_)) {
// Wait until the backend has initialized so that the outcome can be LOG(WARNING) << "Failed to create media pipeline backend.";
// communicated to the client. return false;
bool success = false;
base::WaitableEvent completion_event(false, false);
backend_task_runner_->PostTask(
FROM_HERE, base::Bind(&Backend::Open, backend_->GetWeakPtr(),
audio_manager_, &success, &completion_event));
completion_event.Wait();
if (!success) {
LOG(WARNING) << "Failed to create media pipeline backend.";
return false;
}
} }
audio_bus_ = ::media::AudioBus::Create(audio_params_); audio_bus_ = ::media::AudioBus::Create(audio_params_);
decoder_buffer_ = new DecoderBufferAdapter( decoder_buffer_ = new DecoderBufferAdapter(
new ::media::DecoderBuffer(audio_params_.GetBytesPerBuffer())); new ::media::DecoderBuffer(audio_params_.GetBytesPerBuffer()));
...@@ -260,27 +209,27 @@ bool CastAudioOutputStream::Open() { ...@@ -260,27 +209,27 @@ bool CastAudioOutputStream::Open() {
} }
void CastAudioOutputStream::Close() { void CastAudioOutputStream::Close() {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
VLOG(1) << __FUNCTION__ << " : " << this; VLOG(1) << __FUNCTION__ << " : " << this;
backend_task_runner_->PostTaskAndReply(
FROM_HERE, base::Bind(&Backend::Close, backend_->GetWeakPtr()), backend_->Close();
base::Bind(&CastAudioOutputStream::OnClosed, base::Unretained(this))); // 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".
audio_manager_->ReleaseOutputStream(this);
} }
void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) { void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
DCHECK(source_callback); DCHECK(source_callback);
source_callback_ = source_callback; source_callback_ = source_callback;
backend_task_runner_->PostTask( backend_->Start();
FROM_HERE, base::Bind(&Backend::Start, backend_->GetWeakPtr()));
next_push_time_ = base::TimeTicks::Now(); next_push_time_ = base::TimeTicks::Now();
if (!push_in_progress_) { if (!push_in_progress_) {
audio_task_runner_->PostTask(FROM_HERE, audio_manager_->GetTaskRunner()->PostTask(
base::Bind(&CastAudioOutputStream::PushBuffer, FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
push_in_progress_ = true; push_in_progress_ = true;
} }
...@@ -288,39 +237,27 @@ void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) { ...@@ -288,39 +237,27 @@ void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) {
} }
void CastAudioOutputStream::Stop() { void CastAudioOutputStream::Stop() {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
source_callback_ = nullptr; source_callback_ = nullptr;
backend_task_runner_->PostTask( backend_->Stop();
FROM_HERE, base::Bind(&Backend::Stop, backend_->GetWeakPtr()));
} }
void CastAudioOutputStream::SetVolume(double volume) { void CastAudioOutputStream::SetVolume(double volume) {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
volume_ = volume; volume_ = volume;
backend_task_runner_->PostTask( backend_->SetVolume(volume);
FROM_HERE, base::Bind(&Backend::SetVolume,
backend_->GetWeakPtr(), volume));
} }
void CastAudioOutputStream::GetVolume(double* volume) { void CastAudioOutputStream::GetVolume(double* volume) {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
*volume = volume_; *volume = volume_;
} }
void CastAudioOutputStream::OnClosed() {
DCHECK(audio_task_runner_->BelongsToCurrentThread());
VLOG(1) << __FUNCTION__ << " : " << this;
// 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".
audio_manager_->ReleaseOutputStream(this);
}
void CastAudioOutputStream::PushBuffer() { void CastAudioOutputStream::PushBuffer() {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
DCHECK(push_in_progress_); DCHECK(push_in_progress_);
if (!source_callback_) { if (!source_callback_) {
...@@ -343,18 +280,13 @@ void CastAudioOutputStream::PushBuffer() { ...@@ -343,18 +280,13 @@ void CastAudioOutputStream::PushBuffer() {
audio_bus_->ToInterleaved(frame_count, audio_params_.bits_per_sample() / 8, audio_bus_->ToInterleaved(frame_count, audio_params_.bits_per_sample() / 8,
decoder_buffer_->writable_data()); decoder_buffer_->writable_data());
auto completion_cb = ::media::BindToCurrentLoop( auto completion_cb = base::Bind(&CastAudioOutputStream::OnPushBufferComplete,
base::Bind(&CastAudioOutputStream::OnPushBufferComplete, weak_factory_.GetWeakPtr());
weak_factory_.GetWeakPtr())); backend_->PushBuffer(decoder_buffer_, completion_cb);
backend_task_runner_->PostTask(FROM_HERE,
base::Bind(&Backend::PushBuffer,
backend_->GetWeakPtr(),
decoder_buffer_,
completion_cb));
} }
void CastAudioOutputStream::OnPushBufferComplete(bool success) { void CastAudioOutputStream::OnPushBufferComplete(bool success) {
DCHECK(audio_task_runner_->BelongsToCurrentThread()); DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
DCHECK(push_in_progress_); DCHECK(push_in_progress_);
push_in_progress_ = false; push_in_progress_ = false;
...@@ -375,10 +307,9 @@ void CastAudioOutputStream::OnPushBufferComplete(bool success) { ...@@ -375,10 +307,9 @@ void CastAudioOutputStream::OnPushBufferComplete(bool success) {
base::TimeDelta::FromMilliseconds(kMaxQueuedDataMs); base::TimeDelta::FromMilliseconds(kMaxQueuedDataMs);
delay = std::max(delay, base::TimeDelta()); delay = std::max(delay, base::TimeDelta());
audio_task_runner_->PostDelayedTask( audio_manager_->GetTaskRunner()->PostDelayedTask(
FROM_HERE, FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer,
base::Bind(&CastAudioOutputStream::PushBuffer, weak_factory_.GetWeakPtr()),
weak_factory_.GetWeakPtr()),
delay); delay);
push_in_progress_ = true; push_in_progress_ = true;
} }
......
...@@ -11,10 +11,6 @@ ...@@ -11,10 +11,6 @@
#include "media/audio/audio_io.h" #include "media/audio/audio_io.h"
#include "media/base/audio_parameters.h" #include "media/base/audio_parameters.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace chromecast { namespace chromecast {
namespace media { namespace media {
...@@ -38,7 +34,6 @@ class CastAudioOutputStream : public ::media::AudioOutputStream { ...@@ -38,7 +34,6 @@ class CastAudioOutputStream : public ::media::AudioOutputStream {
private: private:
class Backend; class Backend;
void OnClosed();
void PushBuffer(); void PushBuffer();
void OnPushBufferComplete(bool success); void OnPushBufferComplete(bool success);
...@@ -54,9 +49,6 @@ class CastAudioOutputStream : public ::media::AudioOutputStream { ...@@ -54,9 +49,6 @@ class CastAudioOutputStream : public ::media::AudioOutputStream {
bool push_in_progress_; bool push_in_progress_;
base::TimeTicks next_push_time_; base::TimeTicks next_push_time_;
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_;
base::WeakPtrFactory<CastAudioOutputStream> weak_factory_; base::WeakPtrFactory<CastAudioOutputStream> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CastAudioOutputStream); DISALLOW_COPY_AND_ASSIGN(CastAudioOutputStream);
......
...@@ -4,22 +4,10 @@ ...@@ -4,22 +4,10 @@
#include "chromecast/media/audio/cast_audio_output_stream.h" #include "chromecast/media/audio/cast_audio_output_stream.h"
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/thread_task_runner_handle.h"
#include "chromecast/base/metrics/cast_metrics_test_helper.h" #include "chromecast/base/metrics/cast_metrics_test_helper.h"
#include "chromecast/media/audio/cast_audio_manager.h" #include "chromecast/media/audio/cast_audio_manager.h"
#include "chromecast/media/base/media_message_loop.h"
#include "chromecast/media/cma/backend/media_pipeline_backend_default.h"
#include "chromecast/public/media/cast_decoder_buffer.h" #include "chromecast/public/media/cast_decoder_buffer.h"
#include "chromecast/public/media/decoder_config.h"
#include "chromecast/public/media/decrypt_context.h"
#include "chromecast/public/media/media_pipeline_backend.h" #include "chromecast/public/media/media_pipeline_backend.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -28,14 +16,6 @@ namespace media { ...@@ -28,14 +16,6 @@ namespace media {
namespace { namespace {
const char kDefaultDeviceId[] = ""; const char kDefaultDeviceId[] = "";
void RunUntilIdle(base::TaskRunner* task_runner) {
base::WaitableEvent completion_event(false, false);
task_runner->PostTask(FROM_HERE,
base::Bind(&base::WaitableEvent::Signal,
base::Unretained(&completion_event)));
completion_event.Wait();
}
class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder { class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
public: public:
enum PipelineStatus { enum PipelineStatus {
...@@ -194,7 +174,7 @@ class FakeAudioManager : public CastAudioManager { ...@@ -194,7 +174,7 @@ class FakeAudioManager : public CastAudioManager {
// CastAudioManager overrides. // CastAudioManager overrides.
std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend( std::unique_ptr<MediaPipelineBackend> CreateMediaPipelineBackend(
const MediaPipelineDeviceParams& params) override { const MediaPipelineDeviceParams& params) override {
DCHECK(media::MediaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); DCHECK(GetTaskRunner()->BelongsToCurrentThread());
DCHECK(!media_pipeline_backend_); DCHECK(!media_pipeline_backend_);
std::unique_ptr<FakeMediaPipelineBackend> backend( std::unique_ptr<FakeMediaPipelineBackend> backend(
...@@ -233,10 +213,7 @@ class CastAudioOutputStreamTest : public ::testing::Test { ...@@ -233,10 +213,7 @@ class CastAudioOutputStreamTest : public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
metrics::InitializeMetricsHelperForTesting(); metrics::InitializeMetricsHelperForTesting();
audio_manager_.reset(new FakeAudioManager(message_loop_.task_runner()));
audio_task_runner_ = base::ThreadTaskRunnerHandle::Get();
backend_task_runner_ = media::MediaMessageLoop::GetTaskRunner();
audio_manager_.reset(new FakeAudioManager(audio_task_runner_));
} }
void TearDown() override { void TearDown() override {
...@@ -257,60 +234,14 @@ class CastAudioOutputStreamTest : public ::testing::Test { ...@@ -257,60 +234,14 @@ class CastAudioOutputStreamTest : public ::testing::Test {
return (backend ? backend->decoder() : nullptr); return (backend ? backend->decoder() : nullptr);
} }
// Synchronous utility functions.
::media::AudioOutputStream* CreateStream() { ::media::AudioOutputStream* CreateStream() {
return audio_manager_->MakeAudioOutputStream(GetAudioParams(), return audio_manager_->MakeAudioOutputStream(GetAudioParams(),
kDefaultDeviceId); kDefaultDeviceId);
} }
bool OpenStream(::media::AudioOutputStream* stream) {
bool success = stream->Open();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
return success;
}
void CloseStream(::media::AudioOutputStream* stream) {
stream->Close();
RunUntilIdle(backend_task_runner_.get());
// Backend task runner may have posted more tasks to the audio task runner.
// So we need to drain it once more.
message_loop_.RunUntilIdle();
}
void StartStream(
::media::AudioOutputStream* stream,
::media::AudioOutputStream::AudioSourceCallback* source_callback) {
stream->Start(source_callback);
// Drain the audio task runner so that tasks posted by
// media::AudioOutputStream::Start are run as well.
message_loop_.RunUntilIdle();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
// Drain the audio task runner again to run the tasks posted by the
// backend on audio task runner.
message_loop_.RunUntilIdle();
}
void StopStream(::media::AudioOutputStream* stream) {
stream->Stop();
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
}
void SetStreamVolume(::media::AudioOutputStream* stream, double volume) {
stream->SetVolume(volume);
// Drain the backend task runner so that appropriate states are set on
// the backend pipeline devices.
RunUntilIdle(backend_task_runner_.get());
}
double GetStreamVolume(::media::AudioOutputStream* stream) {
double volume = 0.0;
stream->GetVolume(&volume);
// No need to drain the backend task runner because getting the volume
// does not involve posting any task to the backend.
return volume;
}
void RunAudioLoopFor(int frames) { // Runs the messsage loop for duration equivalent to the given number of
// audio |frames|.
void RunMessageLoopFor(int frames) {
::media::AudioParameters audio_params = GetAudioParams(); ::media::AudioParameters audio_params = GetAudioParams();
base::TimeDelta duration = audio_params.GetBufferDuration() * frames; base::TimeDelta duration = audio_params.GetBufferDuration() * frames;
...@@ -322,9 +253,6 @@ class CastAudioOutputStreamTest : public ::testing::Test { ...@@ -322,9 +253,6 @@ class CastAudioOutputStreamTest : public ::testing::Test {
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
std::unique_ptr<FakeAudioManager> audio_manager_; std::unique_ptr<FakeAudioManager> audio_manager_;
scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_;
// AudioParameters used to create AudioOutputStream. // AudioParameters used to create AudioOutputStream.
// Tests can modify these parameters before calling CreateStream. // Tests can modify these parameters before calling CreateStream.
::media::AudioParameters::Format format_; ::media::AudioParameters::Format format_;
...@@ -342,7 +270,7 @@ TEST_F(CastAudioOutputStreamTest, Format) { ...@@ -342,7 +270,7 @@ TEST_F(CastAudioOutputStreamTest, Format) {
format_ = format[i]; format_ = format[i];
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -351,7 +279,7 @@ TEST_F(CastAudioOutputStreamTest, Format) { ...@@ -351,7 +279,7 @@ TEST_F(CastAudioOutputStreamTest, Format) {
EXPECT_EQ(kSampleFormatS16, audio_config.sample_format); EXPECT_EQ(kSampleFormatS16, audio_config.sample_format);
EXPECT_FALSE(audio_config.encryption_scheme.is_encrypted()); EXPECT_FALSE(audio_config.encryption_scheme.is_encrypted());
CloseStream(stream); stream->Close();
} }
} }
...@@ -362,7 +290,7 @@ TEST_F(CastAudioOutputStreamTest, ChannelLayout) { ...@@ -362,7 +290,7 @@ TEST_F(CastAudioOutputStreamTest, ChannelLayout) {
channel_layout_ = layout[i]; channel_layout_ = layout[i];
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -370,7 +298,7 @@ TEST_F(CastAudioOutputStreamTest, ChannelLayout) { ...@@ -370,7 +298,7 @@ TEST_F(CastAudioOutputStreamTest, ChannelLayout) {
EXPECT_EQ(::media::ChannelLayoutToChannelCount(channel_layout_), EXPECT_EQ(::media::ChannelLayoutToChannelCount(channel_layout_),
audio_config.channel_number); audio_config.channel_number);
CloseStream(stream); stream->Close();
} }
} }
...@@ -378,28 +306,28 @@ TEST_F(CastAudioOutputStreamTest, SampleRate) { ...@@ -378,28 +306,28 @@ TEST_F(CastAudioOutputStreamTest, SampleRate) {
sample_rate_ = ::media::AudioParameters::kAudioCDSampleRate; sample_rate_ = ::media::AudioParameters::kAudioCDSampleRate;
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
const AudioConfig& audio_config = audio_decoder->config(); const AudioConfig& audio_config = audio_decoder->config();
EXPECT_EQ(sample_rate_, audio_config.samples_per_second); EXPECT_EQ(sample_rate_, audio_config.samples_per_second);
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, BitsPerSample) { TEST_F(CastAudioOutputStreamTest, BitsPerSample) {
bits_per_sample_ = 16; bits_per_sample_ = 16;
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
const AudioConfig& audio_config = audio_decoder->config(); const AudioConfig& audio_config = audio_decoder->config();
EXPECT_EQ(bits_per_sample_ / 8, audio_config.bytes_per_channel); EXPECT_EQ(bits_per_sample_ / 8, audio_config.bytes_per_channel);
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, DeviceState) { TEST_F(CastAudioOutputStreamTest, DeviceState) {
...@@ -407,7 +335,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceState) { ...@@ -407,7 +335,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceState) {
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_FALSE(GetAudio()); EXPECT_FALSE(GetAudio());
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
FakeMediaPipelineBackend* backend = GetBackend(); FakeMediaPipelineBackend* backend = GetBackend();
...@@ -416,20 +344,20 @@ TEST_F(CastAudioOutputStreamTest, DeviceState) { ...@@ -416,20 +344,20 @@ TEST_F(CastAudioOutputStreamTest, DeviceState) {
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
StartStream(stream, source_callback.get()); stream->Start(source_callback.get());
EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, backend->state()); EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, backend->state());
StopStream(stream); stream->Stop();
EXPECT_EQ(FakeMediaPipelineBackend::kStatePaused, backend->state()); EXPECT_EQ(FakeMediaPipelineBackend::kStatePaused, backend->state());
CloseStream(stream); stream->Close();
EXPECT_FALSE(GetAudio()); EXPECT_FALSE(GetAudio());
} }
TEST_F(CastAudioOutputStreamTest, PushFrame) { TEST_F(CastAudioOutputStreamTest, PushFrame) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -439,9 +367,9 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) { ...@@ -439,9 +367,9 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
StartStream(stream, source_callback.get()); stream->Start(source_callback.get());
RunAudioLoopFor(2); RunMessageLoopFor(2);
StopStream(stream); stream->Stop();
// Verify that the stream pushed frames to the backend. // Verify that the stream pushed frames to the backend.
EXPECT_LT(0u, audio_decoder->pushed_buffer_count()); EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
...@@ -460,13 +388,13 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) { ...@@ -460,13 +388,13 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
// No error must be reported to source callback. // No error must be reported to source callback.
EXPECT_FALSE(source_callback->error()); EXPECT_FALSE(source_callback->error());
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, DeviceBusy) { TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -474,8 +402,8 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) { ...@@ -474,8 +402,8 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
StartStream(stream, source_callback.get()); stream->Start(source_callback.get());
RunMessageLoopFor(5);
// Make sure that one frame was pushed. // Make sure that one frame was pushed.
EXPECT_EQ(1u, audio_decoder->pushed_buffer_count()); EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
// No error must be reported to source callback. // No error must be reported to source callback.
...@@ -483,30 +411,23 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) { ...@@ -483,30 +411,23 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
// Sleep for a few frames and verify that more frames were not pushed // Sleep for a few frames and verify that more frames were not pushed
// because the backend device was busy. // because the backend device was busy.
RunAudioLoopFor(5); RunMessageLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
EXPECT_EQ(1u, audio_decoder->pushed_buffer_count()); EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
// Unblock the pipeline and verify that PushFrame resumes. // Unblock the pipeline and verify that PushFrame resumes.
// (have to post because this directly calls buffer complete) audio_decoder->set_pipeline_status(FakeAudioDecoder::PIPELINE_STATUS_OK);
backend_task_runner_->PostTask( RunMessageLoopFor(5);
FROM_HERE,
base::Bind(&FakeAudioDecoder::set_pipeline_status,
base::Unretained(audio_decoder),
FakeAudioDecoder::PIPELINE_STATUS_OK));
RunAudioLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
EXPECT_LT(1u, audio_decoder->pushed_buffer_count()); EXPECT_LT(1u, audio_decoder->pushed_buffer_count());
EXPECT_FALSE(source_callback->error()); EXPECT_FALSE(source_callback->error());
StopStream(stream); stream->Stop();
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, DeviceError) { TEST_F(CastAudioOutputStreamTest, DeviceError) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -514,22 +435,21 @@ TEST_F(CastAudioOutputStreamTest, DeviceError) { ...@@ -514,22 +435,21 @@ TEST_F(CastAudioOutputStreamTest, DeviceError) {
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
StartStream(stream, source_callback.get()); stream->Start(source_callback.get());
RunAudioLoopFor(2); RunMessageLoopFor(2);
// Make sure that AudioOutputStream attempted to push the initial frame. // Make sure that AudioOutputStream attempted to push the initial frame.
EXPECT_LT(0u, audio_decoder->pushed_buffer_count()); EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
// AudioOutputStream must report error to source callback. // AudioOutputStream must report error to source callback.
EXPECT_TRUE(source_callback->error()); EXPECT_TRUE(source_callback->error());
StopStream(stream); stream->Stop();
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) { TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
EXPECT_TRUE(OpenStream(stream)); EXPECT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
...@@ -538,74 +458,63 @@ TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) { ...@@ -538,74 +458,63 @@ TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
StartStream(stream, source_callback.get()); stream->Start(source_callback.get());
RunAudioLoopFor(5); RunMessageLoopFor(5);
// Make sure that one frame was pushed. // Make sure that one frame was pushed.
EXPECT_EQ(1u, audio_decoder->pushed_buffer_count()); EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
// Unblock the pipeline and verify that PushFrame resumes.
// (have to post because this directly calls buffer complete)
backend_task_runner_->PostTask(
FROM_HERE,
base::Bind(&FakeAudioDecoder::set_pipeline_status,
base::Unretained(audio_decoder),
FakeAudioDecoder::PIPELINE_STATUS_OK));
RunAudioLoopFor(5);
RunUntilIdle(backend_task_runner_.get());
// AudioOutputStream must report error to source callback. // AudioOutputStream must report error to source callback.
EXPECT_TRUE(source_callback->error()); EXPECT_TRUE(source_callback->error());
StopStream(stream); stream->Stop();
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, Volume) { TEST_F(CastAudioOutputStreamTest, Volume) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ASSERT_TRUE(OpenStream(stream)); ASSERT_TRUE(stream->Open());
FakeAudioDecoder* audio_decoder = GetAudio(); FakeAudioDecoder* audio_decoder = GetAudio();
ASSERT_TRUE(audio_decoder); ASSERT_TRUE(audio_decoder);
double volume = GetStreamVolume(stream); double volume = 0.0;
stream->GetVolume(&volume);
EXPECT_EQ(1.0, volume); EXPECT_EQ(1.0, volume);
EXPECT_EQ(1.0f, audio_decoder->volume()); EXPECT_EQ(1.0f, audio_decoder->volume());
SetStreamVolume(stream, 0.5); stream->SetVolume(0.5);
volume = GetStreamVolume(stream); stream->GetVolume(&volume);
EXPECT_EQ(0.5, volume); EXPECT_EQ(0.5, volume);
EXPECT_EQ(0.5f, audio_decoder->volume()); EXPECT_EQ(0.5f, audio_decoder->volume());
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, StartStopStart) { TEST_F(CastAudioOutputStreamTest, StartStopStart) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ASSERT_TRUE(OpenStream(stream)); ASSERT_TRUE(stream->Open());
std::unique_ptr<FakeAudioSourceCallback> source_callback( std::unique_ptr<FakeAudioSourceCallback> source_callback(
new FakeAudioSourceCallback); new FakeAudioSourceCallback);
stream->Start(source_callback.get()); stream->Start(source_callback.get());
RunAudioLoopFor(2); RunMessageLoopFor(2);
stream->Stop(); stream->Stop();
stream->Start(source_callback.get()); stream->Start(source_callback.get());
RunAudioLoopFor(2); RunMessageLoopFor(2);
RunUntilIdle(backend_task_runner_.get());
FakeAudioDecoder* audio_device = GetAudio(); FakeAudioDecoder* audio_device = GetAudio();
EXPECT_TRUE(audio_device); EXPECT_TRUE(audio_device);
EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, GetBackend()->state()); EXPECT_EQ(FakeMediaPipelineBackend::kStateRunning, GetBackend()->state());
CloseStream(stream); stream->Close();
} }
TEST_F(CastAudioOutputStreamTest, CloseWithoutStart) { TEST_F(CastAudioOutputStreamTest, CloseWithoutStart) {
::media::AudioOutputStream* stream = CreateStream(); ::media::AudioOutputStream* stream = CreateStream();
ASSERT_TRUE(stream); ASSERT_TRUE(stream);
ASSERT_TRUE(OpenStream(stream)); ASSERT_TRUE(stream->Open());
CloseStream(stream); stream->Close();
} }
} // namespace } // namespace
......
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