blob: 4fed5640d8f28e3db0f5c71ff6a377ba4f1ac300 [file] [log] [blame]
// Copyright 2017 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/backend/audio_decoder_wrapper.h"
#include <algorithm>
#include <utility>
#include "base/logging.h"
#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
#include "chromecast/media/cma/base/decoder_buffer_base.h"
#include "chromecast/public/media/cast_decoder_buffer.h"
namespace chromecast {
namespace media {
namespace {
// This revoked AudioDecoder would behave as one with buffer filled up and
// doesn't advance |statistics| and doesn't change RenderingDelay.
class RevokedAudioDecoderWrapper : public DestructableAudioDecoder {
public:
RevokedAudioDecoderWrapper(RenderingDelay rendering_delay,
Statistics statistics,
bool requires_decryption)
: rendering_delay_(rendering_delay),
statistics_(statistics),
requires_decryption_(requires_decryption) {}
~RevokedAudioDecoderWrapper() override = default;
private:
// DestructableAudioDecoder implementation:
void OnInitialized() override {}
void SetDelegate(Delegate* delegate) override {}
BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override {
return MediaPipelineBackend::kBufferPending;
}
bool SetConfig(const AudioConfig& config) override { return true; }
bool SetVolume(float multiplier) override { return true; }
RenderingDelay GetRenderingDelay() override { return rendering_delay_; }
void GetStatistics(Statistics* statistics) override {
*statistics = statistics_;
}
bool RequiresDecryption() override { return requires_decryption_; }
const RenderingDelay rendering_delay_;
const Statistics statistics_;
const bool requires_decryption_;
DISALLOW_COPY_AND_ASSIGN(RevokedAudioDecoderWrapper);
};
} // namespace
ActiveAudioDecoderWrapper::ActiveAudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate)
: backend_manager_(backend_manager),
decoder_(backend_decoder),
content_type_(type),
buffer_delegate_(buffer_delegate),
initialized_(false),
delegate_active_(false),
global_volume_multiplier_(1.0f),
stream_volume_multiplier_(1.0f) {
DCHECK(backend_manager_);
backend_manager_->AddAudioDecoder(this);
if (buffer_delegate_) {
buffer_delegate_->OnStreamStarted();
}
}
ActiveAudioDecoderWrapper::~ActiveAudioDecoderWrapper() {
if (buffer_delegate_) {
buffer_delegate_->OnStreamStopped();
}
backend_manager_->RemoveAudioDecoder(this);
}
void ActiveAudioDecoderWrapper::OnInitialized() {
initialized_ = true;
if (!delegate_active_) {
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
decoder_.SetVolume(volume);
}
}
void ActiveAudioDecoderWrapper::SetGlobalVolumeMultiplier(float multiplier) {
global_volume_multiplier_ = multiplier;
if (!delegate_active_) {
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
if (initialized_) {
decoder_.SetVolume(volume);
}
if (buffer_delegate_) {
buffer_delegate_->OnSetVolume(volume);
}
}
}
void ActiveAudioDecoderWrapper::SetDelegate(Delegate* delegate) {
decoder_.SetDelegate(delegate);
}
CmaBackend::BufferStatus ActiveAudioDecoderWrapper::PushBuffer(
scoped_refptr<DecoderBufferBase> buffer) {
if (buffer_delegate_ && buffer_delegate_->IsActive()) {
// Mute the decoder, we are sending audio to delegate.
if (!delegate_active_) {
delegate_active_ = true;
decoder_.SetVolume(0.0);
}
buffer_delegate_->OnPushBuffer(buffer.get());
} else {
// Restore original volume.
if (delegate_active_) {
delegate_active_ = false;
if (!decoder_.SetVolume(stream_volume_multiplier_ *
global_volume_multiplier_)) {
LOG(ERROR) << "SetVolume failed";
}
}
}
// Retain the buffer. Backend expects pipeline to hold the buffer until
// Decoder::Delegate::OnBufferComplete is called.
// TODO: Release the buffer at a proper time.
pushed_buffer_ = std::move(buffer);
return decoder_.PushBuffer(pushed_buffer_.get());
}
bool ActiveAudioDecoderWrapper::SetConfig(const AudioConfig& config) {
if (buffer_delegate_) {
buffer_delegate_->OnSetConfig(config);
}
return decoder_.SetConfig(config);
}
bool ActiveAudioDecoderWrapper::SetVolume(float multiplier) {
stream_volume_multiplier_ = std::max(0.0f, std::min(multiplier, 1.0f));
float volume = stream_volume_multiplier_ * global_volume_multiplier_;
if (buffer_delegate_) {
buffer_delegate_->OnSetVolume(volume);
}
if (delegate_active_ || !initialized_) {
return true;
}
return decoder_.SetVolume(volume);
}
ActiveAudioDecoderWrapper::RenderingDelay
ActiveAudioDecoderWrapper::GetRenderingDelay() {
return decoder_.GetRenderingDelay();
}
void ActiveAudioDecoderWrapper::GetStatistics(Statistics* statistics) {
decoder_.GetStatistics(statistics);
}
bool ActiveAudioDecoderWrapper::RequiresDecryption() {
return (MediaPipelineBackend::AudioDecoder::RequiresDecryption &&
MediaPipelineBackend::AudioDecoder::RequiresDecryption()) ||
decoder_.IsUsingSoftwareDecoder();
}
AudioDecoderWrapper::AudioDecoderWrapper(
MediaPipelineBackendManager* backend_manager,
MediaPipelineBackend::AudioDecoder* backend_decoder,
AudioContentType type,
MediaPipelineBackendManager::BufferDelegate* buffer_delegate)
: decoder_revoked_(false) {
audio_decoder_ = std::make_unique<ActiveAudioDecoderWrapper>(
backend_manager, backend_decoder, type, buffer_delegate);
}
AudioDecoderWrapper::AudioDecoderWrapper(AudioContentType type)
: decoder_revoked_(true) {
audio_decoder_ = std::make_unique<RevokedAudioDecoderWrapper>(
RenderingDelay(), Statistics(), false);
}
AudioDecoderWrapper::~AudioDecoderWrapper() = default;
void AudioDecoderWrapper::OnInitialized() {
audio_decoder_->OnInitialized();
}
void AudioDecoderWrapper::Revoke() {
if (!decoder_revoked_) {
decoder_revoked_ = true;
// Get some current values from audio_decoder_(ActiveAudioDecoderWrapper),
// then replace the audio_decoder_ with a revoked one.
Statistics statistics;
audio_decoder_->GetStatistics(&statistics);
audio_decoder_ = std::make_unique<RevokedAudioDecoderWrapper>(
audio_decoder_->GetRenderingDelay(), statistics,
audio_decoder_->RequiresDecryption());
}
}
void AudioDecoderWrapper::SetDelegate(Delegate* delegate) {
audio_decoder_->SetDelegate(delegate);
}
AudioDecoderWrapper::BufferStatus AudioDecoderWrapper::PushBuffer(
scoped_refptr<DecoderBufferBase> buffer) {
return audio_decoder_->PushBuffer(buffer);
}
bool AudioDecoderWrapper::SetConfig(const AudioConfig& config) {
return audio_decoder_->SetConfig(config);
}
bool AudioDecoderWrapper::SetVolume(float multiplier) {
return audio_decoder_->SetVolume(multiplier);
}
AudioDecoderWrapper::RenderingDelay AudioDecoderWrapper::GetRenderingDelay() {
return audio_decoder_->GetRenderingDelay();
}
void AudioDecoderWrapper::GetStatistics(Statistics* statistics) {
audio_decoder_->GetStatistics(statistics);
}
bool AudioDecoderWrapper::RequiresDecryption() {
return audio_decoder_->RequiresDecryption();
}
} // namespace media
} // namespace chromecast