Commit f08e9d14 authored by ziyangch's avatar ziyangch Committed by Commit Bot

[Chromecast] Split Internal from CmaAudioOutputStream.

-CmaAudioOutputStreamInternal will be a pure push mode output stream.
And CmaAudioOutputStream will keep the backend state control and push
timer logic.

Bug: internal b/152920790

Test: Cast from Youtube to Android TV device.

Change-Id: Iadbb82a8017b8779a6c96a8473b1179469966242
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2242650
Commit-Queue: Ziyang Cheng <ziyangch@chromium.org>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Reviewed-by: default avatarKenneth MacKay <kmackay@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780110}
parent 550e3718
...@@ -57,6 +57,24 @@ cast_source_set("interleaved_channel_mixer") { ...@@ -57,6 +57,24 @@ cast_source_set("interleaved_channel_mixer") {
] ]
} }
cast_source_set("cma_audio_output") {
sources = [
"cma_audio_output.cc",
"cma_audio_output.h",
]
deps = [
"//base",
"//chromecast/base",
"//chromecast/common/mojom",
"//chromecast/media/base",
"//chromecast/media/cma/backend",
"//chromecast/media/cma/base",
"//chromecast/public/media",
"//media",
]
}
cast_source_set("audio") { cast_source_set("audio") {
sources = [ sources = [
"cast_audio_input_stream.cc", "cast_audio_input_stream.cc",
...@@ -74,6 +92,7 @@ cast_source_set("audio") { ...@@ -74,6 +92,7 @@ cast_source_set("audio") {
deps = [ deps = [
":audio_buildflags", ":audio_buildflags",
":cma_audio_output",
"//base", "//base",
"//chromecast/base", "//chromecast/base",
"//chromecast/common/mojom", "//chromecast/common/mojom",
......
...@@ -194,6 +194,7 @@ TEST_F(CastAudioManagerTest, CanMakeStream) { ...@@ -194,6 +194,7 @@ TEST_F(CastAudioManagerTest, CanMakeStream) {
kDefaultAudioParams, "", ::media::AudioManager::LogCallback()); kDefaultAudioParams, "", ::media::AudioManager::LogCallback());
EXPECT_TRUE(stream->Open()); EXPECT_TRUE(stream->Open());
EXPECT_CALL(*mock_cma_backend_, Start(_)).WillOnce(Return(true));
EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _)) EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _))
.WillRepeatedly(Invoke(OnMoreData)); .WillRepeatedly(Invoke(OnMoreData));
EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0); EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0);
...@@ -218,6 +219,7 @@ TEST_F(CastAudioManagerTest, CanMakeAC3Stream) { ...@@ -218,6 +219,7 @@ TEST_F(CastAudioManagerTest, CanMakeAC3Stream) {
EXPECT_TRUE(stream); EXPECT_TRUE(stream);
// Only run the rest of the test if the device supports AC3. // Only run the rest of the test if the device supports AC3.
if (stream->Open()) { if (stream->Open()) {
EXPECT_CALL(*mock_cma_backend_, Start(_)).WillOnce(Return(true));
EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _)) EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _))
.WillRepeatedly(Invoke(OnMoreData)); .WillRepeatedly(Invoke(OnMoreData));
EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0); EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0);
...@@ -237,6 +239,7 @@ TEST_F(CastAudioManagerTest, DISABLED_CanMakeStreamProxy) { ...@@ -237,6 +239,7 @@ TEST_F(CastAudioManagerTest, DISABLED_CanMakeStreamProxy) {
audio_manager_->MakeAudioOutputStreamProxy(kDefaultAudioParams, ""); audio_manager_->MakeAudioOutputStreamProxy(kDefaultAudioParams, "");
EXPECT_TRUE(stream->Open()); EXPECT_TRUE(stream->Open());
RunThreadsUntilIdle(); RunThreadsUntilIdle();
EXPECT_CALL(*mock_cma_backend_, Start(_)).WillOnce(Return(true));
EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _)) EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _))
.WillRepeatedly(Invoke(OnMoreData)); .WillRepeatedly(Invoke(OnMoreData));
EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0); EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0);
...@@ -258,6 +261,7 @@ TEST_F(CastAudioManagerTest, CanMakeMixerStream) { ...@@ -258,6 +261,7 @@ TEST_F(CastAudioManagerTest, CanMakeMixerStream) {
kDefaultAudioParams, "", ::media::AudioManager::LogCallback()); kDefaultAudioParams, "", ::media::AudioManager::LogCallback());
EXPECT_TRUE(stream->Open()); EXPECT_TRUE(stream->Open());
EXPECT_CALL(*mock_cma_backend_, Start(_)).WillOnce(Return(true));
EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _)) EXPECT_CALL(mock_source_callback_, OnMoreData(_, _, _, _))
.WillRepeatedly(Invoke(OnMoreData)); .WillRepeatedly(Invoke(OnMoreData));
EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0); EXPECT_CALL(mock_source_callback_, OnError(_)).Times(0);
......
// Copyright 2020 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/audio/cma_audio_output.h"
#include <algorithm>
#include <limits>
#include <utility>
#include "base/logging.h"
#include "chromecast/base/task_runner_impl.h"
#include "chromecast/media/api/cma_backend_factory.h"
#include "chromecast/media/base/cast_decoder_buffer_impl.h"
#include "chromecast/media/cma/base/decoder_config_adapter.h"
#include "chromecast/public/media/media_pipeline_device_params.h"
#include "chromecast/public/volume_control.h"
#include "media/audio/audio_device_description.h"
namespace chromecast {
namespace media {
namespace {
AudioContentType GetContentType(const std::string& device_id) {
if (::media::AudioDeviceDescription::IsCommunicationsDevice(device_id)) {
return AudioContentType::kCommunication;
}
return AudioContentType::kMedia;
}
int GetSampleSize(SampleFormat sample_format) {
switch (sample_format) {
case kUnknownSampleFormat:
return 0;
case kSampleFormatU8:
return sizeof(uint8_t);
case kSampleFormatS16:
case kSampleFormatPlanarS16:
return sizeof(int16_t);
case kSampleFormatS32:
case kSampleFormatPlanarS32:
return sizeof(int32_t);
case kSampleFormatF32:
case kSampleFormatPlanarF32:
return sizeof(float);
case kSampleFormatS24:
return 3;
}
}
} // namespace
CmaAudioOutput::CmaAudioOutput(
const ::media::AudioParameters& audio_params,
SampleFormat sample_format,
const std::string& device_id,
const std::string& application_session_id,
chromecast::mojom::MultiroomInfoPtr multiroom_info,
CmaBackendFactory* cma_backend_factory,
CmaBackend::Decoder::Delegate* delegate)
: audio_params_(audio_params),
sample_size_(GetSampleSize(sample_format)),
delegate_(delegate),
timestamp_helper_(audio_params_.sample_rate()) {
DCHECK(delegate_);
Initialize(sample_format, device_id, application_session_id,
std::move(multiroom_info), cma_backend_factory);
}
CmaAudioOutput::~CmaAudioOutput() = default;
void CmaAudioOutput::Initialize(
SampleFormat sample_format,
const std::string& device_id,
const std::string& application_session_id,
chromecast::mojom::MultiroomInfoPtr multiroom_info,
CmaBackendFactory* cma_backend_factory) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(multiroom_info);
DCHECK(cma_backend_factory);
auto cma_backend_task_runner = std::make_unique<TaskRunnerImpl>();
MediaPipelineDeviceParams device_params(
MediaPipelineDeviceParams::kModeIgnorePts,
MediaPipelineDeviceParams::kAudioStreamNormal,
cma_backend_task_runner.get(), GetContentType(device_id), device_id);
device_params.session_id = application_session_id;
device_params.multiroom = multiroom_info->multiroom;
device_params.audio_channel = multiroom_info->audio_channel;
device_params.output_delay_us = multiroom_info->output_delay.InMicroseconds();
auto cma_backend = cma_backend_factory->CreateBackend(device_params);
if (!cma_backend) {
return;
}
auto* audio_decoder = cma_backend->CreateAudioDecoder();
if (!audio_decoder) {
return;
}
audio_decoder->SetDelegate(delegate_);
AudioConfig audio_config;
audio_config.codec = kCodecPCM;
audio_config.channel_layout =
DecoderConfigAdapter::ToChannelLayout(audio_params_.channel_layout());
audio_config.sample_format = sample_format;
audio_config.bytes_per_channel = sample_size_;
audio_config.channel_number = audio_params_.channels();
audio_config.samples_per_second = audio_params_.sample_rate();
DCHECK(IsValidConfig(audio_config));
// Need to first set the config of the audio decoder then initialize the cma
// backend if succeed.
if (!audio_decoder->SetConfig(audio_config) || !cma_backend->Initialize()) {
return;
}
cma_backend_task_runner_ = std::move(cma_backend_task_runner);
cma_backend_ = std::move(cma_backend);
audio_decoder_ = audio_decoder;
timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
}
bool CmaAudioOutput::Start(int64_t start_pts) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!cma_backend_ || !cma_backend_->Start(start_pts)) {
return false;
}
return true;
}
void CmaAudioOutput::Stop() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (cma_backend_) {
cma_backend_->Stop();
}
}
bool CmaAudioOutput::Pause() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!cma_backend_ || !cma_backend_->Pause()) {
return false;
}
return true;
}
bool CmaAudioOutput::Resume() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!cma_backend_ || !cma_backend_->Resume()) {
return false;
}
return true;
}
bool CmaAudioOutput::SetVolume(double volume) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!audio_decoder_) {
return false;
}
return audio_decoder_->SetVolume(volume);
}
void CmaAudioOutput::PushBuffer(
scoped_refptr<CastDecoderBufferImpl> decoder_buffer) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK_GT(decoder_buffer->data_size(), 0u);
DCHECK_EQ(
decoder_buffer->data_size() % (sample_size_ * audio_params_.channels()),
0u);
DCHECK(audio_decoder_);
decoder_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
int frame_count =
decoder_buffer->data_size() / (sample_size_ * audio_params_.channels());
timestamp_helper_.AddFrames(frame_count);
CmaBackend::BufferStatus status =
audio_decoder_->PushBuffer(std::move(decoder_buffer));
if (status != CmaBackend::BufferStatus::kBufferPending)
delegate_->OnPushBufferComplete(status);
}
CmaBackend::AudioDecoder::RenderingDelay CmaAudioOutput::GetRenderingDelay() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(audio_decoder_);
return audio_decoder_->GetRenderingDelay();
}
} // namespace media
} // namespace chromecast
// Copyright 2020 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.
#ifndef CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_H_
#define CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_H_
#include <cstdint>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
#include "chromecast/common/mojom/multiroom.mojom.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/public/media/decoder_config.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_timestamp_helper.h"
namespace chromecast {
class TaskRunnerImpl;
namespace media {
class CastDecoderBufferImpl;
class CmaBackendFactory;
class CmaAudioOutput {
public:
CmaAudioOutput(const ::media::AudioParameters& audio_params,
SampleFormat sample_format,
const std::string& device_id,
const std::string& application_session_id,
chromecast::mojom::MultiroomInfoPtr multiroom_info,
CmaBackendFactory* cma_backend_factory,
CmaBackend::Decoder::Delegate* delegate);
// Disallow copy and assign.
CmaAudioOutput(const CmaAudioOutput&) = delete;
CmaAudioOutput& operator=(const CmaAudioOutput&) = delete;
~CmaAudioOutput();
bool Start(int64_t start_pts);
void Stop();
bool Pause();
bool Resume();
bool SetVolume(double volume);
void PushBuffer(scoped_refptr<CastDecoderBufferImpl> decoder_buffer);
CmaBackend::AudioDecoder::RenderingDelay GetRenderingDelay();
private:
void Initialize(SampleFormat sample_format,
const std::string& device_id,
const std::string& application_session_id,
chromecast::mojom::MultiroomInfoPtr multiroom_info,
CmaBackendFactory* cma_backend_factory);
const ::media::AudioParameters audio_params_;
const int sample_size_;
CmaBackend::Decoder::Delegate* const delegate_;
::media::AudioTimestampHelper timestamp_helper_;
std::unique_ptr<TaskRunnerImpl> cma_backend_task_runner_;
std::unique_ptr<CmaBackend> cma_backend_;
CmaBackend::AudioDecoder* audio_decoder_ = nullptr;
THREAD_CHECKER(media_thread_checker_);
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_H_
...@@ -13,15 +13,14 @@ ...@@ -13,15 +13,14 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "chromecast/base/task_runner_impl.h" #include "chromecast/base/task_runner_impl.h"
#include "chromecast/media/api/cma_backend_factory.h" #include "chromecast/media/audio/cma_audio_output.h"
#include "chromecast/media/base/cast_decoder_buffer_impl.h"
#include "chromecast/media/base/default_monotonic_clock.h" #include "chromecast/media/base/default_monotonic_clock.h"
#include "chromecast/media/cma/base/decoder_buffer_adapter.h"
#include "chromecast/media/cma/base/decoder_config_adapter.h" #include "chromecast/media/cma/base/decoder_config_adapter.h"
#include "chromecast/public/media/media_pipeline_device_params.h" #include "chromecast/public/media/media_pipeline_device_params.h"
#include "chromecast/public/volume_control.h" #include "chromecast/public/volume_control.h"
#include "media/audio/audio_device_description.h" #include "media/audio/audio_device_description.h"
#include "media/base/audio_bus.h" #include "media/base/audio_bus.h"
#include "media/base/decoder_buffer.h"
namespace chromecast { namespace chromecast {
namespace media { namespace media {
...@@ -30,13 +29,6 @@ namespace { ...@@ -30,13 +29,6 @@ namespace {
constexpr base::TimeDelta kRenderBufferSize = base::TimeDelta::FromSeconds(4); constexpr base::TimeDelta kRenderBufferSize = base::TimeDelta::FromSeconds(4);
AudioContentType GetContentType(const std::string& device_id) {
if (::media::AudioDeviceDescription::IsCommunicationsDevice(device_id)) {
return AudioContentType::kCommunication;
}
return AudioContentType::kMedia;
}
} // namespace } // namespace
CmaAudioOutputStream::CmaAudioOutputStream( CmaAudioOutputStream::CmaAudioOutputStream(
...@@ -49,7 +41,6 @@ CmaAudioOutputStream::CmaAudioOutputStream( ...@@ -49,7 +41,6 @@ CmaAudioOutputStream::CmaAudioOutputStream(
audio_params_(audio_params), audio_params_(audio_params),
device_id_(device_id), device_id_(device_id),
cma_backend_factory_(cma_backend_factory), cma_backend_factory_(cma_backend_factory),
timestamp_helper_(audio_params_.sample_rate()),
buffer_duration_(buffer_duration), buffer_duration_(buffer_duration),
render_buffer_size_estimate_(kRenderBufferSize) { render_buffer_size_estimate_(kRenderBufferSize) {
DCHECK(cma_backend_factory_); DCHECK(cma_backend_factory_);
...@@ -69,55 +60,13 @@ void CmaAudioOutputStream::Initialize( ...@@ -69,55 +60,13 @@ void CmaAudioOutputStream::Initialize(
const std::string& application_session_id, const std::string& application_session_id,
chromecast::mojom::MultiroomInfoPtr multiroom_info) { chromecast::mojom::MultiroomInfoPtr multiroom_info) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(cma_backend_factory_); DCHECK_EQ(cma_backend_state_, CmaBackendState::kUninitialized);
output_ = std::make_unique<CmaAudioOutput>(
if (cma_backend_state_ != CmaBackendState::kUninitialized) audio_params_, kSampleFormatS16, device_id_, application_session_id,
return; std::move(multiroom_info), cma_backend_factory_, this);
cma_backend_task_runner_ = std::make_unique<TaskRunnerImpl>();
MediaPipelineDeviceParams device_params(
MediaPipelineDeviceParams::kModeIgnorePts,
MediaPipelineDeviceParams::kAudioStreamNormal,
cma_backend_task_runner_.get(), GetContentType(device_id_), device_id_);
device_params.session_id = application_session_id;
device_params.multiroom = multiroom_info->multiroom;
device_params.audio_channel = multiroom_info->audio_channel;
device_params.output_delay_us = multiroom_info->output_delay.InMicroseconds();
cma_backend_ = cma_backend_factory_->CreateBackend(device_params);
if (!cma_backend_) {
encountered_error_ = true;
return;
}
audio_decoder_ = cma_backend_->CreateAudioDecoder();
if (!audio_decoder_) {
encountered_error_ = true;
return;
}
audio_decoder_->SetDelegate(this);
AudioConfig audio_config;
audio_config.codec = kCodecPCM;
audio_config.channel_layout =
DecoderConfigAdapter::ToChannelLayout(audio_params_.channel_layout());
audio_config.sample_format = kSampleFormatS16;
audio_config.bytes_per_channel = 2;
audio_config.channel_number = audio_params_.channels();
audio_config.samples_per_second = audio_params_.sample_rate();
DCHECK(IsValidConfig(audio_config));
if (!audio_decoder_->SetConfig(audio_config)) {
encountered_error_ = true;
return;
}
if (!cma_backend_->Initialize()) {
encountered_error_ = true;
return;
}
cma_backend_state_ = CmaBackendState::kStopped; cma_backend_state_ = CmaBackendState::kStopped;
audio_bus_ = ::media::AudioBus::Create(audio_params_); audio_bus_ = ::media::AudioBus::Create(audio_params_);
timestamp_helper_.SetBaseTimestamp(base::TimeDelta());
} }
void CmaAudioOutputStream::Start( void CmaAudioOutputStream::Start(
...@@ -137,9 +86,19 @@ void CmaAudioOutputStream::Start( ...@@ -137,9 +86,19 @@ void CmaAudioOutputStream::Start(
if (cma_backend_state_ == CmaBackendState::kPaused || if (cma_backend_state_ == CmaBackendState::kPaused ||
cma_backend_state_ == CmaBackendState::kStopped) { cma_backend_state_ == CmaBackendState::kStopped) {
if (cma_backend_state_ == CmaBackendState::kPaused) { if (cma_backend_state_ == CmaBackendState::kPaused) {
cma_backend_->Resume(); if (!output_->Resume()) {
encountered_error_ = true;
source_callback_->OnError(::media::AudioOutputStream::
AudioSourceCallback::ErrorType::kUnknown);
return;
}
} else { } else {
cma_backend_->Start(0); if (!output_->Start(0)) {
encountered_error_ = true;
source_callback_->OnError(::media::AudioOutputStream::
AudioSourceCallback::ErrorType::kUnknown);
return;
}
render_buffer_size_estimate_ = kRenderBufferSize; render_buffer_size_estimate_ = kRenderBufferSize;
} }
next_push_time_ = base::TimeTicks::Now(); next_push_time_ = base::TimeTicks::Now();
...@@ -158,8 +117,8 @@ void CmaAudioOutputStream::Stop(base::WaitableEvent* finished) { ...@@ -158,8 +117,8 @@ void CmaAudioOutputStream::Stop(base::WaitableEvent* finished) {
push_timer_.Stop(); push_timer_.Stop();
// Don't actually stop the backend. Stop() gets called when the stream is // Don't actually stop the backend. Stop() gets called when the stream is
// paused. We rely on Flush() to stop the backend. // paused. We rely on Flush() to stop the backend.
if (cma_backend_) { if (output_) {
cma_backend_->Pause(); output_->Pause();
cma_backend_state_ = CmaBackendState::kPaused; cma_backend_state_ = CmaBackendState::kPaused;
} }
source_callback_ = nullptr; source_callback_ = nullptr;
...@@ -171,9 +130,9 @@ void CmaAudioOutputStream::Flush(base::WaitableEvent* finished) { ...@@ -171,9 +130,9 @@ void CmaAudioOutputStream::Flush(base::WaitableEvent* finished) {
// Prevent further pushes to the audio buffer after stopping. // Prevent further pushes to the audio buffer after stopping.
push_timer_.Stop(); push_timer_.Stop();
if (cma_backend_ && (cma_backend_state_ == CmaBackendState::kPaused || if (output_ && (cma_backend_state_ == CmaBackendState::kPaused ||
cma_backend_state_ == CmaBackendState::kStarted)) { cma_backend_state_ == CmaBackendState::kStarted)) {
cma_backend_->Stop(); output_->Stop();
cma_backend_state_ = CmaBackendState::kStopped; cma_backend_state_ = CmaBackendState::kStopped;
} }
push_in_progress_ = false; push_in_progress_ = false;
...@@ -186,29 +145,28 @@ void CmaAudioOutputStream::Close(base::OnceClosure closure) { ...@@ -186,29 +145,28 @@ void CmaAudioOutputStream::Close(base::OnceClosure closure) {
// Prevent further pushes to the audio buffer after stopping. // Prevent further pushes to the audio buffer after stopping.
push_timer_.Stop(); push_timer_.Stop();
// Only stop the backend if it was started. // Only stop the backend if it was started.
if (cma_backend_ && cma_backend_state_ != CmaBackendState::kStopped) { if (output_ && cma_backend_state_ != CmaBackendState::kStopped) {
cma_backend_->Stop(); output_->Stop();
} }
push_in_progress_ = false; push_in_progress_ = false;
source_callback_ = nullptr; source_callback_ = nullptr;
cma_backend_state_ = CmaBackendState::kPendingClose; cma_backend_state_ = CmaBackendState::kPendingClose;
audio_bus_.reset(); audio_bus_.reset();
cma_backend_.reset(); output_.reset();
cma_backend_task_runner_.reset();
std::move(closure).Run(); std::move(closure).Run();
} }
void CmaAudioOutputStream::SetVolume(double volume) { void CmaAudioOutputStream::SetVolume(double volume) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (!audio_decoder_) { if (!output_) {
return; return;
} }
if (encountered_error_) { if (encountered_error_) {
return; return;
} }
audio_decoder_->SetVolume(volume); output_->SetVolume(volume);
} }
void CmaAudioOutputStream::PushBuffer() { void CmaAudioOutputStream::PushBuffer() {
...@@ -232,7 +190,7 @@ void CmaAudioOutputStream::PushBuffer() { ...@@ -232,7 +190,7 @@ void CmaAudioOutputStream::PushBuffer() {
} }
CmaBackend::AudioDecoder::RenderingDelay rendering_delay = CmaBackend::AudioDecoder::RenderingDelay rendering_delay =
audio_decoder_->GetRenderingDelay(); output_->GetRenderingDelay();
base::TimeDelta delay; base::TimeDelta delay;
if (rendering_delay.delay_microseconds < 0 || if (rendering_delay.delay_microseconds < 0 ||
...@@ -262,18 +220,12 @@ void CmaAudioOutputStream::PushBuffer() { ...@@ -262,18 +220,12 @@ void CmaAudioOutputStream::PushBuffer() {
OnPushBufferComplete(CmaBackend::BufferStatus::kBufferFailed); OnPushBufferComplete(CmaBackend::BufferStatus::kBufferFailed);
return; return;
} }
auto decoder_buffer = auto decoder_buffer = base::MakeRefCounted<CastDecoderBufferImpl>(
base::MakeRefCounted<DecoderBufferAdapter>(new ::media::DecoderBuffer( frame_count * audio_bus_->channels() * sizeof(int16_t));
frame_count * audio_bus_->channels() * sizeof(int16_t)));
audio_bus_->ToInterleaved<::media::SignedInt16SampleTypeTraits>( audio_bus_->ToInterleaved<::media::SignedInt16SampleTypeTraits>(
frame_count, reinterpret_cast<int16_t*>(decoder_buffer->writable_data())); frame_count, reinterpret_cast<int16_t*>(decoder_buffer->writable_data()));
decoder_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
timestamp_helper_.AddFrames(frame_count);
push_in_progress_ = true; push_in_progress_ = true;
BufferStatus status = audio_decoder_->PushBuffer(std::move(decoder_buffer)); output_->PushBuffer(std::move(decoder_buffer));
if (status != CmaBackend::BufferStatus::kBufferPending)
OnPushBufferComplete(status);
} }
void CmaAudioOutputStream::OnPushBufferComplete(BufferStatus status) { void CmaAudioOutputStream::OnPushBufferComplete(BufferStatus status) {
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "chromecast/media/api/cma_backend.h" #include "chromecast/media/api/cma_backend.h"
#include "media/audio/audio_io.h" #include "media/audio/audio_io.h"
#include "media/base/audio_parameters.h" #include "media/base/audio_parameters.h"
#include "media/base/audio_timestamp_helper.h"
namespace base { namespace base {
class WaitableEvent; class WaitableEvent;
...@@ -36,6 +35,7 @@ class TaskRunnerImpl; ...@@ -36,6 +35,7 @@ class TaskRunnerImpl;
namespace media { namespace media {
class CmaAudioOutput;
class CmaBackendFactory; class CmaBackendFactory;
class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate { class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate {
...@@ -80,14 +80,12 @@ class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate { ...@@ -80,14 +80,12 @@ class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate {
const ::media::AudioParameters audio_params_; const ::media::AudioParameters audio_params_;
const std::string device_id_; const std::string device_id_;
CmaBackendFactory* const cma_backend_factory_; CmaBackendFactory* const cma_backend_factory_;
std::unique_ptr<CmaAudioOutput> output_;
base::Lock running_lock_; base::Lock running_lock_;
bool running_ = true; bool running_ = true;
CmaBackendState cma_backend_state_ = CmaBackendState::kUninitialized; CmaBackendState cma_backend_state_ = CmaBackendState::kUninitialized;
::media::AudioTimestampHelper timestamp_helper_;
const base::TimeDelta buffer_duration_; const base::TimeDelta buffer_duration_;
std::unique_ptr<TaskRunnerImpl> cma_backend_task_runner_;
std::unique_ptr<CmaBackend> cma_backend_;
std::unique_ptr<::media::AudioBus> audio_bus_; std::unique_ptr<::media::AudioBus> audio_bus_;
base::OneShotTimer push_timer_; base::OneShotTimer push_timer_;
bool push_in_progress_ = false; bool push_in_progress_ = false;
...@@ -96,7 +94,6 @@ class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate { ...@@ -96,7 +94,6 @@ class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate {
base::TimeTicks last_push_complete_time_; base::TimeTicks last_push_complete_time_;
base::TimeDelta last_rendering_delay_; base::TimeDelta last_rendering_delay_;
base::TimeDelta render_buffer_size_estimate_; base::TimeDelta render_buffer_size_estimate_;
CmaBackend::AudioDecoder* audio_decoder_ = nullptr;
::media::AudioOutputStream::AudioSourceCallback* source_callback_ = nullptr; ::media::AudioOutputStream::AudioSourceCallback* source_callback_ = nullptr;
THREAD_CHECKER(media_thread_checker_); THREAD_CHECKER(media_thread_checker_);
......
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