Index: chromecast/media/audio/cast_audio_output_stream.cc |
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc |
index 3b75adf06b12c29b3c5830885c93ef1c5ba20c44..3af92654267ce3b35edcedfeb903a97d7ddedc68 100644 |
--- a/chromecast/media/audio/cast_audio_output_stream.cc |
+++ b/chromecast/media/audio/cast_audio_output_stream.cc |
@@ -4,88 +4,42 @@ |
#include "chromecast/media/audio/cast_audio_output_stream.h" |
-#include <stdint.h> |
- |
#include "base/bind.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/task_runner_impl.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/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_device_params.h" |
-#include "media/base/bind_to_current_loop.h" |
#include "media/base/decoder_buffer.h" |
-namespace chromecast { |
-namespace media { |
namespace { |
- |
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 |
-// Backend represents a MediaPipelineBackend adapter that runs on cast |
-// media thread (media::MediaMessageLoop::GetTaskRunner). |
-// It can be created and destroyed on any thread, but all other member functions |
-// must be called on a single thread. |
+namespace chromecast { |
+namespace media { |
+ |
+// 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 |
: public MediaPipelineBackend::Decoder::Delegate { |
public: |
using PushBufferCompletionCallback = base::Callback<void(bool)>; |
- Backend(const ::media::AudioParameters& audio_params) |
- : audio_params_(audio_params), |
- decoder_(nullptr), |
- first_start_(true), |
- error_(false), |
- weak_factory_(this) { |
+ Backend() : decoder_(nullptr), first_start_(true), error_(false) { |
thread_checker_.DetachFromThread(); |
} |
~Backend() override {} |
- void Open(CastAudioManager* audio_manager, |
- bool* success, |
- base::WaitableEvent* completion_event) { |
+ bool Open(const ::media::AudioParameters& audio_params, |
+ CastAudioManager* audio_manager) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(backend_ == nullptr); |
DCHECK(audio_manager); |
- DCHECK(success); |
- DCHECK(completion_event); |
+ DCHECK(backend_ == nullptr); |
backend_task_runner_.reset(new TaskRunnerImpl()); |
MediaPipelineDeviceParams device_params( |
@@ -93,10 +47,24 @@ class CastAudioOutputStream::Backend |
MediaPipelineDeviceParams::kAudioStreamSoundEffects, |
backend_task_runner_.get()); |
backend_ = audio_manager->CreateMediaPipelineBackend(device_params); |
- if (backend_) |
- decoder_ = InitializeBackend(audio_params_, backend_.get(), this); |
- *success = decoder_ != nullptr; |
- completion_event->Signal(); |
+ if (!backend_) |
+ return false; |
+ |
+ 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() { |
@@ -139,7 +107,6 @@ class CastAudioOutputStream::Backend |
} |
backend_buffer_ = decoder_buffer; |
- |
completion_cb_ = completion_cb; |
BufferStatus status = decoder_->PushBuffer(backend_buffer_.get()); |
if (status != MediaPipelineBackend::kBufferPending) |
@@ -152,6 +119,7 @@ class CastAudioOutputStream::Backend |
decoder_->SetVolume(volume); |
} |
+ private: |
// MediaPipelineBackend::Decoder::Delegate implementation |
void OnPushBufferComplete(BufferStatus status) override { |
DCHECK(thread_checker_.CalledOnValidThread()); |
@@ -168,6 +136,7 @@ class CastAudioOutputStream::Backend |
void OnEndOfStream() override {} |
void OnDecoderError() override { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
error_ = true; |
if (!completion_cb_.is_null()) |
OnPushBufferComplete(MediaPipelineBackend::kBufferFailed); |
@@ -179,12 +148,6 @@ class CastAudioOutputStream::Backend |
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<TaskRunnerImpl> backend_task_runner_; |
MediaPipelineBackend::AudioDecoder* decoder_; |
@@ -193,7 +156,6 @@ class CastAudioOutputStream::Backend |
bool error_; |
scoped_refptr<DecoderBufferBase> backend_buffer_; |
base::ThreadChecker thread_checker_; |
- base::WeakPtrFactory<CastAudioOutputStream::Backend> weak_factory_; |
DISALLOW_COPY_AND_ASSIGN(Backend); |
}; |
@@ -206,22 +168,19 @@ CastAudioOutputStream::CastAudioOutputStream( |
audio_manager_(audio_manager), |
volume_(1.0), |
source_callback_(nullptr), |
- backend_(new Backend(audio_params)), |
+ backend_(new Backend()), |
buffer_duration_(audio_params.GetBufferDuration()), |
push_in_progress_(false), |
- audio_task_runner_(audio_manager->GetTaskRunner()), |
- backend_task_runner_(media::MediaMessageLoop::GetTaskRunner()), |
weak_factory_(this) { |
VLOG(1) << "CastAudioOutputStream " << this << " created with " |
<< audio_params_.AsHumanReadableString(); |
} |
CastAudioOutputStream::~CastAudioOutputStream() { |
- backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); |
} |
bool CastAudioOutputStream::Open() { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
::media::AudioParameters::Format format = audio_params_.format(); |
DCHECK((format == ::media::AudioParameters::AUDIO_PCM_LINEAR) || |
@@ -236,21 +195,11 @@ bool CastAudioOutputStream::Open() { |
DCHECK_GE(audio_params_.channels(), 1); |
DCHECK_LE(audio_params_.channels(), 2); |
- { |
- // Wait until the backend has initialized so that the outcome can be |
- // communicated to the client. |
- 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; |
- } |
+ if (!backend_->Open(audio_params_, audio_manager_)) { |
+ LOG(WARNING) << "Failed to create media pipeline backend."; |
+ return false; |
} |
+ |
audio_bus_ = ::media::AudioBus::Create(audio_params_); |
decoder_buffer_ = new DecoderBufferAdapter( |
new ::media::DecoderBuffer(audio_params_.GetBytesPerBuffer())); |
@@ -260,27 +209,27 @@ bool CastAudioOutputStream::Open() { |
} |
void CastAudioOutputStream::Close() { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
- |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
VLOG(1) << __FUNCTION__ << " : " << this; |
- backend_task_runner_->PostTaskAndReply( |
- FROM_HERE, base::Bind(&Backend::Close, backend_->GetWeakPtr()), |
- base::Bind(&CastAudioOutputStream::OnClosed, base::Unretained(this))); |
+ |
+ backend_->Close(); |
+ // 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) { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
DCHECK(source_callback); |
source_callback_ = source_callback; |
- backend_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Backend::Start, backend_->GetWeakPtr())); |
+ backend_->Start(); |
next_push_time_ = base::TimeTicks::Now(); |
if (!push_in_progress_) { |
- audio_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&CastAudioOutputStream::PushBuffer, |
- weak_factory_.GetWeakPtr())); |
+ audio_manager_->GetTaskRunner()->PostTask( |
+ FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer, |
+ weak_factory_.GetWeakPtr())); |
push_in_progress_ = true; |
} |
@@ -288,39 +237,27 @@ void CastAudioOutputStream::Start(AudioSourceCallback* source_callback) { |
} |
void CastAudioOutputStream::Stop() { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
source_callback_ = nullptr; |
- backend_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Backend::Stop, backend_->GetWeakPtr())); |
+ backend_->Stop(); |
} |
void CastAudioOutputStream::SetVolume(double volume) { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
volume_ = volume; |
- backend_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Backend::SetVolume, |
- backend_->GetWeakPtr(), volume)); |
+ backend_->SetVolume(volume); |
} |
void CastAudioOutputStream::GetVolume(double* volume) { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
*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() { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
DCHECK(push_in_progress_); |
if (!source_callback_) { |
@@ -343,18 +280,13 @@ void CastAudioOutputStream::PushBuffer() { |
audio_bus_->ToInterleaved(frame_count, audio_params_.bits_per_sample() / 8, |
decoder_buffer_->writable_data()); |
- auto completion_cb = ::media::BindToCurrentLoop( |
- base::Bind(&CastAudioOutputStream::OnPushBufferComplete, |
- weak_factory_.GetWeakPtr())); |
- backend_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&Backend::PushBuffer, |
- backend_->GetWeakPtr(), |
- decoder_buffer_, |
- completion_cb)); |
+ auto completion_cb = base::Bind(&CastAudioOutputStream::OnPushBufferComplete, |
+ weak_factory_.GetWeakPtr()); |
+ backend_->PushBuffer(decoder_buffer_, completion_cb); |
} |
void CastAudioOutputStream::OnPushBufferComplete(bool success) { |
- DCHECK(audio_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread()); |
DCHECK(push_in_progress_); |
push_in_progress_ = false; |
@@ -375,10 +307,9 @@ void CastAudioOutputStream::OnPushBufferComplete(bool success) { |
base::TimeDelta::FromMilliseconds(kMaxQueuedDataMs); |
delay = std::max(delay, base::TimeDelta()); |
- audio_task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&CastAudioOutputStream::PushBuffer, |
- weak_factory_.GetWeakPtr()), |
+ audio_manager_->GetTaskRunner()->PostDelayedTask( |
+ FROM_HERE, base::Bind(&CastAudioOutputStream::PushBuffer, |
+ weak_factory_.GetWeakPtr()), |
delay); |
push_in_progress_ = true; |
} |