// Copyright 2015 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 "chromecast/media/cma/pipeline/audio_decoder_software_wrapper.h" #include "base/bind.h" #include "base/logging.h" #include "base/thread_task_runner_handle.h" #include "chromecast/media/cma/base/decoder_buffer_base.h" namespace chromecast { namespace media { AudioDecoderSoftwareWrapper::AudioDecoderSoftwareWrapper( MediaPipelineBackend::AudioDecoder* backend_decoder) : backend_decoder_(backend_decoder), delegate_(nullptr), weak_factory_(this) { DCHECK(backend_decoder_); backend_decoder_->SetDelegate(this); } AudioDecoderSoftwareWrapper::~AudioDecoderSoftwareWrapper() {} void AudioDecoderSoftwareWrapper::SetDelegate(DecoderDelegate* delegate) { DCHECK(delegate); delegate_ = delegate; } MediaPipelineBackend::BufferStatus AudioDecoderSoftwareWrapper::PushBuffer( CastDecoderBuffer* buffer) { DCHECK(buffer); if (!software_decoder_) return backend_decoder_->PushBuffer(buffer); DecoderBufferBase* buffer_base = static_cast(buffer); if (!software_decoder_->Decode( make_scoped_refptr(buffer_base), base::Bind(&AudioDecoderSoftwareWrapper::OnDecodedBuffer, weak_factory_.GetWeakPtr()))) { return MediaPipelineBackend::kBufferFailed; } return MediaPipelineBackend::kBufferPending; } void AudioDecoderSoftwareWrapper::GetStatistics(Statistics* statistics) { DCHECK(statistics); return backend_decoder_->GetStatistics(statistics); } bool AudioDecoderSoftwareWrapper::SetConfig(const AudioConfig& config) { DCHECK(delegate_); DCHECK(IsValidConfig(config)); if (backend_decoder_->SetConfig(config)) { software_decoder_.reset(); output_config_ = config; return true; } if (config.is_encrypted || !CreateSoftwareDecoder(config)) return false; output_config_.codec = media::kCodecPCM; output_config_.sample_format = media::kSampleFormatS16; output_config_.channel_number = 2; output_config_.bytes_per_channel = 2; output_config_.samples_per_second = config.samples_per_second; output_config_.is_encrypted = false; return backend_decoder_->SetConfig(output_config_); } bool AudioDecoderSoftwareWrapper::SetVolume(float multiplier) { return backend_decoder_->SetVolume(multiplier); } AudioDecoderSoftwareWrapper::RenderingDelay AudioDecoderSoftwareWrapper::GetRenderingDelay() { return backend_decoder_->GetRenderingDelay(); } bool AudioDecoderSoftwareWrapper::CreateSoftwareDecoder( const AudioConfig& config) { // TODO(kmackay) Consider using planar float instead. software_decoder_ = media::CastAudioDecoder::Create( base::ThreadTaskRunnerHandle::Get(), config, media::CastAudioDecoder::kOutputSigned16, base::Bind(&AudioDecoderSoftwareWrapper::OnDecoderInitialized, weak_factory_.GetWeakPtr())); return (software_decoder_.get() != nullptr); } void AudioDecoderSoftwareWrapper::OnDecoderInitialized(bool success) { if (!success) { LOG(ERROR) << "Failed to initialize software decoder"; delegate_->OnDecoderError(); } } void AudioDecoderSoftwareWrapper::OnDecodedBuffer( CastAudioDecoder::Status status, const scoped_refptr& decoded) { if (status != CastAudioDecoder::kDecodeOk) { delegate_->OnPushBufferComplete(MediaPipelineBackend::kBufferFailed); return; } pending_pushed_buffer_ = decoded; MediaPipelineBackend::BufferStatus buffer_status = backend_decoder_->PushBuffer(pending_pushed_buffer_.get()); if (buffer_status != MediaPipelineBackend::kBufferPending) delegate_->OnPushBufferComplete(buffer_status); } void AudioDecoderSoftwareWrapper::OnPushBufferComplete( MediaPipelineBackend::BufferStatus status) { DCHECK(delegate_); delegate_->OnPushBufferComplete(status); } void AudioDecoderSoftwareWrapper::OnEndOfStream() { DCHECK(delegate_); delegate_->OnEndOfStream(); } void AudioDecoderSoftwareWrapper::OnDecoderError() { DCHECK(delegate_); delegate_->OnDecoderError(); } void AudioDecoderSoftwareWrapper::OnKeyStatusChanged(const std::string& key_id, CastKeyStatus key_status, uint32_t system_code) { DCHECK(delegate_); delegate_->OnKeyStatusChanged(key_id, key_status, system_code); } void AudioDecoderSoftwareWrapper::OnVideoResolutionChanged(const Size& size) { NOTREACHED(); } } // namespace media } // namespace chromecast