summaryrefslogtreecommitdiffstats
path: root/media/base/pipeline.cc
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-20 06:01:16 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-20 06:01:16 +0000
commitff6256104abc7e766684f28ef4c42b945fd3225e (patch)
tree6ef0af0880affb4deb5139d594d787797be10eef /media/base/pipeline.cc
parent35daebe09bf03548ca99e58bc6ebb57d5b7a520d (diff)
downloadchromium_src-ff6256104abc7e766684f28ef4c42b945fd3225e.zip
chromium_src-ff6256104abc7e766684f28ef4c42b945fd3225e.tar.gz
chromium_src-ff6256104abc7e766684f28ef4c42b945fd3225e.tar.bz2
Move AudioRenderer out of Filter heirarchy.
BUG=108341 TEST=none Review URL: https://chromiumcodereview.appspot.com/10753021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147619 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/pipeline.cc')
-rw-r--r--media/base/pipeline.cc186
1 files changed, 104 insertions, 82 deletions
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
index 2b26541..1000747 100644
--- a/media/base/pipeline.cc
+++ b/media/base/pipeline.cc
@@ -17,6 +17,7 @@
#include "base/synchronization/condition_variable.h"
#include "media/base/audio_decoder.h"
#include "media/base/audio_renderer.h"
+#include "media/base/callback_util.h"
#include "media/base/clock.h"
#include "media/base/composite_filter.h"
#include "media/base/filter_collection.h"
@@ -64,7 +65,6 @@ media::PipelineStatus PipelineStatusNotification::status() {
struct Pipeline::PipelineInitState {
scoped_refptr<AudioDecoder> audio_decoder;
scoped_refptr<VideoDecoder> video_decoder;
- scoped_refptr<AudioRenderer> audio_renderer;
scoped_refptr<VideoRenderer> video_renderer;
scoped_refptr<CompositeFilter> composite;
};
@@ -317,6 +317,7 @@ bool Pipeline::IsPipelineSeeking() {
}
void Pipeline::ReportStatus(const PipelineStatusCB& cb, PipelineStatus status) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
if (cb.is_null())
return;
cb.Run(status);
@@ -390,6 +391,14 @@ TimeDelta Pipeline::GetDuration() const {
return GetMediaDuration();
}
+void Pipeline::OnAudioDisabled() {
+ DCHECK(IsRunning());
+ message_loop_->PostTask(FROM_HERE, base::Bind(
+ &Pipeline::AudioDisabledTask, this));
+ media_log_->AddEvent(
+ media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
+}
+
void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
DCHECK(time <= max_time);
DCHECK(IsRunning());
@@ -460,6 +469,61 @@ TimeDelta Pipeline::TimeForByteOffset_Locked(int64 byte_offset) const {
return time_offset;
}
+void Pipeline::DoPause(const base::Closure& done_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
+
+ if (audio_renderer_)
+ closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_));
+
+ if (pipeline_filter_)
+ closures->push(base::Bind(&Filter::Pause, pipeline_filter_));
+
+ RunInSeries(closures.Pass(), done_cb);
+}
+
+void Pipeline::DoFlush(const base::Closure& done_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
+
+ if (audio_renderer_)
+ closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_));
+
+ if (pipeline_filter_)
+ closures->push(base::Bind(&Filter::Flush, pipeline_filter_));
+
+ RunInParallel(closures.Pass(), done_cb);
+}
+
+void Pipeline::DoPlay(const base::Closure& done_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
+
+ if (audio_renderer_)
+ closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_));
+
+ if (pipeline_filter_)
+ closures->push(base::Bind(&Filter::Play, pipeline_filter_));
+
+ RunInSeries(closures.Pass(), done_cb);
+}
+
+void Pipeline::DoStop(const base::Closure& done_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
+
+ if (demuxer_)
+ closures->push(base::Bind(&Demuxer::Stop, demuxer_));
+
+ if (audio_renderer_)
+ closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_));
+
+ if (pipeline_filter_)
+ closures->push(base::Bind(&Filter::Stop, pipeline_filter_));
+
+ RunInSeries(closures.Pass(), done_cb);
+}
+
void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
DCHECK(IsRunning());
base::AutoLock auto_lock(lock_);
@@ -491,16 +555,6 @@ void Pipeline::NotifyEnded() {
media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
}
-void Pipeline::DisableAudioRenderer() {
- DCHECK(IsRunning());
-
- // Disable renderer on the message loop.
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &Pipeline::DisableAudioRendererTask, this));
- media_log_->AddEvent(
- media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
-}
-
// Called from any thread.
void Pipeline::OnFilterInitialize(PipelineStatus status) {
// Continue the initialize task by proceeding to the next stage.
@@ -658,12 +712,13 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
PlaybackRateChangedTask(GetPlaybackRate());
VolumeChangedTask(GetVolume());
- // Fire a seek request to get the renderers to preroll. We don't need to
- // tell the demuxer to seek since it should already be at the start.
+ // Fire a seek request to get the renderers to preroll. We can skip a seek
+ // here as the demuxer should be at the start of the stream.
seek_pending_ = true;
SetState(kSeeking);
seek_timestamp_ = demuxer_->GetStartTime();
- OnDemuxerSeekDone(seek_timestamp_, PIPELINE_OK);
+ DoSeek(seek_timestamp_, true,
+ base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this));
}
}
@@ -752,9 +807,11 @@ void Pipeline::PlaybackRateChangedTask(float playback_rate) {
// hasn't completed yet, the playback rate will be set when initialization
// completes.
if (pipeline_filter_) {
- DCHECK(demuxer_);
demuxer_->SetPlaybackRate(playback_rate);
pipeline_filter_->SetPlaybackRate(playback_rate);
+
+ if (audio_renderer_)
+ audio_renderer_->SetPlaybackRate(playback_rate_);
}
}
@@ -800,8 +857,7 @@ void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
if (clock_->IsPlaying())
clock_->Pause();
}
- pipeline_filter_->Pause(
- base::Bind(&Pipeline::OnFilterStateTransition, this));
+ DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
}
void Pipeline::NotifyEndedTask() {
@@ -841,7 +897,7 @@ void Pipeline::NotifyEndedTask() {
ReportStatus(ended_cb_, status_);
}
-void Pipeline::DisableAudioRendererTask() {
+void Pipeline::AudioDisabledTask() {
DCHECK(message_loop_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
@@ -888,16 +944,14 @@ void Pipeline::FilterStateTransitionTask() {
// Carry out the action for the current state.
if (TransientState(state_)) {
if (state_ == kPausing) {
- pipeline_filter_->Pause(
- base::Bind(&Pipeline::OnFilterStateTransition, this));
+ DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
} else if (state_ == kFlushing) {
- pipeline_filter_->Flush(
- base::Bind(&Pipeline::OnFilterStateTransition, this));
+ DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this));
} else if (state_ == kSeeking) {
- DoSeek(seek_timestamp_);
+ DoSeek(seek_timestamp_, false,
+ base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this));
} else if (state_ == kStarting) {
- pipeline_filter_->Play(
- base::Bind(&Pipeline::OnFilterStateTransition, this));
+ DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this));
} else if (state_ == kStopping) {
DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this));
} else {
@@ -943,8 +997,7 @@ void Pipeline::TeardownStateTransitionTask() {
break;
case kPausing:
SetState(kFlushing);
- pipeline_filter_->Flush(
- base::Bind(&Pipeline::OnTeardownStateTransition, this));
+ DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
break;
case kFlushing:
SetState(kStopping);
@@ -1092,23 +1145,20 @@ bool Pipeline::InitializeAudioRenderer(
if (!decoder)
return false;
- filter_collection_->SelectAudioRenderer(
- &pipeline_init_state_->audio_renderer);
- if (!pipeline_init_state_->audio_renderer) {
+ filter_collection_->SelectAudioRenderer(&audio_renderer_);
+ if (!audio_renderer_) {
SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
return false;
}
- pipeline_init_state_->composite->AddFilter(
- pipeline_init_state_->audio_renderer);
-
- pipeline_init_state_->audio_renderer->Initialize(
+ audio_renderer_->Initialize(
decoder,
base::Bind(&Pipeline::OnFilterInitialize, this),
base::Bind(&Pipeline::OnAudioUnderflow, this),
- base::Bind(&Pipeline::OnAudioTimeUpdate, this));
-
- audio_renderer_ = pipeline_init_state_->audio_renderer;
+ base::Bind(&Pipeline::OnAudioTimeUpdate, this),
+ base::Bind(&Pipeline::NotifyEnded, this),
+ base::Bind(&Pipeline::OnAudioDisabled, this),
+ base::Bind(&Pipeline::SetError, this));
return true;
}
@@ -1194,8 +1244,7 @@ void Pipeline::TearDownPipeline() {
case kStarted:
case kEnded:
SetState(kPausing);
- pipeline_filter_->Pause(
- base::Bind(&Pipeline::OnTeardownStateTransition, this));
+ DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this));
break;
case kStopping:
@@ -1207,53 +1256,26 @@ void Pipeline::TearDownPipeline() {
};
}
-void Pipeline::DoStop(const base::Closure& callback) {
- if (demuxer_) {
- demuxer_->Stop(base::Bind(
- &Pipeline::OnDemuxerStopDone, this, callback));
- return;
- }
-
- OnDemuxerStopDone(callback);
-}
-
-void Pipeline::OnDemuxerStopDone(const base::Closure& callback) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &Pipeline::OnDemuxerStopDone, this, callback));
- return;
- }
-
- if (pipeline_filter_) {
- pipeline_filter_->Stop(callback);
- return;
- }
-
- callback.Run();
-}
-
-void Pipeline::DoSeek(TimeDelta seek_timestamp) {
- demuxer_->Seek(seek_timestamp, base::Bind(
- &Pipeline::OnDemuxerSeekDone, this, seek_timestamp));
-}
+void Pipeline::DoSeek(base::TimeDelta seek_timestamp,
+ bool skip_demuxer_seek,
+ const PipelineStatusCB& done_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
+ new std::queue<PipelineStatusCBFunc>());
-void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp,
- PipelineStatus status) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status));
- return;
- }
+ if (!skip_demuxer_seek)
+ status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp));
- PipelineStatusCB done_cb =
- base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this);
+ if (audio_renderer_)
+ status_cbs->push(base::Bind(
+ &AudioRenderer::Seek, audio_renderer_, seek_timestamp));
- if (status == PIPELINE_OK && pipeline_filter_) {
- pipeline_filter_->Seek(seek_timestamp, done_cb);
- return;
- }
+ if (pipeline_filter_)
+ status_cbs->push(base::Bind(
+ &Filter::Seek, pipeline_filter_, seek_timestamp));
- ReportStatus(done_cb, status);
+ RunInSeriesWithStatus(status_cbs.Pass(), base::Bind(
+ &Pipeline::ReportStatus, this, done_cb));
}
void Pipeline::OnAudioUnderflow() {