| Index: media/base/pipeline.cc
|
| diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
|
| index 55f8a408f3d392aca5e1065a93954fad5fd49c53..5e62868bcbb430c6b82c51d68a42b8d6ccd3c9cb 100644
|
| --- a/media/base/pipeline.cc
|
| +++ b/media/base/pipeline.cc
|
| @@ -22,6 +22,7 @@
|
| #include "media/base/filter_collection.h"
|
| #include "media/base/media_log.h"
|
| #include "media/base/video_decoder.h"
|
| +#include "media/base/video_decoder_config.h"
|
| #include "media/base/video_renderer.h"
|
|
|
| using base::TimeDelta;
|
| @@ -108,14 +109,15 @@ Pipeline::~Pipeline() {
|
| void Pipeline::Start(scoped_ptr<FilterCollection> collection,
|
| const PipelineStatusCB& ended_cb,
|
| const PipelineStatusCB& error_cb,
|
| - const PipelineStatusCB& start_cb) {
|
| + const PipelineStatusCB& seek_cb,
|
| + const ReadyStateCB& ready_state_cb) {
|
| base::AutoLock auto_lock(lock_);
|
| CHECK(!running_) << "Media pipeline is already running";
|
|
|
| running_ = true;
|
| message_loop_->PostTask(FROM_HERE, base::Bind(
|
| &Pipeline::StartTask, this, base::Passed(&collection),
|
| - ended_cb, error_cb, start_cb));
|
| + ended_cb, error_cb, seek_cb, ready_state_cb));
|
| }
|
|
|
| void Pipeline::Stop(const base::Closure& stop_cb) {
|
| @@ -281,12 +283,14 @@ void Pipeline::ReportStatus(const PipelineStatusCB& cb, PipelineStatus status) {
|
| error_cb_.Reset();
|
| }
|
|
|
| -void Pipeline::FinishInitialization() {
|
| +void Pipeline::FinishSeek() {
|
| DCHECK(message_loop_->BelongsToCurrentThread());
|
| + seek_timestamp_ = kNoTimestamp();
|
| + seek_pending_ = false;
|
| +
|
| // Execute the seek callback, if present. Note that this might be the
|
| // initial callback passed into Start().
|
| ReportStatus(seek_cb_, status_);
|
| - seek_timestamp_ = kNoTimestamp();
|
| seek_cb_.Reset();
|
| }
|
|
|
| @@ -551,7 +555,8 @@ void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) {
|
| void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection,
|
| const PipelineStatusCB& ended_cb,
|
| const PipelineStatusCB& error_cb,
|
| - const PipelineStatusCB& start_cb) {
|
| + const PipelineStatusCB& seek_cb,
|
| + const ReadyStateCB& ready_state_cb) {
|
| DCHECK(message_loop_->BelongsToCurrentThread());
|
| CHECK_EQ(kCreated, state_)
|
| << "Media pipeline cannot be started more than once";
|
| @@ -559,7 +564,8 @@ void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection,
|
| filter_collection_ = filter_collection.Pass();
|
| ended_cb_ = ended_cb;
|
| error_cb_ = error_cb;
|
| - seek_cb_ = start_cb;
|
| + seek_cb_ = seek_cb;
|
| + ready_state_cb_ = ready_state_cb;
|
|
|
| // Kick off initialization.
|
| pipeline_init_state_.reset(new PipelineInitState());
|
| @@ -625,9 +631,15 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
|
| // Assuming audio renderer was created, create video renderer.
|
| if (state_ == kInitAudioRenderer) {
|
| SetState(kInitVideoRenderer);
|
| - if (InitializeVideoRenderer(demuxer_->GetStream(DemuxerStream::VIDEO))) {
|
| + scoped_refptr<DemuxerStream> video_stream =
|
| + demuxer_->GetStream(DemuxerStream::VIDEO);
|
| + if (InitializeVideoRenderer(video_stream)) {
|
| base::AutoLock auto_lock(lock_);
|
| has_video_ = true;
|
| +
|
| + // Get an initial natural size so we have something when we signal
|
| + // the kHaveMetadata ready state.
|
| + natural_size_ = video_stream->video_decoder_config().natural_size();
|
| return;
|
| }
|
| }
|
| @@ -647,6 +659,9 @@ void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
|
| PlaybackRateChangedTask(GetPlaybackRate());
|
| VolumeChangedTask(GetVolume());
|
|
|
| + if (!ready_state_cb_.is_null())
|
| + ready_state_cb_.Run(kHaveMetadata);
|
| +
|
| // 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;
|
| @@ -904,10 +919,14 @@ void Pipeline::FilterStateTransitionTask() {
|
| NOTREACHED() << "Unexpected state: " << state_;
|
| }
|
| } else if (state_ == kStarted) {
|
| - FinishInitialization();
|
|
|
| - // Finally, complete the seek.
|
| - seek_pending_ = false;
|
| + // Fire canplaythrough immediately after playback begins because of
|
| + // crbug.com/106480.
|
| + // TODO(vrk): set ready state to HaveFutureData when bug above is fixed.
|
| + if (!ready_state_cb_.is_null() && status_ == PIPELINE_OK)
|
| + ready_state_cb_.Run(kHaveEnoughData);
|
| +
|
| + FinishSeek();
|
|
|
| // If a playback rate change was requested during a seek, do it now that
|
| // the seek has compelted.
|
| @@ -1143,7 +1162,7 @@ void Pipeline::TearDownPipeline() {
|
| SetState(kStopping);
|
| DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
|
|
|
| - FinishInitialization();
|
| + FinishSeek();
|
| break;
|
|
|
| case kPausing:
|
| @@ -1153,10 +1172,8 @@ void Pipeline::TearDownPipeline() {
|
| SetState(kStopping);
|
| DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
|
|
|
| - if (seek_pending_) {
|
| - seek_pending_ = false;
|
| - FinishInitialization();
|
| - }
|
| + if (seek_pending_)
|
| + FinishSeek();
|
|
|
| break;
|
|
|
|
|