Commit 7c856abf authored by fischman@chromium.org's avatar fischman@chromium.org

Remove AudioDecoder from the Filter heirarchy.

BUG=108339
TEST=none

Review URL: https://chromiumcodereview.appspot.com/9325044

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120718 0039d316-1c4b-4281-b951-d872f2087c98
parent 16de8d51
// Copyright (c) 2012 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 "media/base/audio_decoder.h"
namespace media {
AudioDecoder::AudioDecoder() {}
AudioDecoder::~AudioDecoder() {}
} // namespace media
// Copyright (c) 2012 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 MEDIA_BASE_AUDIO_DECODER_H_
#define MEDIA_BASE_AUDIO_DECODER_H_
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "media/base/channel_layout.h"
#include "media/base/pipeline_status.h"
#include "media/base/media_export.h"
namespace media {
class Buffer;
class DemuxerStream;
class MEDIA_EXPORT AudioDecoder
: public base::RefCountedThreadSafe<AudioDecoder> {
public:
// Initialize an AudioDecoder with the given DemuxerStream, executing the
// callback upon completion.
// stats_callback is used to update global pipeline statistics.
virtual void Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback) = 0;
// Request samples to be decoded and returned via the provided callback.
// Only one read may be in flight at any given time.
//
// Implementations guarantee that the callback will not be called from within
// this method.
//
// Non-NULL sample buffer pointers will contain decoded audio data or may
// indicate the end of the stream. A NULL buffer pointer indicates an aborted
// Read(). This can happen if the DemuxerStream gets flushed and doesn't have
// any more data to return.
typedef base::Callback<void(scoped_refptr<Buffer>)> ReadCB;
virtual void Read(const ReadCB& callback) = 0;
// Reset decoder state, dropping any queued encoded data.
virtual void Reset(const base::Closure& closure) = 0;
// Returns various information about the decoded audio format.
virtual int bits_per_channel() = 0;
virtual ChannelLayout channel_layout() = 0;
virtual int samples_per_second() = 0;
protected:
friend class base::RefCountedThreadSafe<AudioDecoder>;
virtual ~AudioDecoder();
AudioDecoder();
DISALLOW_COPY_AND_ASSIGN(AudioDecoder);
};
} // namespace media
#endif // MEDIA_BASE_AUDIO_DECODER_H_
......@@ -5,6 +5,7 @@
#include "media/base/filter_collection.h"
#include "base/logging.h"
#include "media/base/audio_decoder.h"
namespace media {
......@@ -25,8 +26,8 @@ void FilterCollection::AddVideoDecoder(VideoDecoder* filter) {
AddFilter(VIDEO_DECODER, filter);
}
void FilterCollection::AddAudioDecoder(AudioDecoder* filter) {
AddFilter(AUDIO_DECODER, filter);
void FilterCollection::AddAudioDecoder(AudioDecoder* audio_decoder) {
audio_decoders_.push_back(audio_decoder);
}
void FilterCollection::AddVideoRenderer(VideoRenderer* filter) {
......@@ -38,11 +39,12 @@ void FilterCollection::AddAudioRenderer(AudioRenderer* filter) {
}
bool FilterCollection::IsEmpty() const {
return filters_.empty();
return filters_.empty() && audio_decoders_.empty();
}
void FilterCollection::Clear() {
filters_.clear();
audio_decoders_.clear();
}
void FilterCollection::SelectVideoDecoder(
......@@ -50,9 +52,13 @@ void FilterCollection::SelectVideoDecoder(
SelectFilter<VIDEO_DECODER>(filter_out);
}
void FilterCollection::SelectAudioDecoder(
scoped_refptr<AudioDecoder>* filter_out) {
SelectFilter<AUDIO_DECODER>(filter_out);
void FilterCollection::SelectAudioDecoder(scoped_refptr<AudioDecoder>* out) {
if (audio_decoders_.empty()) {
*out = NULL;
return;
}
*out = audio_decoders_.front();
audio_decoders_.pop_front();
}
void FilterCollection::SelectVideoRenderer(
......
......@@ -13,6 +13,8 @@
namespace media {
class AudioDecoder;
// This is a collection of Filter objects used to form a media playback
// pipeline. See src/media/base/pipeline.h for more information.
class MEDIA_EXPORT FilterCollection {
......@@ -26,7 +28,7 @@ class MEDIA_EXPORT FilterCollection {
// Adds a filter to the collection.
void AddVideoDecoder(VideoDecoder* filter);
void AddAudioDecoder(AudioDecoder* filter);
void AddAudioDecoder(AudioDecoder* audio_decoder);
void AddVideoRenderer(VideoRenderer* filter);
void AddAudioRenderer(AudioRenderer* filter);
......@@ -41,7 +43,7 @@ class MEDIA_EXPORT FilterCollection {
// If a filter is returned it is removed from the collection.
// Filters are selected in FIFO order.
void SelectVideoDecoder(scoped_refptr<VideoDecoder>* filter_out);
void SelectAudioDecoder(scoped_refptr<AudioDecoder>* filter_out);
void SelectAudioDecoder(scoped_refptr<AudioDecoder>* out);
void SelectVideoRenderer(scoped_refptr<VideoRenderer>* filter_out);
void SelectAudioRenderer(scoped_refptr<AudioRenderer>* filter_out);
......@@ -50,7 +52,6 @@ class MEDIA_EXPORT FilterCollection {
// the following types. This is used to mark, identify, and support
// downcasting of different filter types stored in the filters_ list.
enum FilterType {
AUDIO_DECODER,
VIDEO_DECODER,
AUDIO_RENDERER,
VIDEO_RENDERER,
......@@ -61,6 +62,7 @@ class MEDIA_EXPORT FilterCollection {
typedef std::list<FilterListElement> FilterList;
FilterList filters_;
scoped_ptr<DemuxerFactory> demuxer_factory_;
std::list<scoped_refptr<AudioDecoder> > audio_decoders_;
// Helper function that adds a filter to the filter list.
void AddFilter(FilterType filter_type, Filter* filter);
......
......@@ -81,8 +81,4 @@ bool VideoDecoder::HasAlpha() const {
void VideoDecoder::PrepareForShutdownHack() {}
AudioDecoder::AudioDecoder() {}
AudioDecoder::~AudioDecoder() {}
} // namespace media
......@@ -38,6 +38,7 @@
namespace media {
class AudioDecoder;
class Buffer;
class Decoder;
class DemuxerStream;
......@@ -55,9 +56,6 @@ typedef base::Callback<void(PipelineStatus)> FilterStatusCB;
MEDIA_EXPORT void ResetAndRunCB(FilterStatusCB* cb, PipelineStatus status);
MEDIA_EXPORT void ResetAndRunCB(base::Closure* cb);
// Used for updating pipeline statistics.
typedef base::Callback<void(const PipelineStatistics&)> StatisticsCallback;
class MEDIA_EXPORT Filter : public base::RefCountedThreadSafe<Filter> {
public:
Filter();
......@@ -169,39 +167,6 @@ class MEDIA_EXPORT VideoDecoder : public Filter {
};
class MEDIA_EXPORT AudioDecoder : public Filter {
public:
// Initialize a AudioDecoder with the given DemuxerStream, executing the
// callback upon completion.
// stats_callback is used to update global pipeline statistics.
virtual void Initialize(DemuxerStream* stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback) = 0;
// Request samples to be decoded and returned via the provided callback.
// Only one read may be in flight at any given time.
//
// Implementations guarantee that the callback will not be called from within
// this method.
//
// Non-NULL sample buffer pointers will contain decoded audio data or may
// indicate the end of the stream. A NULL buffer pointer indicates an aborted
// Read(). This can happen if the DemuxerStream gets flushed and doesn't have
// any more data to return.
typedef base::Callback<void(scoped_refptr<Buffer>)> ReadCB;
virtual void Read(const ReadCB& callback) = 0;
// Returns various information about the decoded audio format.
virtual int bits_per_channel() = 0;
virtual ChannelLayout channel_layout() = 0;
virtual int samples_per_second() = 0;
protected:
AudioDecoder();
virtual ~AudioDecoder();
};
class MEDIA_EXPORT VideoRenderer : public Filter {
public:
// Used to update the pipeline's clock time. The parameter is the time that
......@@ -234,7 +199,7 @@ class MEDIA_EXPORT AudioRenderer : public Filter {
// If the |underflow_callback| is called ResumeAfterUnderflow() must be called
// to resume playback. Pause(), Seek(), or Stop() cancels the underflow
// condition.
virtual void Initialize(AudioDecoder* decoder,
virtual void Initialize(const scoped_refptr<AudioDecoder>& decoder,
const PipelineStatusCB& init_callback,
const base::Closure& underflow_callback,
const AudioTimeCB& time_cb) = 0;
......
......@@ -16,6 +16,7 @@
#include <string>
#include "base/callback.h"
#include "media/base/audio_decoder.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/demuxer.h"
#include "media/base/filters.h"
......@@ -203,21 +204,16 @@ class MockAudioDecoder : public AudioDecoder {
public:
MockAudioDecoder();
// Filter implementation.
MOCK_METHOD1(Stop, void(const base::Closure& callback));
MOCK_METHOD1(SetPlaybackRate, void(float playback_rate));
MOCK_METHOD2(Seek, void(base::TimeDelta time, const FilterStatusCB& cb));
MOCK_METHOD0(OnAudioRendererDisabled, void());
// AudioDecoder implementation.
MOCK_METHOD3(Initialize, void(DemuxerStream* stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback));
MOCK_METHOD1(Read, void(const ReadCB& callback));
MOCK_METHOD3(Initialize, void(const scoped_refptr<DemuxerStream>&,
const PipelineStatusCB&,
const StatisticsCallback&));
MOCK_METHOD1(Read, void(const ReadCB&));
MOCK_METHOD1(ProduceAudioSamples, void(scoped_refptr<Buffer>));
MOCK_METHOD0(bits_per_channel, int(void));
MOCK_METHOD0(channel_layout, ChannelLayout(void));
MOCK_METHOD0(samples_per_second, int(void));
MOCK_METHOD1(Reset, void(const base::Closure&));
protected:
virtual ~MockAudioDecoder();
......@@ -266,7 +262,7 @@ class MockAudioRenderer : public AudioRenderer {
MOCK_METHOD0(OnAudioRendererDisabled, void());
// AudioRenderer implementation.
MOCK_METHOD4(Initialize, void(AudioDecoder* decoder,
MOCK_METHOD4(Initialize, void(const scoped_refptr<AudioDecoder>& decoder,
const PipelineStatusCB& init_callback,
const base::Closure& underflow_callback,
const AudioTimeCB& time_cb));
......
......@@ -14,9 +14,12 @@
#include "base/stl_util.h"
#include "base/string_util.h"
#include "base/synchronization/condition_variable.h"
#include "media/base/audio_decoder.h"
#include "media/base/clock.h"
#include "media/base/composite_filter.h"
#include "media/base/composite_filter.h"
#include "media/base/filter_collection.h"
#include "media/base/filters.h"
#include "media/base/media_log.h"
namespace media {
......@@ -54,11 +57,10 @@ media::PipelineStatus PipelineStatusNotification::status() {
return status_;
}
class Pipeline::PipelineInitState {
public:
scoped_refptr<AudioDecoder> audio_decoder_;
scoped_refptr<VideoDecoder> video_decoder_;
scoped_refptr<CompositeFilter> composite_;
struct Pipeline::PipelineInitState {
scoped_refptr<AudioDecoder> audio_decoder;
scoped_refptr<VideoDecoder> video_decoder;
scoped_refptr<CompositeFilter> composite;
};
Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log)
......@@ -621,8 +623,8 @@ void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection,
// Kick off initialization.
pipeline_init_state_.reset(new PipelineInitState());
pipeline_init_state_->composite_ = new CompositeFilter(message_loop_);
pipeline_init_state_->composite_->set_host(this);
pipeline_init_state_->composite = new CompositeFilter(message_loop_);
pipeline_init_state_->composite->set_host(this);
SetState(kInitDemuxer);
InitializeDemuxer();
......@@ -652,8 +654,8 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
// Currently only VideoDecoders have a recoverable error code.
if (state_ == kInitVideoDecoder &&
last_stage_status == DECODER_ERROR_NOT_SUPPORTED) {
pipeline_init_state_->composite_->RemoveFilter(
pipeline_init_state_->video_decoder_.get());
pipeline_init_state_->composite->RemoveFilter(
pipeline_init_state_->video_decoder.get());
state_ = kInitAudioRenderer;
} else {
SetError(last_stage_status);
......@@ -683,7 +685,7 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
SetState(kInitAudioRenderer);
// Returns false if there's no audio stream.
if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) {
if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) {
base::AutoLock auto_lock(lock_);
has_audio_ = true;
return;
......@@ -701,7 +703,7 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
// Assuming video decoder was created, create video renderer.
if (state_ == kInitVideoDecoder) {
SetState(kInitVideoRenderer);
if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) {
if (InitializeVideoRenderer(pipeline_init_state_->video_decoder)) {
base::AutoLock auto_lock(lock_);
has_video_ = true;
return;
......@@ -717,7 +719,7 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
// Clear the collection of filters.
filter_collection_->Clear();
pipeline_filter_ = pipeline_init_state_->composite_;
pipeline_filter_ = pipeline_init_state_->composite;
// Clear init state since we're done initializing.
pipeline_init_state_.reset();
......@@ -1029,7 +1031,7 @@ void Pipeline::FilterStateTransitionTask() {
// Start monitoring rate of downloading.
int bitrate = 0;
if (demuxer_.get()) {
if (demuxer_) {
bitrate = demuxer_->GetBitrate();
local_source_ = demuxer_->IsLocalSource();
streaming_ = !demuxer_->IsSeekable();
......@@ -1116,7 +1118,7 @@ void Pipeline::FinishDestroyingFiltersTask() {
}
bool Pipeline::PrepareFilter(scoped_refptr<Filter> filter) {
bool ret = pipeline_init_state_->composite_->AddFilter(filter.get());
bool ret = pipeline_init_state_->composite->AddFilter(filter.get());
if (!ret)
SetError(PIPELINE_ERROR_INITIALIZATION_FAILED);
return ret;
......@@ -1171,19 +1173,14 @@ bool Pipeline::InitializeAudioDecoder(
if (!stream)
return false;
scoped_refptr<AudioDecoder> audio_decoder;
filter_collection_->SelectAudioDecoder(&audio_decoder);
filter_collection_->SelectAudioDecoder(&pipeline_init_state_->audio_decoder);
if (!audio_decoder) {
if (!pipeline_init_state_->audio_decoder) {
SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
return false;
}
if (!PrepareFilter(audio_decoder))
return false;
pipeline_init_state_->audio_decoder_ = audio_decoder;
audio_decoder->Initialize(
pipeline_init_state_->audio_decoder->Initialize(
stream,
base::Bind(&Pipeline::OnFilterInitialize, this),
base::Bind(&Pipeline::OnUpdateStatistics, this));
......@@ -1214,7 +1211,7 @@ bool Pipeline::InitializeVideoDecoder(
if (!PrepareFilter(video_decoder_))
return false;
pipeline_init_state_->video_decoder_ = video_decoder_;
pipeline_init_state_->video_decoder = video_decoder_;
video_decoder_->Initialize(
stream,
base::Bind(&Pipeline::OnFilterInitialize, this),
......@@ -1300,7 +1297,7 @@ void Pipeline::TearDownPipeline() {
case kInitVideoDecoder:
case kInitVideoRenderer:
// Make it look like initialization was successful.
pipeline_filter_ = pipeline_init_state_->composite_;
pipeline_filter_ = pipeline_init_state_->composite;
pipeline_init_state_.reset();
filter_collection_.reset();
......
......@@ -35,21 +35,6 @@ class MediaLog;
class VideoDecoder;
class VideoRenderer;
// TODO(scherkus): this should be moved alongside host interface defintions.
struct PipelineStatistics {
PipelineStatistics()
: audio_bytes_decoded(0),
video_bytes_decoded(0),
video_frames_decoded(0),
video_frames_dropped(0) {
}
uint32 audio_bytes_decoded; // Should be uint64?
uint32 video_bytes_decoded; // Should be uint64?
uint32 video_frames_decoded;
uint32 video_frames_dropped;
};
enum NetworkEvent {
DOWNLOAD_CONTINUED,
DOWNLOAD_PAUSED,
......@@ -571,6 +556,9 @@ class MEDIA_EXPORT Pipeline
PipelineStatus status_;
// Whether the media contains rendered audio and video streams.
// TODO(fischman,scherkus): replace these with checks for
// {audio,video}_decoder_ once extraction of {Audio,Video}Decoder from the
// Filter heirarchy is done.
bool has_audio_;
bool has_video_;
......@@ -628,7 +616,7 @@ class MEDIA_EXPORT Pipeline
// Helper class that stores filter references during pipeline
// initialization.
class PipelineInitState;
struct PipelineInitState;
scoped_ptr<PipelineInitState> pipeline_init_state_;
// Statistics.
......
......@@ -37,6 +37,24 @@ enum PipelineStatus {
typedef base::Callback<void(PipelineStatus)> PipelineStatusCB;
// TODO(scherkus): this should be moved alongside host interface definitions.
struct PipelineStatistics {
PipelineStatistics()
: audio_bytes_decoded(0),
video_bytes_decoded(0),
video_frames_decoded(0),
video_frames_dropped(0) {
}
uint32 audio_bytes_decoded; // Should be uint64?
uint32 video_bytes_decoded; // Should be uint64?
uint32 video_frames_decoded;
uint32 video_frames_dropped;
};
// Used for updating pipeline statistics.
typedef base::Callback<void(const PipelineStatistics&)> StatisticsCallback;
} // namespace media
#endif // MEDIA_BASE_PIPELINE_STATUS_H_
......@@ -140,14 +140,9 @@ class PipelineTest : public ::testing::Test {
}
// Sets up expectations to allow the audio decoder to initialize.
void InitializeAudioDecoder(MockDemuxerStream* stream) {
void InitializeAudioDecoder(const scoped_refptr<DemuxerStream>& stream) {
EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _))
.WillOnce(Invoke(&RunPipelineStatusCB3));
EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(0.0f));
EXPECT_CALL(*mocks_->audio_decoder(), Seek(base::TimeDelta(), _))
.WillOnce(Invoke(&RunFilterStatusCB));
EXPECT_CALL(*mocks_->audio_decoder(), Stop(_))
.WillOnce(Invoke(&RunStopFilterCallback));
}
// Sets up expectations to allow the video renderer to initialize.
......@@ -166,13 +161,13 @@ class PipelineTest : public ::testing::Test {
// Sets up expectations to allow the audio renderer to initialize.
void InitializeAudioRenderer(bool disable_after_init_callback = false) {
if (disable_after_init_callback) {
EXPECT_CALL(*mocks_->audio_renderer(),
Initialize(mocks_->audio_decoder(), _, _, _))
EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), _, _, _))
.WillOnce(DoAll(Invoke(&RunPipelineStatusCB4),
DisableAudioRenderer(mocks_->audio_renderer())));
} else {
EXPECT_CALL(*mocks_->audio_renderer(),
Initialize(mocks_->audio_decoder(), _, _, _))
EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), _, _, _))
.WillOnce(Invoke(&RunPipelineStatusCB4));
}
EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f));
......@@ -232,8 +227,6 @@ class PipelineTest : public ::testing::Test {
.WillOnce(Invoke(&RunFilterStatusCB));
if (audio_stream_) {
EXPECT_CALL(*mocks_->audio_decoder(), Seek(seek_time, _))
.WillOnce(Invoke(&RunFilterStatusCB));
EXPECT_CALL(*mocks_->audio_renderer(), Seek(seek_time, _))
.WillOnce(Invoke(&RunFilterStatusCB));
}
......@@ -573,8 +566,6 @@ TEST_F(PipelineTest, DisableAudioRenderer) {
.WillOnce(DisableAudioRenderer(mocks_->audio_renderer()));
EXPECT_CALL(*mocks_->demuxer(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->audio_decoder(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->audio_renderer(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->video_decoder(),
......@@ -607,8 +598,6 @@ TEST_F(PipelineTest, DisableAudioRendererDuringInit) {
EXPECT_CALL(*mocks_->demuxer(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->audio_decoder(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->audio_renderer(),
OnAudioRendererDisabled());
EXPECT_CALL(*mocks_->video_decoder(),
......@@ -700,7 +689,6 @@ TEST_F(PipelineTest, AudioStreamShorterThanVideo) {
float playback_rate = 1.0f;
EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate));
pipeline_->SetPlaybackRate(playback_rate);
......@@ -754,7 +742,6 @@ TEST_F(PipelineTest, ErrorDuringSeek) {
float playback_rate = 1.0f;
EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(playback_rate));
EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate));
pipeline_->SetPlaybackRate(playback_rate);
message_loop_.RunAllPending();
......
......@@ -51,6 +51,10 @@ void AudioRendererBase::Pause(const base::Closure& callback) {
}
}
void AudioRendererBase::Flush(const base::Closure& callback) {
decoder_->Reset(callback);
}
void AudioRendererBase::Stop(const base::Closure& callback) {
OnStop();
{
......@@ -84,7 +88,7 @@ void AudioRendererBase::Seek(base::TimeDelta time, const FilterStatusCB& cb) {
algorithm_->FlushBuffers();
}
void AudioRendererBase::Initialize(AudioDecoder* decoder,
void AudioRendererBase::Initialize(const scoped_refptr<AudioDecoder>& decoder,
const PipelineStatusCB& init_callback,
const base::Closure& underflow_callback,
const AudioTimeCB& audio_time_cb) {
......
......@@ -22,6 +22,7 @@
#include <deque>
#include "base/synchronization/lock.h"
#include "media/base/audio_decoder.h"
#include "media/base/buffers.h"
#include "media/base/filters.h"
#include "media/filters/audio_renderer_algorithm_base.h"
......@@ -36,12 +37,12 @@ class MEDIA_EXPORT AudioRendererBase : public AudioRenderer {
// Filter implementation.
virtual void Play(const base::Closure& callback) OVERRIDE;
virtual void Pause(const base::Closure& callback) OVERRIDE;
virtual void Flush(const base::Closure& callback) OVERRIDE;
virtual void Stop(const base::Closure& callback) OVERRIDE;
virtual void Seek(base::TimeDelta time, const FilterStatusCB& cb) OVERRIDE;
// AudioRenderer implementation.
virtual void Initialize(AudioDecoder* decoder,
virtual void Initialize(const scoped_refptr<AudioDecoder>& decoder,
const PipelineStatusCB& init_callback,
const base::Closure& underflow_callback,
const AudioTimeCB& audio_time_cb) OVERRIDE;
......
......@@ -8,7 +8,6 @@
#include "media/base/audio_decoder_config.h"
#include "media/base/data_buffer.h"
#include "media/base/demuxer.h"
#include "media/base/filter_host.h"
#include "media/base/pipeline.h"
#include "media/ffmpeg/ffmpeg_common.h"
......@@ -59,8 +58,8 @@ FFmpegAudioDecoder::FFmpegAudioDecoder(MessageLoop* message_loop)
FFmpegAudioDecoder::~FFmpegAudioDecoder() {
av_free(decoded_audio_);
// XXX: should we require Stop() to be called? this might end up getting
// called on a random thread due to refcounting.
// TODO(scherkus): should we require Stop() to be called? this might end up
// getting called on a random thread due to refcounting.
if (codec_context_) {
av_free(codec_context_->extradata);
avcodec_close(codec_context_);
......@@ -68,23 +67,14 @@ FFmpegAudioDecoder::~FFmpegAudioDecoder() {
}
}
void FFmpegAudioDecoder::Flush(const base::Closure& callback) {
message_loop_->PostTask(
FROM_HERE,
base::Bind(&FFmpegAudioDecoder::DoFlush, this, callback));
}
void FFmpegAudioDecoder::Initialize(
DemuxerStream* stream,
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback) {
// TODO(scherkus): change Initialize() signature to pass |stream| as a
// scoped_refptr<>.
scoped_refptr<DemuxerStream> ref_stream(stream);
message_loop_->PostTask(
FROM_HERE,
base::Bind(&FFmpegAudioDecoder::DoInitialize, this,
ref_stream, callback, stats_callback));
stream, callback, stats_callback));
}
void FFmpegAudioDecoder::Read(const ReadCB& callback) {
......@@ -106,6 +96,11 @@ int FFmpegAudioDecoder::samples_per_second() {
return samples_per_second_;
}
void FFmpegAudioDecoder::Reset(const base::Closure& closure) {
message_loop_->PostTask(FROM_HERE, base::Bind(
&FFmpegAudioDecoder::DoReset, this, closure));
}
void FFmpegAudioDecoder::DoInitialize(
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& callback,
......@@ -148,10 +143,10 @@ void FFmpegAudioDecoder::DoInitialize(
callback.Run(PIPELINE_OK);
}
void FFmpegAudioDecoder::DoFlush(const base::Closure& callback) {
void FFmpegAudioDecoder::DoReset(const base::Closure& closure) {
avcodec_flush_buffers(codec_context_);
estimated_next_timestamp_ = kNoTimestamp();
callback.Run();
closure.Run();
}
void FFmpegAudioDecoder::DoRead(const ReadCB& callback) {
......
......@@ -8,7 +8,7 @@
#include <list>
#include "base/message_loop.h"
#include "media/base/filters.h"
#include "media/base/audio_decoder.h"
struct AVCodecContext;
......@@ -21,24 +21,22 @@ class MEDIA_EXPORT FFmpegAudioDecoder : public AudioDecoder {
explicit FFmpegAudioDecoder(MessageLoop* message_loop);
virtual ~FFmpegAudioDecoder();
// Filter implementation.
virtual void Flush(const base::Closure& callback) OVERRIDE;
// AudioDecoder implementation.
virtual void Initialize(DemuxerStream* stream,
virtual void Initialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback) OVERRIDE;
virtual void Read(const ReadCB& callback) OVERRIDE;
virtual int bits_per_channel() OVERRIDE;
virtual ChannelLayout channel_layout() OVERRIDE;
virtual int samples_per_second() OVERRIDE;
virtual void Reset(const base::Closure& closure) OVERRIDE;
private:
// Methods running on decoder thread.
void DoInitialize(const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& callback,
const StatisticsCallback& stats_callback);
void DoFlush(const base::Closure& callback);
void DoReset(const base::Closure& closure);
void DoRead(const ReadCB& callback);
void DoDecodeBuffer(const scoped_refptr<Buffer>& input);
......
......@@ -77,11 +77,6 @@ class FFmpegAudioDecoderTest : public testing::Test {
message_loop_.RunAllPending();
}
void Stop() {
decoder_->Stop(NewExpectedClosure());
message_loop_.RunAllPending();
}
void ReadPacket(const DemuxerStream::ReadCallback& read_callback) {
CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
......@@ -134,17 +129,6 @@ TEST_F(FFmpegAudioDecoderTest, Initialize) {
EXPECT_EQ(16, decoder_->bits_per_channel());
EXPECT_EQ(CHANNEL_LAYOUT_STEREO, decoder_->channel_layout());
EXPECT_EQ(44100, decoder_->samples_per_second());
Stop();
}
TEST_F(FFmpegAudioDecoderTest, Flush) {
Initialize();
decoder_->Flush(NewExpectedClosure());
message_loop_.RunAllPending();
Stop();
}
TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
......@@ -176,8 +160,6 @@ TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
Read();
ASSERT_EQ(4u, decoded_audio_.size());
ExpectEndOfStream(3);
Stop();
}
TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
......@@ -192,8 +174,6 @@ TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
EXPECT_EQ(decoded_audio_.size(), 1u);
EXPECT_TRUE(decoded_audio_[0].get() == NULL);
Stop();
}
} // namespace media
......@@ -96,6 +96,8 @@
'audio/win/wavein_input_win.h',
'audio/win/waveout_output_win.cc',
'audio/win/waveout_output_win.h',
'base/audio_decoder.cc',
'base/audio_decoder.h',
'base/audio_decoder_config.cc',
'base/audio_decoder_config.h',
'base/bitstream_buffer.h',
......
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