diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-02 17:56:27 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-02 17:56:27 +0000 |
commit | 9bfe9b82466e685d48b0c8fa296e94900155c689 (patch) | |
tree | cb348420ed91125842c1eda89e67b8b36b5b7164 | |
parent | 6d7406e0257912de103c719d8597554edb965271 (diff) | |
download | chromium_src-9bfe9b82466e685d48b0c8fa296e94900155c689.zip chromium_src-9bfe9b82466e685d48b0c8fa296e94900155c689.tar.gz chromium_src-9bfe9b82466e685d48b0c8fa296e94900155c689.tar.bz2 |
Remove DemuxerFactory and URL parameter from Pipeline.
Since Demuxers still require asynchronous initialization DemuxerFactory::Build() has been replaced with Demuxer::Initialize(). Since FFmpegDemuxer is the only Demuxer requiring a DataSource it is now passed in via FFmpegDemuxer's constructor.
Now that Demuxer::set_host() is guaranteed to be called prior to initialization we're able to tighten up some code inside ChunkDemuxer. We should still nuke set_host() (see bug 111585) but I'll leave that for a future CL.
BUG=110804, 110809
Review URL: https://chromiumcodereview.appspot.com/9860027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130165 0039d316-1c4b-4281-b951-d872f2087c98
36 files changed, 320 insertions, 670 deletions
diff --git a/chrome/test/data/prerender/prerender_html5_common.js b/chrome/test/data/prerender/prerender_html5_common.js index 09d196b..2a4c0a4 100644 --- a/chrome/test/data/prerender/prerender_html5_common.js +++ b/chrome/test/data/prerender/prerender_html5_common.js @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -20,7 +20,6 @@ function assert(bool) { var canPlaySeen = false; var playingSeen = false; var canPlayThroughSeen = false; -var stalledSeen = false; var loadStartSeen = false; var hasError = false; @@ -49,16 +48,16 @@ function mediaEventHandler(e) { loadStartSeen = true; break; case 'stalled': - assert(loadStartSeen); - stalledSeen = true; + // We should never see a stalled event during the display portion of the + // test. + assert(false); break; } - var stallDone = !testNetworkEvents || stalledSeen; var progressDone = (willPlay && canPlayThroughSeen && playingSeen) || (!willPlay && canPlayThroughSeen && !playingSeen); - if (stallDone && progressDone) + if (progressDone) document.title = 'PASS'; } diff --git a/media/base/demuxer.h b/media/base/demuxer.h index 044df3d..3647a9d 100644 --- a/media/base/demuxer.h +++ b/media/base/demuxer.h @@ -45,6 +45,12 @@ class MEDIA_EXPORT Demuxer // to be released before the host object is destroyed by the pipeline. virtual void set_host(DemuxerHost* host); + // Completes initialization of the demuxer. + // + // TODO(scherkus): pass in DemuxerHost here instead of using set_host(), + // see http://crbug.com/111585 + virtual void Initialize(const PipelineStatusCB& status_cb) = 0; + // The pipeline playback rate has been changed. Demuxers may implement this // method if they need to respond to this call. virtual void SetPlaybackRate(float playback_rate); @@ -76,6 +82,8 @@ class MEDIA_EXPORT Demuxer // Returns true if the source is from a local file or stream (such as a // webcam stream), false otherwise. + // + // TODO(scherkus): See http://crbug.com/120426 on why we should remove this. virtual bool IsLocalSource() = 0; // Returns true if seeking is possible; false otherwise. diff --git a/media/base/demuxer_factory.cc b/media/base/demuxer_factory.cc deleted file mode 100644 index 1f968d7..0000000 --- a/media/base/demuxer_factory.cc +++ /dev/null @@ -1,11 +0,0 @@ -// 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/demuxer_factory.h" - -namespace media { - -DemuxerFactory::~DemuxerFactory() {} - -} // namespace media diff --git a/media/base/demuxer_factory.h b/media/base/demuxer_factory.h deleted file mode 100644 index 6a13356..0000000 --- a/media/base/demuxer_factory.h +++ /dev/null @@ -1,32 +0,0 @@ -// 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_DEMUXER_FACTORY_H_ -#define MEDIA_BASE_DEMUXER_FACTORY_H_ - -#include <string> - -#include "base/callback.h" -#include "media/base/media_export.h" -#include "media/base/pipeline_status.h" - -namespace media { - -class Demuxer; - -// Asynchronous factory interface for building Demuxer objects. -class MEDIA_EXPORT DemuxerFactory { - public: - // Ownership of the Demuxer is transferred through this callback. - typedef base::Callback<void(PipelineStatus, Demuxer*)> BuildCallback; - - virtual ~DemuxerFactory(); - - // Builds a Demuxer for |url| and returns it via |callback|. - virtual void Build(const std::string& url, const BuildCallback& callback) = 0; -}; - -} // namespace media - -#endif // MEDIA_BASE_DEMUXER_FACTORY_H_ diff --git a/media/base/filter_collection.cc b/media/base/filter_collection.cc index 3171399..537dd60 100644 --- a/media/base/filter_collection.cc +++ b/media/base/filter_collection.cc @@ -13,13 +13,12 @@ FilterCollection::FilterCollection() {} FilterCollection::~FilterCollection() {} -void FilterCollection::SetDemuxerFactory(scoped_ptr<DemuxerFactory> factory) { - DCHECK(factory.get()); - demuxer_factory_ = factory.Pass(); +void FilterCollection::SetDemuxer(const scoped_refptr<Demuxer>& demuxer) { + demuxer_ = demuxer; } -DemuxerFactory* FilterCollection::GetDemuxerFactory() { - return demuxer_factory_.get(); +const scoped_refptr<Demuxer>& FilterCollection::GetDemuxer() { + return demuxer_; } void FilterCollection::AddAudioDecoder(AudioDecoder* audio_decoder) { diff --git a/media/base/filter_collection.h b/media/base/filter_collection.h index c3629a1..8d8591d 100644 --- a/media/base/filter_collection.h +++ b/media/base/filter_collection.h @@ -8,7 +8,7 @@ #include <list> #include "base/memory/ref_counted.h" -#include "media/base/demuxer_factory.h" +#include "media/base/demuxer.h" #include "media/base/filters.h" namespace media { @@ -22,9 +22,9 @@ class MEDIA_EXPORT FilterCollection { FilterCollection(); ~FilterCollection(); - // DemuxerFactory accessor methods. - void SetDemuxerFactory(scoped_ptr<DemuxerFactory> factory); - DemuxerFactory* GetDemuxerFactory(); + // Demuxer accessor methods. + void SetDemuxer(const scoped_refptr<Demuxer>& demuxer); + const scoped_refptr<Demuxer>& GetDemuxer(); // Adds a filter to the collection. void AddAudioDecoder(AudioDecoder* audio_decoder); @@ -60,7 +60,7 @@ class MEDIA_EXPORT FilterCollection { typedef std::pair<FilterType, scoped_refptr<Filter> > FilterListElement; typedef std::list<FilterListElement> FilterList; FilterList filters_; - scoped_ptr<DemuxerFactory> demuxer_factory_; + scoped_refptr<Demuxer> demuxer_; std::list<scoped_refptr<AudioDecoder> > audio_decoders_; std::list<scoped_refptr<VideoDecoder> > video_decoders_; diff --git a/media/base/mock_filters.cc b/media/base/mock_filters.cc index e41ecb3..3502973 100644 --- a/media/base/mock_filters.cc +++ b/media/base/mock_filters.cc @@ -38,35 +38,6 @@ void MockDataSource::SetTotalAndBufferedBytes(int64 total_bytes, buffered_bytes_ = buffered_bytes; } -MockDemuxerFactory::MockDemuxerFactory(MockDemuxer* demuxer) - : demuxer_(demuxer), status_(PIPELINE_OK) { -} - -MockDemuxerFactory::~MockDemuxerFactory() {} - -void MockDemuxerFactory::SetError(PipelineStatus error) { - DCHECK_NE(error, PIPELINE_OK); - status_ = error; -} - -void MockDemuxerFactory::RunBuildCallback(const std::string& url, - const BuildCallback& callback) { - if (!demuxer_.get()) { - callback.Run(PIPELINE_ERROR_REQUIRED_FILTER_MISSING, NULL); - return; - } - - scoped_refptr<MockDemuxer> demuxer = demuxer_; - demuxer_ = NULL; - - if (status_ == PIPELINE_OK) { - callback.Run(PIPELINE_OK, demuxer.get()); - return; - } - - callback.Run(status_, NULL); -} - MockDemuxer::MockDemuxer() : total_bytes_(-1), buffered_bytes_(-1), duration_() { EXPECT_CALL(*this, GetBitrate()).WillRepeatedly(Return(0)); @@ -128,28 +99,9 @@ MockFilterCollection::MockFilterCollection() MockFilterCollection::~MockFilterCollection() {} -scoped_ptr<FilterCollection> MockFilterCollection::filter_collection( - bool include_demuxer, - bool run_build_cb, - bool run_build, - PipelineStatus build_status) const { +scoped_ptr<FilterCollection> MockFilterCollection::Create() { scoped_ptr<FilterCollection> collection(new FilterCollection()); - - scoped_ptr<MockDemuxerFactory> demuxer_factory( - new MockDemuxerFactory(include_demuxer ? demuxer_ : NULL)); - - if (build_status != PIPELINE_OK) - demuxer_factory->SetError(build_status); - - if (run_build_cb) { - ON_CALL(*demuxer_factory, Build(_, _)).WillByDefault(Invoke( - demuxer_factory.get(), &MockDemuxerFactory::RunBuildCallback)); - } // else ignore Build calls. - - if (run_build) - EXPECT_CALL(*demuxer_factory, Build(_, _)); - - collection->SetDemuxerFactory(demuxer_factory.PassAs<DemuxerFactory>()); + collection->SetDemuxer(demuxer_); collection->AddVideoDecoder(video_decoder_); collection->AddAudioDecoder(audio_decoder_); collection->AddVideoRenderer(video_renderer_); @@ -161,7 +113,12 @@ void RunFilterCallback(::testing::Unused, const base::Closure& closure) { closure.Run(); } -void RunPipelineStatusCB(::testing::Unused, const PipelineStatusCB& status_cb) { +void RunPipelineStatusCB(const PipelineStatusCB& status_cb) { + status_cb.Run(PIPELINE_OK); +} + +void RunPipelineStatusCB2(::testing::Unused, + const PipelineStatusCB& status_cb) { status_cb.Run(PIPELINE_OK); } diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 22cde25..75058fc 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -105,6 +105,7 @@ class MockDemuxer : public Demuxer { public: MockDemuxer(); + MOCK_METHOD1(Initialize, void(const PipelineStatusCB& cb)); virtual void set_host(DemuxerHost* demuxer_host); MOCK_METHOD1(Stop, void(const base::Closure& callback)); MOCK_METHOD1(SetPlaybackRate, void(float playback_rate)); @@ -136,25 +137,6 @@ class MockDemuxer : public Demuxer { DISALLOW_COPY_AND_ASSIGN(MockDemuxer); }; -class MockDemuxerFactory : public DemuxerFactory { - public: - explicit MockDemuxerFactory(MockDemuxer* demuxer); - virtual ~MockDemuxerFactory(); - - void SetError(PipelineStatus error); - void RunBuildCallback(const std::string& url, const BuildCallback& callback); - - // DemuxerFactory methods. - MOCK_METHOD2(Build, void(const std::string& url, - const BuildCallback& callback)); - - private: - scoped_refptr<MockDemuxer> demuxer_; - PipelineStatus status_; - - DISALLOW_COPY_AND_ASSIGN(MockDemuxerFactory); -}; - class MockDemuxerStream : public DemuxerStream { public: MockDemuxerStream(); @@ -290,13 +272,8 @@ class MockFilterCollection { MockVideoRenderer* video_renderer() const { return video_renderer_; } MockAudioRenderer* audio_renderer() const { return audio_renderer_; } - scoped_ptr<FilterCollection> filter_collection() const { - return filter_collection(true, true, true, PIPELINE_OK).Pass(); - } - - scoped_ptr<FilterCollection> filter_collection( - bool include_demuxer, bool run_build_cb, bool run_build, - PipelineStatus build_status) const; + // Creates the FilterCollection containing the mocks. + scoped_ptr<FilterCollection> Create(); private: scoped_refptr<MockDemuxer> demuxer_; @@ -312,7 +289,8 @@ class MockFilterCollection { // Closure on behalf of the provided filter. Can be used when mocking // the Initialize() and Seek() methods. void RunFilterCallback(::testing::Unused, const base::Closure& closure); -void RunPipelineStatusCB(::testing::Unused, const PipelineStatusCB& status_cb); +void RunPipelineStatusCB(const PipelineStatusCB& status_cb); +void RunPipelineStatusCB2(::testing::Unused, const PipelineStatusCB& status_cb); void RunPipelineStatusCB3(::testing::Unused, const PipelineStatusCB& status_cb, ::testing::Unused); void RunPipelineStatusCB4(::testing::Unused, const PipelineStatusCB& status_cb, @@ -321,6 +299,10 @@ void RunPipelineStatusCB4(::testing::Unused, const PipelineStatusCB& status_cb, // provided filter. Can be used when mocking the Stop() method. void RunStopFilterCallback(const base::Closure& closure); +ACTION_P(RunPipelineStatusCBWithError, error) { + arg0.Run(error); +} + // Helper gmock action that calls SetError() on behalf of the provided filter. ACTION_P2(SetError, filter, error) { filter->host()->SetError(error); diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index af62cb2..c30af3b 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc @@ -89,7 +89,6 @@ Pipeline::~Pipeline() { } void Pipeline::Start(scoped_ptr<FilterCollection> collection, - const std::string& url, const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb, const NetworkEventCB& network_cb, @@ -100,7 +99,7 @@ void Pipeline::Start(scoped_ptr<FilterCollection> collection, running_ = true; message_loop_->PostTask(FROM_HERE, base::Bind( &Pipeline::StartTask, this, base::Passed(&collection), - url, ended_cb, error_cb, network_cb, start_cb)); + ended_cb, error_cb, network_cb, start_cb)); } void Pipeline::Stop(const base::Closure& stop_cb) { @@ -593,7 +592,6 @@ void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { } void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, - const std::string& url, const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb, const NetworkEventCB& network_cb, @@ -601,7 +599,6 @@ void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK_EQ(kCreated, state_); filter_collection_ = filter_collection.Pass(); - url_ = url; ended_cb_ = ended_cb; error_cb_ = error_cb; network_cb_ = network_cb; @@ -1088,26 +1085,28 @@ void Pipeline::InitializeDemuxer() { DCHECK_EQ(MessageLoop::current(), message_loop_); DCHECK(IsPipelineOk()); - filter_collection_->GetDemuxerFactory()->Build( - url_, base::Bind(&Pipeline::OnDemuxerBuilt, this)); + demuxer_ = filter_collection_->GetDemuxer(); + if (!demuxer_) { + SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); + return; + } + + demuxer_->set_host(this); + demuxer_->Initialize(base::Bind(&Pipeline::OnDemuxerInitialized, this)); } -void Pipeline::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { +void Pipeline::OnDemuxerInitialized(PipelineStatus status) { if (MessageLoop::current() != message_loop_) { message_loop_->PostTask(FROM_HERE, base::Bind( - &Pipeline::OnDemuxerBuilt, this, status, make_scoped_refptr(demuxer))); + &Pipeline::OnDemuxerInitialized, this, status)); return; } - demuxer_ = demuxer; if (status != PIPELINE_OK) { SetError(status); return; } - CHECK(demuxer_) << "Null demuxer encountered despite PIPELINE_OK."; - demuxer_->set_host(this); - { base::AutoLock auto_lock(lock_); // We do not want to start the clock running. We only want to set the base diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 9c272ed..f2c7751 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -116,8 +116,8 @@ class MEDIA_EXPORT Pipeline // Constructs a media pipeline that will execute on |message_loop|. Pipeline(MessageLoop* message_loop, MediaLog* media_log); - // Build a pipeline to render the given URL using the given filter collection - // to construct a filter chain. + // Build a pipeline to using the given filter collection to construct a filter + // chain. // // Pipeline initialization is an inherently asynchronous process. Clients can // either poll the IsInitialized() method (discouraged) or optionally pass in @@ -137,7 +137,6 @@ class MEDIA_EXPORT Pipeline // // TODO(scherkus): remove IsInitialized() and force clients to use callbacks. void Start(scoped_ptr<FilterCollection> filter_collection, - const std::string& url, const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb, const NetworkEventCB& network_cb, @@ -350,7 +349,6 @@ class MEDIA_EXPORT Pipeline // methods are run as the result of posting a task to the PipelineInternal's // message loop. void StartTask(scoped_ptr<FilterCollection> filter_collection, - const std::string& url, const PipelineStatusCB& ended_cb, const PipelineStatusCB& error_cb, const NetworkEventCB& network_cb, @@ -404,9 +402,9 @@ class MEDIA_EXPORT Pipeline // of these methods are only called on the pipeline thread. // The following initialize methods are used to select a specific type of - // Filter object from FilterCollection and initialize it asynchronously. + // object from FilterCollection and initialize it asynchronously. void InitializeDemuxer(); - void OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer); + void OnDemuxerInitialized(PipelineStatus status); // Returns true if the asynchronous action of creating decoder has started. // Returns false if this method did nothing because the corresponding @@ -573,9 +571,6 @@ class MEDIA_EXPORT Pipeline // Filter collection as passed in by Start(). scoped_ptr<FilterCollection> filter_collection_; - // URL for the data source as passed in by Start(). - std::string url_; - // Callbacks for various pipeline operations. PipelineStatusCB seek_cb_; base::Closure stop_cb_; diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index 42fd5bd..14d39d9 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -55,11 +55,6 @@ class CallbackHelper { DISALLOW_COPY_AND_ASSIGN(CallbackHelper); }; -// Run |cb| w/ OK status. -static void RunPipelineStatusOKCB(const PipelineStatusCB& cb) { - cb.Run(PIPELINE_OK); -} - // TODO(scherkus): even though some filters are initialized on separate // threads these test aren't flaky... why? It's because filters' Initialize() // is executed on |message_loop_| and the mock filters instantly call @@ -93,6 +88,7 @@ class PipelineTest : public ::testing::Test { base::Unretained(&callbacks_))); message_loop_.RunAllPending(); + pipeline_ = NULL; mocks_.reset(); } @@ -101,11 +97,13 @@ class PipelineTest : public ::testing::Test { typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; void InitializeDemuxer(MockDemuxerStreamVector* streams, const base::TimeDelta& duration) { + EXPECT_CALL(*mocks_->demuxer(), Initialize(_)) + .WillOnce(Invoke(&RunPipelineStatusCB)); mocks_->demuxer()->SetTotalAndBufferedBytesAndDuration( kTotalBytes, kBufferedBytes, duration); EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->demuxer(), Seek(mocks_->demuxer()->GetStartTime(), _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); EXPECT_CALL(*mocks_->demuxer(), Stop(_)) .WillOnce(Invoke(&RunStopFilterCallback)); @@ -129,7 +127,7 @@ class PipelineTest : public ::testing::Test { void InitializeVideoDecoder(MockDemuxerStream* stream) { EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream, _, _)) - .WillOnce(WithArg<1>(Invoke(&RunPipelineStatusOKCB))); + .WillOnce(Invoke(&RunPipelineStatusCB3)); } // Sets up expectations to allow the audio decoder to initialize. @@ -146,7 +144,7 @@ class PipelineTest : public ::testing::Test { EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->video_renderer(), Seek(mocks_->demuxer()->GetStartTime(), _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); EXPECT_CALL(*mocks_->video_renderer(), Stop(_)) .WillOnce(Invoke(&RunStopFilterCallback)); } @@ -166,35 +164,22 @@ class PipelineTest : public ::testing::Test { EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f)); EXPECT_CALL(*mocks_->audio_renderer(), Seek(base::TimeDelta(), _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) .WillOnce(Invoke(&RunStopFilterCallback)); } // Sets up expectations on the callback and initializes the pipeline. Called // after tests have set expectations any filters they wish to use. - void InitializePipeline() { - InitializePipeline(PIPELINE_OK); - } - // Most tests can expect the |filter_collection|'s |build_status| to get - // reflected in |Start()|'s argument. void InitializePipeline(PipelineStatus start_status) { - InitializePipeline(start_status, start_status); - } - // But some tests require different statuses in build & Start. - void InitializePipeline(PipelineStatus build_status, - PipelineStatus start_status) { - // Expect an initialization callback. EXPECT_CALL(callbacks_, OnStart(start_status)); pipeline_->Start( - mocks_->filter_collection(true, true, true, build_status).Pass(), - "", + mocks_->Create().Pass(), base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), NetworkEventCB(), base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); - message_loop_.RunAllPending(); } @@ -217,16 +202,16 @@ class PipelineTest : public ::testing::Test { void ExpectSeek(const base::TimeDelta& seek_time) { // Every filter should receive a call to Seek(). EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); if (audio_stream_) { EXPECT_CALL(*mocks_->audio_renderer(), Seek(seek_time, _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); } if (video_stream_) { EXPECT_CALL(*mocks_->video_renderer(), Seek(seek_time, _)) - .WillOnce(Invoke(&RunPipelineStatusCB)); + .WillOnce(Invoke(&RunPipelineStatusCB2)); } // We expect a successful seek callback. @@ -295,12 +280,16 @@ TEST_F(PipelineTest, NotStarted) { } TEST_F(PipelineTest, NeverInitializes) { + // Don't execute the callback passed into Initialize(). + EXPECT_CALL(*mocks_->demuxer(), Initialize(_)); + EXPECT_CALL(*mocks_->demuxer(), Stop(_)) + .WillOnce(Invoke(&RunStopFilterCallback)); + // This test hangs during initialization by never calling // InitializationComplete(). StrictMock<> will ensure that the callback is // never executed. pipeline_->Start( - mocks_->filter_collection(false, false, true, PIPELINE_OK).Pass(), - "", + mocks_->Create().Pass(), base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), NetworkEventCB(), @@ -317,37 +306,39 @@ TEST_F(PipelineTest, NeverInitializes) { } TEST_F(PipelineTest, RequiredFilterMissing) { - // Sets up expectations on the callback and initializes the pipeline. Called - // after tests have set expectations any filters they wish to use. - // Expect an initialization callback. - EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); - // Create a filter collection with missing filter. - scoped_ptr<FilterCollection> collection(mocks_->filter_collection( - false, true, true, PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); + scoped_ptr<FilterCollection> collection(mocks_->Create()); + collection->SetDemuxer(NULL); + + EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); pipeline_->Start( - collection.Pass(), - "", - base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), - base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), - NetworkEventCB(), - base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); + collection.Pass(), + base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), + base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), + NetworkEventCB(), + base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); message_loop_.RunAllPending(); - EXPECT_FALSE(pipeline_->IsInitialized()); } TEST_F(PipelineTest, URLNotFound) { + EXPECT_CALL(*mocks_->demuxer(), Initialize(_)) + .WillOnce(RunPipelineStatusCBWithError( + PIPELINE_ERROR_URL_NOT_FOUND)); + EXPECT_CALL(*mocks_->demuxer(), Stop(_)) + .WillOnce(Invoke(&RunStopFilterCallback)); + InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND); EXPECT_FALSE(pipeline_->IsInitialized()); } TEST_F(PipelineTest, NoStreams) { - // Manually set these expectations because SetPlaybackRate() is not called if - // we cannot fully initialize the pipeline. + EXPECT_CALL(*mocks_->demuxer(), Initialize(_)) + .WillOnce(Invoke(&RunPipelineStatusCB)); EXPECT_CALL(*mocks_->demuxer(), Stop(_)) .WillOnce(Invoke(&RunStopFilterCallback)); - InitializePipeline(PIPELINE_OK, PIPELINE_ERROR_COULD_NOT_RENDER); + + InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER); EXPECT_FALSE(pipeline_->IsInitialized()); } diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index 44dd392..452d535 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -335,8 +335,7 @@ ChunkDemuxer::ChunkDemuxer(ChunkDemuxerClient* client) : state_(WAITING_FOR_INIT), client_(client), buffered_bytes_(0), - seek_waits_for_data_(true), - deferred_error_(PIPELINE_OK) { + seek_waits_for_data_(true) { DCHECK(client); } @@ -344,7 +343,7 @@ ChunkDemuxer::~ChunkDemuxer() { DCHECK_NE(state_, INITIALIZED); } -void ChunkDemuxer::Init(const PipelineStatusCB& cb) { +void ChunkDemuxer::Initialize(const PipelineStatusCB& cb) { DVLOG(1) << "Init()"; { base::AutoLock auto_lock(lock_); @@ -362,17 +361,6 @@ void ChunkDemuxer::Init(const PipelineStatusCB& cb) { client_->DemuxerOpened(this); } -void ChunkDemuxer::set_host(DemuxerHost* host) { - DCHECK(state_ == INITIALIZED || state_ == PARSE_ERROR); - Demuxer::set_host(host); - host->SetDuration(duration_); - host->SetCurrentReadPosition(0); - if (deferred_error_ != PIPELINE_OK) { - host->OnDemuxerError(deferred_error_); - deferred_error_ = PIPELINE_OK; - } -} - void ChunkDemuxer::Stop(const base::Closure& callback) { DVLOG(1) << "Stop()"; Shutdown(); @@ -549,16 +537,14 @@ bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { } // Notify the host of 'network activity' because we got data. - if (host()) { - host()->SetBufferedBytes(buffered_bytes); - - if (buffered_ts.InSeconds() >= 0) { - host()->SetBufferedTime(buffered_ts); - } + host()->SetBufferedBytes(buffered_bytes); - host()->SetNetworkActivity(true); + if (buffered_ts.InSeconds() >= 0) { + host()->SetBufferedTime(buffered_ts); } + host()->SetNetworkActivity(true); + if (!cb.is_null()) cb.Run(PIPELINE_OK); @@ -662,14 +648,8 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { return; } - DemuxerHost* demuxer_host = host(); - if (demuxer_host) { - base::AutoUnlock auto_unlock(lock_); - demuxer_host->OnDemuxerError(error); - return; - } - - deferred_error_ = error; + base::AutoUnlock auto_unlock(lock_); + host()->OnDemuxerError(error); } void ChunkDemuxer::OnStreamParserInitDone(bool success, @@ -682,6 +662,8 @@ void ChunkDemuxer::OnStreamParserInitDone(bool success, } duration_ = duration; + host()->SetDuration(duration_); + host()->SetCurrentReadPosition(0); ChangeState_Locked(INITIALIZED); PipelineStatusCB cb; diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index bf63527..8e141c8 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -25,10 +25,8 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost { explicit ChunkDemuxer(ChunkDemuxerClient* client); virtual ~ChunkDemuxer(); - void Init(const PipelineStatusCB& cb); - // Demuxer implementation. - virtual void set_host(DemuxerHost* host) OVERRIDE; + virtual void Initialize(const PipelineStatusCB& cb) OVERRIDE; virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE; virtual void OnAudioRendererDisabled() OVERRIDE; @@ -95,10 +93,6 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost { ByteQueue byte_queue_; - // Stores an error that happens after initilization but before set_host(). - // TODO(acolwell): Remove this when http://crbug.com/111585 is fixed. - PipelineStatus deferred_error_; - DISALLOW_COPY_AND_ASSIGN(ChunkDemuxer); }; diff --git a/media/filters/chunk_demuxer_factory.cc b/media/filters/chunk_demuxer_factory.cc deleted file mode 100644 index 8455d58..0000000 --- a/media/filters/chunk_demuxer_factory.cc +++ /dev/null @@ -1,38 +0,0 @@ -// 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/filters/chunk_demuxer_factory.h" - -#include "base/bind.h" -#include "base/message_loop.h" -#include "media/filters/chunk_demuxer.h" - -namespace media { - -static void InitDone(MessageLoop* message_loop, - const DemuxerFactory::BuildCallback& cb, - scoped_refptr<Demuxer> demuxer, - PipelineStatus status) { - if (status != PIPELINE_OK) - demuxer = NULL; - message_loop->PostTask(FROM_HERE, base::Bind(cb, status, demuxer)); -} - -ChunkDemuxerFactory::ChunkDemuxerFactory(ChunkDemuxerClient* client) - : client_(client) { - DCHECK(client_); -} - -ChunkDemuxerFactory::~ChunkDemuxerFactory() {} - -void ChunkDemuxerFactory::Build(const std::string& url, - const BuildCallback& cb) { - scoped_refptr<ChunkDemuxer> demuxer(new ChunkDemuxer(client_)); - - // Call Init() on demuxer. Note that ownership is being passed to the - // callback here. - demuxer->Init(base::Bind(&InitDone, MessageLoop::current(), cb, demuxer)); -} - -} // namespace media diff --git a/media/filters/chunk_demuxer_factory.h b/media/filters/chunk_demuxer_factory.h deleted file mode 100644 index 9e34a12..0000000 --- a/media/filters/chunk_demuxer_factory.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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_FILTERS_CHUNK_DEMUXER_FACTORY_H_ -#define MEDIA_FILTERS_CHUNK_DEMUXER_FACTORY_H_ - -#include <string> - -#include "base/memory/scoped_ptr.h" -#include "media/base/demuxer_factory.h" - -namespace media { - -class ChunkDemuxer; -class ChunkDemuxerClient; - -// Factory for building ChunkDemuxers. The factory will only build a -// ChunkDemuxer with the given client. -class MEDIA_EXPORT ChunkDemuxerFactory : public DemuxerFactory { - public: - ChunkDemuxerFactory(ChunkDemuxerClient* client); - virtual ~ChunkDemuxerFactory(); - - // DemuxerFactory methods. - virtual void Build(const std::string& url, const BuildCallback& cb) OVERRIDE; - - private: - ChunkDemuxerClient* client_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerFactory); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_CHUNK_DEMUXER_FACTORY_H_ diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index 38e960ec..a6ebb97 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -90,6 +90,7 @@ class ChunkDemuxerTest : public testing::Test { ChunkDemuxerTest() : client_(new MockChunkDemuxerClient()), demuxer_(new ChunkDemuxer(client_.get())) { + demuxer_->set_host(&mock_demuxer_host_); } virtual ~ChunkDemuxerTest() { @@ -193,29 +194,21 @@ class ChunkDemuxerTest : public testing::Test { return AppendData(info_tracks.get(), info_tracks_size); } - void InitDoneCalled(const base::TimeDelta& expected_duration, - PipelineStatus expected_status, - bool call_set_host, + void InitDoneCalled(PipelineStatus expected_status, PipelineStatus status) { EXPECT_EQ(status, expected_status); + } - if (status == PIPELINE_OK) { + PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& expected_duration, + PipelineStatus expected_status) { + if (expected_status == PIPELINE_OK) { EXPECT_CALL(mock_demuxer_host_, SetDuration(expected_duration)); EXPECT_CALL(mock_demuxer_host_, SetCurrentReadPosition(_)); - - if (call_set_host) - demuxer_->set_host(&mock_demuxer_host_); } - } - PipelineStatusCB CreateInitDoneCB(const base::TimeDelta& duration, - PipelineStatus expected_status, - bool call_set_host) { return base::Bind(&ChunkDemuxerTest::InitDoneCalled, base::Unretained(this), - duration, - expected_status, - call_set_host); + expected_status); } bool InitDemuxer(bool has_audio, bool has_video, @@ -224,7 +217,8 @@ class ChunkDemuxerTest : public testing::Test { (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(CreateInitDoneCB(kDefaultDuration(), expected_status, true)); + demuxer_->Initialize(CreateInitDoneCB( + kDefaultDuration(), expected_status)); return AppendInfoTracks(has_audio, has_video, video_content_encoded); } @@ -276,7 +270,7 @@ class ChunkDemuxerTest : public testing::Test { int buffer_size = 0; EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(CreateInitDoneCB(duration, PIPELINE_OK, true)); + demuxer_->Initialize(CreateInitDoneCB(duration, PIPELINE_OK)); // Read a WebM file into memory and send the data to the demuxer. ReadTestDataFile(filename, &buffer, &buffer_size); @@ -343,6 +337,7 @@ TEST_F(ChunkDemuxerTest, TestInit) { client_.reset(new MockChunkDemuxerClient()); demuxer_ = new ChunkDemuxer(client_.get()); + demuxer_->set_host(&mock_demuxer_host_); ASSERT_TRUE(InitDemuxer(has_audio, has_video, video_content_encoded)); scoped_refptr<DemuxerStream> audio_stream = @@ -639,7 +634,7 @@ TEST_F(ChunkDemuxerTest, TestMonotonicallyIncreasingTimestampsAcrossClusters) { // INFO & TRACKS data. TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); + demuxer_->Initialize(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); ClusterBuilder cb; cb.SetClusterTimecode(0); @@ -652,7 +647,7 @@ TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { // Test cases where we get an EndOfStream() call during initialization. TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); + demuxer_->Initialize(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); demuxer_->EndOfStream(PIPELINE_OK); } @@ -836,7 +831,7 @@ TEST_F(ChunkDemuxerTest, TestReadsAfterEndOfStream) { TEST_F(ChunkDemuxerTest, TestAppendingInPieces) { EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK, true)); + demuxer_->Initialize(CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK)); scoped_array<uint8> info_tracks; int info_tracks_size = 0; @@ -1031,15 +1026,15 @@ TEST_F(ChunkDemuxerTest, TestIncrementalClusterParsing) { TEST_F(ChunkDemuxerTest, TestParseErrorDuringInit) { + EXPECT_CALL(mock_demuxer_host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); + EXPECT_CALL(*client_, DemuxerOpened(_)); - demuxer_->Init(CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK, false)); + demuxer_->Initialize(CreateInitDoneCB( + kDefaultDuration(), PIPELINE_OK)); ASSERT_TRUE(AppendInfoTracks(true, true, false)); uint8 tmp = 0; ASSERT_TRUE(demuxer_->AppendData(&tmp, 1)); - - EXPECT_CALL(mock_demuxer_host_, OnDemuxerError(PIPELINE_ERROR_DECODE)); - demuxer_->set_host(&mock_demuxer_host_); } } // namespace media diff --git a/media/filters/dummy_demuxer.cc b/media/filters/dummy_demuxer.cc index 1a8f43b..d5692da 100644 --- a/media/filters/dummy_demuxer.cc +++ b/media/filters/dummy_demuxer.cc @@ -47,8 +47,8 @@ DummyDemuxer::DummyDemuxer(bool has_video, bool has_audio, bool local_source) DummyDemuxer::~DummyDemuxer() {} -int DummyDemuxer::GetBitrate() { - return 0; +void DummyDemuxer::Initialize(const PipelineStatusCB& status_cb) { + status_cb.Run(PIPELINE_OK); } scoped_refptr<DemuxerStream> DummyDemuxer::GetStream(DemuxerStream::Type type) { @@ -64,6 +64,10 @@ base::TimeDelta DummyDemuxer::GetStartTime() const { return base::TimeDelta(); } +int DummyDemuxer::GetBitrate() { + return 0; +} + bool DummyDemuxer::IsLocalSource() { return local_source_; } diff --git a/media/filters/dummy_demuxer.h b/media/filters/dummy_demuxer.h index e248f68..7f59369 100644 --- a/media/filters/dummy_demuxer.h +++ b/media/filters/dummy_demuxer.h @@ -39,12 +39,13 @@ class DummyDemuxerStream : public DemuxerStream { DISALLOW_COPY_AND_ASSIGN(DummyDemuxerStream); }; -class DummyDemuxer : public Demuxer { +class MEDIA_EXPORT DummyDemuxer : public Demuxer { public: DummyDemuxer(bool has_video, bool has_audio, bool local_source); virtual ~DummyDemuxer(); // Demuxer implementation. + virtual void Initialize(const PipelineStatusCB& status_cb) OVERRIDE; virtual scoped_refptr<DemuxerStream> GetStream( DemuxerStream::Type type) OVERRIDE; virtual void set_host(DemuxerHost* demuxer_host) OVERRIDE; diff --git a/media/filters/dummy_demuxer_factory.cc b/media/filters/dummy_demuxer_factory.cc deleted file mode 100644 index 34b79ba..0000000 --- a/media/filters/dummy_demuxer_factory.cc +++ /dev/null @@ -1,29 +0,0 @@ -// 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/filters/dummy_demuxer_factory.h" - -#include "base/memory/scoped_ptr.h" -#include "media/filters/dummy_demuxer.h" - -namespace media { - -DummyDemuxerFactory::DummyDemuxerFactory(bool has_video, - bool has_audio, - bool local_source) - : has_video_(has_video), - has_audio_(has_audio), - local_source_(local_source) { -} - -DummyDemuxerFactory::~DummyDemuxerFactory() {} - -void DummyDemuxerFactory::Build(const std::string& url, - const BuildCallback& cb) { - scoped_refptr<DummyDemuxer> demuxer = - new DummyDemuxer(has_video_, has_audio_, local_source_); - cb.Run(PIPELINE_OK, demuxer.get()); -} - -} // namespace media diff --git a/media/filters/dummy_demuxer_factory.h b/media/filters/dummy_demuxer_factory.h deleted file mode 100644 index 6bbf441..0000000 --- a/media/filters/dummy_demuxer_factory.h +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -// Implements the DemuxerFactory interface using DummyDemuxer. - -#ifndef MEDIA_FILTERS_DUMMY_DEMUXER_FACTORY_H_ -#define MEDIA_FILTERS_DUMMY_DEMUXER_FACTORY_H_ - -#include "base/compiler_specific.h" -#include "media/base/demuxer_factory.h" - -namespace media { - -class MEDIA_EXPORT DummyDemuxerFactory : public DemuxerFactory { - public: - DummyDemuxerFactory(bool has_video, bool has_audio, bool local_source); - virtual ~DummyDemuxerFactory(); - - // DemuxerFactory methods. - virtual void Build(const std::string& url, const BuildCallback& cb) OVERRIDE; - - private: - bool has_video_; - bool has_audio_; - bool local_source_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(DummyDemuxerFactory); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_DUMMY_DEMUXER_FACTORY_H_ diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 9429b0d..56db917 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -276,20 +276,24 @@ base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( // // FFmpegDemuxer // -FFmpegDemuxer::FFmpegDemuxer(MessageLoop* message_loop, bool local_source) +FFmpegDemuxer::FFmpegDemuxer( + MessageLoop* message_loop, + const scoped_refptr<DataSource>& data_source, + bool local_source) : message_loop_(message_loop), local_source_(local_source), format_context_(NULL), + data_source_(data_source), read_event_(false, false), read_has_failed_(false), last_read_bytes_(0), read_position_(0), - max_duration_(base::TimeDelta::FromMicroseconds(-1)), - deferred_status_(PIPELINE_OK), + bitrate_(0), first_seek_hack_(true), start_time_(kNoTimestamp()), audio_disabled_(false) { DCHECK(message_loop_); + DCHECK(data_source_); } FFmpegDemuxer::~FFmpegDemuxer() { @@ -336,22 +340,12 @@ void FFmpegDemuxer::OnAudioRendererDisabled() { void FFmpegDemuxer::set_host(DemuxerHost* demuxer_host) { Demuxer::set_host(demuxer_host); - if (data_source_) - data_source_->set_host(demuxer_host); - if (max_duration_.InMicroseconds() >= 0) - host()->SetDuration(max_duration_); - if (read_position_ > 0) - host()->SetCurrentReadPosition(read_position_); - if (deferred_status_ != PIPELINE_OK) - host()->OnDemuxerError(deferred_status_); + data_source_->set_host(demuxer_host); } -void FFmpegDemuxer::Initialize(DataSource* data_source, - const PipelineStatusCB& status_cb) { - message_loop_->PostTask( - FROM_HERE, - base::Bind(&FFmpegDemuxer::InitializeTask, this, - make_scoped_refptr(data_source), status_cb)); +void FFmpegDemuxer::Initialize(const PipelineStatusCB& status_cb) { + message_loop_->PostTask(FROM_HERE, base::Bind( + &FFmpegDemuxer::InitializeTask, this, status_cb)); } scoped_refptr<DemuxerStream> FFmpegDemuxer::GetStream( @@ -392,19 +386,14 @@ size_t FFmpegDemuxer::Read(size_t size, uint8* data) { // let FFmpeg demuxer methods to run on. int last_read_bytes = WaitForRead(); if (last_read_bytes == DataSource::kReadError) { - if (host()) - host()->OnDemuxerError(PIPELINE_ERROR_READ); - else - deferred_status_ = PIPELINE_ERROR_READ; + host()->OnDemuxerError(PIPELINE_ERROR_READ); // Returns with a negative number to signal an error to FFmpeg. read_has_failed_ = true; return AVERROR(EIO); } read_position_ += last_read_bytes; - - if (host()) - host()->SetCurrentReadPosition(read_position_); + host()->SetCurrentReadPosition(read_position_); return last_read_bytes; } @@ -443,13 +432,44 @@ MessageLoop* FFmpegDemuxer::message_loop() { return message_loop_; } -void FFmpegDemuxer::InitializeTask(DataSource* data_source, - const PipelineStatusCB& status_cb) { - DCHECK_EQ(MessageLoop::current(), message_loop_); +// Helper for calculating the bitrate of the media based on information stored +// in |format_context| or failing that the size and duration of the media. +// +// Returns 0 if a bitrate could not be determined. +static int CalculateBitrate( + AVFormatContext* format_context, + const base::TimeDelta& duration, + int64 filesize_in_bytes) { + // If there is a bitrate set on the container, use it. + if (format_context->bit_rate > 0) + return format_context->bit_rate; + + // Then try to sum the bitrates individually per stream. + int bitrate = 0; + for (size_t i = 0; i < format_context->nb_streams; ++i) { + AVCodecContext* codec_context = format_context->streams[i]->codec; + bitrate += codec_context->bit_rate; + } + if (bitrate > 0) + return bitrate; + + // See if we can approximate the bitrate as long as we have a filesize and + // valid duration. + if (duration.InMicroseconds() <= 0 || + duration == kInfiniteDuration() || + filesize_in_bytes == 0) { + return 0; + } + + // Do math in floating point as we'd overflow an int64 if the filesize was + // larger than ~1073GB. + double bytes = filesize_in_bytes; + double duration_us = duration.InMicroseconds(); + return bytes * 8000000.0 / duration_us; +} - data_source_ = data_source; - if (host()) - data_source_->set_host(host()); +void FFmpegDemuxer::InitializeTask(const PipelineStatusCB& status_cb) { + DCHECK_EQ(MessageLoop::current(), message_loop_); // Add ourself to Protocol list and get our unique key. std::string key = FFmpegGlue::GetInstance()->AddProtocol(this); @@ -538,47 +558,21 @@ void FFmpegDemuxer::InitializeTask(DataSource* data_source, // Good to go: set the duration and bitrate and notify we're done // initializing. - if (host()) - host()->SetDuration(max_duration); - max_duration_ = max_duration; + host()->SetDuration(max_duration); - int bitrate = GetBitrate(); - if (bitrate > 0) - data_source_->SetBitrate(bitrate); + int64 filesize_in_bytes = 0; + GetSize(&filesize_in_bytes); + bitrate_ = CalculateBitrate(format_context_, max_duration, filesize_in_bytes); + if (bitrate_ > 0) + data_source_->SetBitrate(bitrate_); status_cb.Run(PIPELINE_OK); } -int FFmpegDemuxer::GetBitrate() { - DCHECK(format_context_); - - // If there is a bitrate set on the container, use it. - if (format_context_->bit_rate > 0) - return format_context_->bit_rate; - // Then try to sum the bitrates individually per stream. - int bitrate = 0; - for (size_t i = 0; i < format_context_->nb_streams; ++i) { - AVCodecContext* codec_context = format_context_->streams[i]->codec; - bitrate += codec_context->bit_rate; - } - if (bitrate > 0) - return bitrate; - - // See if we can approximate the bitrate as long as we have a filesize and - // valid duration. - int64 filesize_in_bytes; - if (max_duration_.InMicroseconds() <= 0 || - max_duration_ == kInfiniteDuration() || - !GetSize(&filesize_in_bytes)) { - return 0; - } - - // Do math in floating point as we'd overflow an int64 if the filesize was - // larger than ~1073GB. - double bytes = filesize_in_bytes; - double duration = max_duration_.InMicroseconds(); - return bytes * 8000000.0 / duration; +int FFmpegDemuxer::GetBitrate() { + DCHECK(format_context_) << "Initialize() has not been called"; + return bitrate_; } bool FFmpegDemuxer::IsLocalSource() { diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index 711e609..6a6bc64 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h @@ -130,20 +130,20 @@ class FFmpegDemuxerStream : public DemuxerStream { class MEDIA_EXPORT FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { public: - FFmpegDemuxer(MessageLoop* message_loop, bool local_source); + FFmpegDemuxer(MessageLoop* message_loop, + const scoped_refptr<DataSource>& data_source, + bool local_source); virtual ~FFmpegDemuxer(); // Posts a task to perform additional demuxing. virtual void PostDemuxTask(); - void Initialize( - DataSource* data_source, const PipelineStatusCB& status_cb); - // Demuxer implementation. + virtual void set_host(DemuxerHost* demuxer_host) OVERRIDE; + virtual void Initialize(const PipelineStatusCB& status_cb) OVERRIDE; virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void Seek(base::TimeDelta time, const PipelineStatusCB& cb) OVERRIDE; virtual void OnAudioRendererDisabled() OVERRIDE; - virtual void set_host(DemuxerHost* demuxer_host) OVERRIDE; virtual void SetPlaybackRate(float playback_rate) OVERRIDE; virtual scoped_refptr<DemuxerStream> GetStream( DemuxerStream::Type type) OVERRIDE; @@ -171,8 +171,7 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { FRIEND_TEST_ALL_PREFIXES(FFmpegDemuxerTest, ProtocolRead); // Carries out initialization on the demuxer thread. - void InitializeTask( - DataSource* data_source, const PipelineStatusCB& status_cb); + void InitializeTask(const PipelineStatusCB& status_cb); // Carries out a seek on the demuxer thread. void SeekTask(base::TimeDelta time, const PipelineStatusCB& cb); @@ -242,10 +241,8 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer, public FFmpegURLProtocol { int last_read_bytes_; int64 read_position_; - // Initialization can happen before set_host() is called, in which case we - // store these bits for deferred reporting to the DemuxerHost when we get one. - base::TimeDelta max_duration_; - PipelineStatus deferred_status_; + // Derived bitrate after initialization has completed. + int bitrate_; // Used to skip the implicit "first seek" to avoid resetting FFmpeg's internal // state. diff --git a/media/filters/ffmpeg_demuxer_factory.cc b/media/filters/ffmpeg_demuxer_factory.cc deleted file mode 100644 index 13494b9..0000000 --- a/media/filters/ffmpeg_demuxer_factory.cc +++ /dev/null @@ -1,39 +0,0 @@ -// 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 "base/bind.h" -#include "base/message_loop.h" -#include "googleurl/src/gurl.h" -#include "media/filters/ffmpeg_demuxer.h" -#include "media/filters/ffmpeg_demuxer_factory.h" - -namespace media { - -FFmpegDemuxerFactory::FFmpegDemuxerFactory( - const scoped_refptr<DataSource>& data_source, - MessageLoop* loop) - : data_source_(data_source), - loop_(loop) { -} - -FFmpegDemuxerFactory::~FFmpegDemuxerFactory() {} - -static void DemuxerInitDone(const DemuxerFactory::BuildCallback& cb, - const scoped_refptr<FFmpegDemuxer>& demuxer, - PipelineStatus status) { - cb.Run(status, demuxer); -} - -void FFmpegDemuxerFactory::Build(const std::string& url, - const BuildCallback& cb) { - GURL gurl = GURL(url); - bool local_source = !gurl.SchemeIs("http") && !gurl.SchemeIs("https"); - scoped_refptr<FFmpegDemuxer> demuxer = new FFmpegDemuxer(loop_, local_source); - - demuxer->Initialize( - data_source_, - base::Bind(&DemuxerInitDone, cb, demuxer)); -} - -} // namespace media diff --git a/media/filters/ffmpeg_demuxer_factory.h b/media/filters/ffmpeg_demuxer_factory.h deleted file mode 100644 index 6a9463f..0000000 --- a/media/filters/ffmpeg_demuxer_factory.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -// Implements the DemuxerFactory interface using FFmpegDemuxer. - -#ifndef MEDIA_FILTERS_FFMPEG_DEMUXER_FACTORY_H_ -#define MEDIA_FILTERS_FFMPEG_DEMUXER_FACTORY_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "media/base/demuxer_factory.h" - -class MessageLoop; - -namespace media { - -class MEDIA_EXPORT FFmpegDemuxerFactory : public DemuxerFactory { - public: - FFmpegDemuxerFactory(const scoped_refptr<DataSource>& data_source, - MessageLoop* loop); - virtual ~FFmpegDemuxerFactory(); - - // DemuxerFactory methods. - virtual void Build(const std::string& url, const BuildCallback& cb) OVERRIDE; - - private: - scoped_refptr<DataSource> data_source_; - MessageLoop* loop_; // Unowned. - - DISALLOW_IMPLICIT_CONSTRUCTORS(FFmpegDemuxerFactory); -}; - -} // namespace media - -#endif // MEDIA_FILTERS_FFMPEG_DEMUXER_FACTORY_H_ diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 3189e08..520b59b 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -41,19 +41,7 @@ MATCHER(IsEndOfStreamBuffer, class FFmpegDemuxerTest : public testing::Test { protected: - FFmpegDemuxerTest() { - // Create an FFmpegDemuxer with local data source. - demuxer_ = new FFmpegDemuxer(&message_loop_, true); - demuxer_->disable_first_seek_hack_for_testing(); - - // Inject a filter host and message loop and prepare a data source. - demuxer_->set_host(&host_); - - EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); - EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); - EXPECT_CALL(host_, SetCurrentReadPosition(_)) - .WillRepeatedly(SaveArg<0>(¤t_read_position_)); - } + FFmpegDemuxerTest() {} virtual ~FFmpegDemuxerTest() { if (demuxer_) { @@ -67,34 +55,33 @@ class FFmpegDemuxerTest : public testing::Test { demuxer_ = NULL; } - scoped_refptr<FileDataSource> CreateDataSource(const std::string& name) { - return CreateDataSource(name, false); + void CreateDemuxer(const std::string& name) { + CreateDemuxer(name, false); } - scoped_refptr<FileDataSource> CreateDataSource(const std::string& name, - bool disable_file_size) { - FilePath file_path; - EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); + void CreateDemuxer(const std::string& name, bool disable_file_size) { + CHECK(!demuxer_); - file_path = file_path.Append(FILE_PATH_LITERAL("media")) - .Append(FILE_PATH_LITERAL("test")) - .Append(FILE_PATH_LITERAL("data")) - .AppendASCII(name); + EXPECT_CALL(host_, SetTotalBytes(_)).Times(AnyNumber()); + EXPECT_CALL(host_, SetBufferedBytes(_)).Times(AnyNumber()); + EXPECT_CALL(host_, SetCurrentReadPosition(_)) + .WillRepeatedly(SaveArg<0>(¤t_read_position_)); - scoped_refptr<FileDataSource> data_source = new FileDataSource( - disable_file_size); + CreateDataSource(name, disable_file_size); - EXPECT_EQ(PIPELINE_OK, data_source->Initialize(file_path.MaybeAsASCII())); + // Create an FFmpegDemuxer with local data source. + demuxer_ = new FFmpegDemuxer(&message_loop_, data_source_, true); + demuxer_->disable_first_seek_hack_for_testing(); - return data_source.get(); + // Inject a filter host and message loop and prepare a data source. + demuxer_->set_host(&host_); } MOCK_METHOD1(CheckPoint, void(int v)); - // Initializes FFmpegDemuxer. - void InitializeDemuxer(const scoped_refptr<DataSource>& data_source) { + void InitializeDemuxer() { EXPECT_CALL(host_, SetDuration(_)); - demuxer_->Initialize(data_source, NewExpectedStatusCB(PIPELINE_OK)); + demuxer_->Initialize(NewExpectedStatusCB(PIPELINE_OK)); message_loop_.RunAllPending(); } @@ -120,9 +107,8 @@ class FFmpegDemuxerTest : public testing::Test { // returns true if the bitrate is valid, false otherwise. bool VideoHasValidBitrate( const std::string& file_name, bool disable_file_size) { - scoped_refptr<FileDataSource> data_source = - CreateDataSource(file_name, disable_file_size); - InitializeDemuxer(data_source); + CreateDemuxer(file_name, disable_file_size); + InitializeDemuxer(); return demuxer_->GetBitrate() > 0; } @@ -133,6 +119,7 @@ class FFmpegDemuxerTest : public testing::Test { } // Fixture members. + scoped_refptr<FileDataSource> data_source_; scoped_refptr<FFmpegDemuxer> demuxer_; StrictMock<MockDemuxerHost> host_; MessageLoop message_loop_; @@ -140,14 +127,29 @@ class FFmpegDemuxerTest : public testing::Test { int64 current_read_position_; private: + void CreateDataSource(const std::string& name, bool disable_file_size) { + CHECK(!data_source_); + + FilePath file_path; + EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); + + file_path = file_path.Append(FILE_PATH_LITERAL("media")) + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")) + .AppendASCII(name); + + data_source_ = new FileDataSource(disable_file_size); + EXPECT_EQ(PIPELINE_OK, data_source_->Initialize(file_path.MaybeAsASCII())); + } + DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerTest); }; TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { // Simulate avformat_open_input() failing. + CreateDemuxer("ten_byte_file"), EXPECT_CALL(host_, SetCurrentReadPosition(_)); - demuxer_->Initialize(CreateDataSource("ten_byte_file"), - NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); + demuxer_->Initialize(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); message_loop_.RunAllPending(); } @@ -156,31 +158,32 @@ TEST_F(FFmpegDemuxerTest, Initialize_OpenFails) { // avformat_open_input(), but has avformat_find_stream_info() fail. // //TEST_F(FFmpegDemuxerTest, Initialize_ParseFails) { +// CreateDemuxer("find_stream_info_fail.webm"); // demuxer_->Initialize( -// CreateDataSource("find_stream_info_fail.webm"), // NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_PARSE)); // message_loop_.RunAllPending(); //} TEST_F(FFmpegDemuxerTest, Initialize_NoStreams) { // Open a file with no streams whatsoever. + CreateDemuxer("no_streams.webm"); EXPECT_CALL(host_, SetCurrentReadPosition(_)); demuxer_->Initialize( - CreateDataSource("no_streams.webm"), NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); message_loop_.RunAllPending(); } TEST_F(FFmpegDemuxerTest, Initialize_NoAudioVideo) { // Open a file containing streams but none of which are audio/video streams. + CreateDemuxer("no_audio_video.webm"); demuxer_->Initialize( - CreateDataSource("no_audio_video.webm"), NewExpectedStatusCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS)); message_loop_.RunAllPending(); } TEST_F(FFmpegDemuxerTest, Initialize_Successful) { - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Video stream should be present. scoped_refptr<DemuxerStream> stream = @@ -230,7 +233,8 @@ TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) { // Stream #4: Audio (16-bit signed little endian PCM) // // We should only pick the first audio/video streams we come across. - InitializeDemuxer(CreateDataSource("bear-320x240-multitrack.webm")); + CreateDemuxer("bear-320x240-multitrack.webm"); + InitializeDemuxer(); // Video stream should be VP8. scoped_refptr<DemuxerStream> stream = @@ -251,7 +255,8 @@ TEST_F(FFmpegDemuxerTest, Initialize_Multitrack) { TEST_F(FFmpegDemuxerTest, Read_Audio) { // We test that on a successful audio packet read. - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Attempt a read from the audio stream and run the message loop until done. scoped_refptr<DemuxerStream> audio = @@ -271,7 +276,8 @@ TEST_F(FFmpegDemuxerTest, Read_Audio) { TEST_F(FFmpegDemuxerTest, Read_Video) { // We test that on a successful video packet read. - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Attempt a read from the video stream and run the message loop until done. scoped_refptr<DemuxerStream> video = @@ -292,7 +298,8 @@ TEST_F(FFmpegDemuxerTest, Read_Video) { TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { // Test the start time is the first timestamp of the video and audio stream. - InitializeDemuxer(CreateDataSource("nonzero-start-time.webm")); + CreateDemuxer("nonzero-start-time.webm"); + InitializeDemuxer(); // Attempt a read from the video stream and run the message loop until done. scoped_refptr<DemuxerStream> video = @@ -323,7 +330,8 @@ TEST_F(FFmpegDemuxerTest, Read_VideoNonZeroStart) { TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { // Verify that end of stream buffers are created. - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // We should now expect an end of stream buffer. scoped_refptr<DemuxerStream> audio = @@ -356,7 +364,8 @@ TEST_F(FFmpegDemuxerTest, Read_EndOfStream) { TEST_F(FFmpegDemuxerTest, Seek) { // We're testing that the demuxer frees all queued packets when it receives // a Seek(). - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Get our streams. scoped_refptr<DemuxerStream> video = @@ -434,7 +443,8 @@ class MockReadCB : public base::RefCountedThreadSafe<MockReadCB> { TEST_F(FFmpegDemuxerTest, Stop) { // Tests that calling Read() on a stopped demuxer stream immediately deletes // the callback. - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Get our stream. scoped_refptr<DemuxerStream> audio = @@ -470,7 +480,8 @@ TEST_F(FFmpegDemuxerTest, Stop) { // This test verifies that DemuxerStream::Read() does not use an invalid demuxer // pointer (no crash occurs) and calls the callback with an EndOfStream buffer. TEST_F(FFmpegDemuxerTest, StreamReadAfterStopAndDemuxerDestruction) { - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Get our stream. scoped_refptr<DemuxerStream> audio = @@ -513,7 +524,8 @@ TEST_F(FFmpegDemuxerTest, DisableAudioStream) { // 1. Initialize the demuxer with audio and video stream. // 2. Send a "disable audio stream" message to the demuxer. // 3. Demuxer will free audio packets even if audio stream was initialized. - InitializeDemuxer(CreateDataSource("bear-320x240.webm")); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); // Submit a "disable audio stream" message to the demuxer. demuxer_->OnAudioRendererDisabled(); @@ -548,8 +560,9 @@ TEST_F(FFmpegDemuxerTest, DisableAudioStream) { class MockFFmpegDemuxer : public FFmpegDemuxer { public: - explicit MockFFmpegDemuxer(MessageLoop* message_loop) - : FFmpegDemuxer(message_loop, true) { + MockFFmpegDemuxer(MessageLoop* message_loop, + const scoped_refptr<DataSource>& data_source) + : FFmpegDemuxer(message_loop, data_source, true) { } virtual ~MockFFmpegDemuxer() {} @@ -575,10 +588,8 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) { // Creates a demuxer. scoped_refptr<MockFFmpegDemuxer> demuxer( - new MockFFmpegDemuxer(&message_loop_)); - ASSERT_TRUE(demuxer); + new MockFFmpegDemuxer(&message_loop_, data_source)); demuxer->set_host(&host_); - demuxer->data_source_ = data_source; uint8 kBuffer[1]; InSequence s; @@ -643,8 +654,8 @@ TEST_F(FFmpegDemuxerTest, GetBitrate_UnsetInContainer_NoFileSize) { } TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { - scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); - InitializeDemuxer(data_source); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); InSequence s; @@ -663,29 +674,30 @@ TEST_F(FFmpegDemuxerTest, ProtocolGetSetPosition) { } TEST_F(FFmpegDemuxerTest, ProtocolGetSize) { - scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); - InitializeDemuxer(data_source); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); int64 data_source_size = 0; int64 demuxer_size = 0; - EXPECT_TRUE(data_source->GetSize(&data_source_size)); + EXPECT_TRUE(data_source_->GetSize(&data_source_size)); EXPECT_TRUE(demuxer_->GetSize(&demuxer_size)); EXPECT_NE(0, data_source_size); EXPECT_EQ(data_source_size, demuxer_size); } TEST_F(FFmpegDemuxerTest, ProtocolIsStreaming) { - scoped_refptr<DataSource> data_source = CreateDataSource("bear-320x240.webm"); - InitializeDemuxer(data_source); + CreateDemuxer("bear-320x240.webm"); + InitializeDemuxer(); - EXPECT_FALSE(data_source->IsStreaming()); + EXPECT_FALSE(data_source_->IsStreaming()); EXPECT_FALSE(demuxer_->IsStreaming()); } // Verify that seek works properly when the WebM cues data is at the start of // the file instead of at the end. TEST_F(FFmpegDemuxerTest, SeekWithCuesBeforeFirstCluster) { - InitializeDemuxer(CreateDataSource("bear-320x240-cues-in-front.webm")); + CreateDemuxer("bear-320x240-cues-in-front.webm"); + InitializeDemuxer(); // Get our streams. scoped_refptr<DemuxerStream> video = diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc index b84cfc0..cfcbf87 100644 --- a/media/filters/pipeline_integration_test.cc +++ b/media/filters/pipeline_integration_test.cc @@ -85,7 +85,7 @@ class PipelineIntegrationTest public: void StartPipelineWithMediaSource(MockMediaSource& source) { pipeline_->Start( - CreateFilterCollection(&source), source.url(), + CreateFilterCollection(&source), base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), NetworkEventCB(), QuitOnStatusCB(PIPELINE_OK)); diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc index 558e1ec..6fcead0 100644 --- a/media/filters/pipeline_integration_test_base.cc +++ b/media/filters/pipeline_integration_test_base.cc @@ -6,9 +6,9 @@ #include "base/bind.h" #include "media/base/media_log.h" -#include "media/filters/chunk_demuxer_factory.h" +#include "media/filters/chunk_demuxer.h" #include "media/filters/ffmpeg_audio_decoder.h" -#include "media/filters/ffmpeg_demuxer_factory.h" +#include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source.h" #include "media/filters/null_audio_renderer.h" @@ -81,7 +81,6 @@ bool PipelineIntegrationTestBase::Start(const std::string& url, PipelineStatus expected_status) { pipeline_->Start( CreateFilterCollection(url), - url, base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)), base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)), NetworkEventCB(), @@ -147,22 +146,21 @@ scoped_ptr<FilterCollection> PipelineIntegrationTestBase::CreateFilterCollection(const std::string& url) { scoped_refptr<FileDataSource> data_source = new FileDataSource(); CHECK_EQ(PIPELINE_OK, data_source->Initialize(url)); - return CreateFilterCollection(scoped_ptr<DemuxerFactory>( - new FFmpegDemuxerFactory(data_source, &message_loop_))); + return CreateFilterCollection(new FFmpegDemuxer( + &message_loop_, data_source, false)); } scoped_ptr<FilterCollection> PipelineIntegrationTestBase::CreateFilterCollection( ChunkDemuxerClient* client) { - return CreateFilterCollection(scoped_ptr<DemuxerFactory>( - new ChunkDemuxerFactory(client))); + return CreateFilterCollection(new ChunkDemuxer(client)); } scoped_ptr<FilterCollection> PipelineIntegrationTestBase::CreateFilterCollection( - scoped_ptr<DemuxerFactory> demuxer_factory) { + const scoped_refptr<Demuxer>& demuxer) { scoped_ptr<FilterCollection> collection(new FilterCollection()); - collection->SetDemuxerFactory(demuxer_factory.Pass()); + collection->SetDemuxer(demuxer); collection->AddAudioDecoder(new FFmpegAudioDecoder( base::Bind(&MessageLoopFactory::GetMessageLoop, base::Unretained(message_loop_factory_.get()), diff --git a/media/filters/pipeline_integration_test_base.h b/media/filters/pipeline_integration_test_base.h index 4b486d2..df7937a 100644 --- a/media/filters/pipeline_integration_test_base.h +++ b/media/filters/pipeline_integration_test_base.h @@ -68,7 +68,7 @@ class PipelineIntegrationTestBase { void OnError(PipelineStatus status); void QuitAfterCurrentTimeTask(const base::TimeDelta& quit_time); scoped_ptr<FilterCollection> CreateFilterCollection( - scoped_ptr<DemuxerFactory> demuxer_factory); + const scoped_refptr<Demuxer>& demuxer); void OnVideoRendererPaint(); MOCK_METHOD1(OnSetOpaque, void(bool)); diff --git a/media/media.gyp b/media/media.gyp index a11e2d0..29a7774 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -130,8 +130,6 @@ 'base/decrypt_config.h', 'base/demuxer.cc', 'base/demuxer.h', - 'base/demuxer_factory.cc', - 'base/demuxer_factory.h', 'base/demuxer_stream.cc', 'base/demuxer_stream.h', 'base/djb2.cc', @@ -189,18 +187,12 @@ 'filters/chunk_demuxer.cc', 'filters/chunk_demuxer.h', 'filters/chunk_demuxer_client.h', - 'filters/chunk_demuxer_factory.cc', - 'filters/chunk_demuxer_factory.h', 'filters/dummy_demuxer.cc', 'filters/dummy_demuxer.h', - 'filters/dummy_demuxer_factory.cc', - 'filters/dummy_demuxer_factory.h', 'filters/ffmpeg_audio_decoder.cc', 'filters/ffmpeg_audio_decoder.h', 'filters/ffmpeg_demuxer.cc', 'filters/ffmpeg_demuxer.h', - 'filters/ffmpeg_demuxer_factory.cc', - 'filters/ffmpeg_demuxer_factory.h', 'filters/ffmpeg_h264_bitstream_converter.cc', 'filters/ffmpeg_h264_bitstream_converter.h', 'filters/ffmpeg_glue.cc', @@ -292,14 +284,10 @@ 'filters/chunk_demuxer.cc', 'filters/chunk_demuxer.h', 'filters/chunk_demuxer_client.h', - 'filters/chunk_demuxer_factory.cc', - 'filters/chunk_demuxer_factory.h', 'filters/ffmpeg_audio_decoder.cc', 'filters/ffmpeg_audio_decoder.h', 'filters/ffmpeg_demuxer.cc', 'filters/ffmpeg_demuxer.h', - 'filters/ffmpeg_demuxer_factory.cc', - 'filters/ffmpeg_demuxer_factory.h', 'filters/ffmpeg_h264_bitstream_converter.cc', 'filters/ffmpeg_h264_bitstream_converter.h', 'filters/ffmpeg_glue.cc', diff --git a/media/tools/player_wtl/movie.cc b/media/tools/player_wtl/movie.cc index a506bdf..4e3c9ab 100644 --- a/media/tools/player_wtl/movie.cc +++ b/media/tools/player_wtl/movie.cc @@ -14,14 +14,14 @@ #include "media/base/message_loop_factory.h" #include "media/base/pipeline.h" #include "media/filters/ffmpeg_audio_decoder.h" -#include "media/filters/ffmpeg_demuxer_factory.h" +#include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source.h" #include "media/filters/null_audio_renderer.h" #include "media/filters/video_renderer_base.h" using media::FFmpegAudioDecoder; -using media::FFmpegDemuxerFactory; +using media::FFmpegDemuxer; using media::FFmpegVideoDecoder; using media::FileDataSource; using media::FilterCollection; @@ -78,8 +78,8 @@ bool Movie::Open(const wchar_t* url, VideoRendererBase* video_renderer) { // Create filter collection. scoped_ptr<FilterCollection> collection(new FilterCollection()); - collection->SetDemuxerFactory(scoped_ptr<DemuxerFactory>( - new FFmpegDemuxerFactory(data_source, pipeline_loop))); + collection->SetDemuxer(new FFmpegDemuxer( + pipeline_loop, data_source, true)); collection->AddAudioDecoder(new FFmpegAudioDecoder( base::Bind(&MessageLoopFactory::GetMessageLoop, base::Unretained(message_loop_factory_.get()), @@ -97,7 +97,6 @@ bool Movie::Open(const wchar_t* url, VideoRendererBase* video_renderer) { media::PipelineStatusNotification note; pipeline_->Start( collection.Pass(), - url_utf8, media::PipelineStatusCB(), media::PipelineStatusCB(), media::NetworkEventCB(), diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index e2ea311..467d92f 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -24,7 +24,7 @@ #include "media/base/pipeline.h" #include "media/base/video_frame.h" #include "media/filters/ffmpeg_audio_decoder.h" -#include "media/filters/ffmpeg_demuxer_factory.h" +#include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source.h" #include "media/filters/null_audio_renderer.h" @@ -109,8 +109,8 @@ bool InitPipeline(MessageLoop* message_loop, // Create our filter factories. scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); - collection->SetDemuxerFactory(scoped_ptr<media::DemuxerFactory>( - new media::FFmpegDemuxerFactory(data_source, message_loop))); + collection->SetDemuxer(new media::FFmpegDemuxer( + message_loop, data_source, true)); collection->AddAudioDecoder(new media::FFmpegAudioDecoder( base::Bind(&media::MessageLoopFactory::GetMessageLoop, base::Unretained(message_loop_factory), @@ -133,7 +133,7 @@ bool InitPipeline(MessageLoop* message_loop, *pipeline = new media::Pipeline(message_loop, new media::MediaLog()); media::PipelineStatusNotification note; (*pipeline)->Start( - collection.Pass(), "", media::PipelineStatusCB(), + collection.Pass(), media::PipelineStatusCB(), media::PipelineStatusCB(), media::NetworkEventCB(), note.Callback()); diff --git a/media/tools/seek_tester/seek_tester.cc b/media/tools/seek_tester/seek_tester.cc index 17b03ea..b3d3e09 100644 --- a/media/tools/seek_tester/seek_tester.cc +++ b/media/tools/seek_tester/seek_tester.cc @@ -51,8 +51,8 @@ int main(int argc, char** argv) { MessageLoop loop; media::PipelineStatusCB quitter = base::Bind(&QuitMessageLoop, &loop); scoped_refptr<media::FFmpegDemuxer> demuxer( - new media::FFmpegDemuxer(&loop, true)); - demuxer->Initialize(file_data_source, quitter); + new media::FFmpegDemuxer(&loop, file_data_source, true)); + demuxer->Initialize(quitter); loop.Run(); demuxer->Seek(base::TimeDelta::FromMilliseconds(seek_target_ms), quitter); diff --git a/webkit/media/filter_helpers.cc b/webkit/media/filter_helpers.cc index f665f84..d1499a5 100644 --- a/webkit/media/filter_helpers.cc +++ b/webkit/media/filter_helpers.cc @@ -7,10 +7,10 @@ #include "base/bind.h" #include "media/base/filter_collection.h" #include "media/base/message_loop_factory.h" -#include "media/filters/chunk_demuxer_factory.h" -#include "media/filters/dummy_demuxer_factory.h" +#include "media/filters/chunk_demuxer.h" +#include "media/filters/dummy_demuxer.h" #include "media/filters/ffmpeg_audio_decoder.h" -#include "media/filters/ffmpeg_demuxer_factory.h" +#include "media/filters/ffmpeg_demuxer.h" #include "media/filters/ffmpeg_video_decoder.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" #include "webkit/media/media_stream_client.h" @@ -60,9 +60,9 @@ bool BuildMediaStreamCollection(const WebKit::WebURL& url, // that the MediaStream represents a local webcam. This will need to // change in the future when GetVideoDecoder is no longer hardcoded to // only return CaptureVideoDecoders. - scoped_ptr<media::DemuxerFactory> demuxer_factory( - new media::DummyDemuxerFactory(true, false, true)); - filter_collection->SetDemuxerFactory(demuxer_factory.Pass()); + // + // See http://crbug.com/120426 for details. + filter_collection->SetDemuxer(new media::DummyDemuxer(true, false, true)); return true; } @@ -77,9 +77,7 @@ bool BuildMediaSourceCollection( if (media_source_url.isEmpty() || url != media_source_url) return false; - scoped_ptr<media::DemuxerFactory> demuxer_factory( - new media::ChunkDemuxerFactory(client)); - filter_collection->SetDemuxerFactory(demuxer_factory.Pass()); + filter_collection->SetDemuxer(new media::ChunkDemuxer(client)); AddDefaultDecodersToCollection(message_loop_factory, filter_collection, video_decoder); @@ -88,13 +86,14 @@ bool BuildMediaSourceCollection( void BuildDefaultCollection( const scoped_refptr<media::DataSource>& data_source, + bool local_source, media::MessageLoopFactory* message_loop_factory, media::FilterCollection* filter_collection, scoped_refptr<media::FFmpegVideoDecoder>* video_decoder) { - scoped_ptr<media::DemuxerFactory> demuxer_factory( - new media::FFmpegDemuxerFactory( - data_source, message_loop_factory->GetMessageLoop("PipelineThread"))); - filter_collection->SetDemuxerFactory(demuxer_factory.Pass()); + filter_collection->SetDemuxer(new media::FFmpegDemuxer( + message_loop_factory->GetMessageLoop("PipelineThread"), + data_source, + local_source)); AddDefaultDecodersToCollection(message_loop_factory, filter_collection, video_decoder); diff --git a/webkit/media/filter_helpers.h b/webkit/media/filter_helpers.h index f34da86..cdea330 100644 --- a/webkit/media/filter_helpers.h +++ b/webkit/media/filter_helpers.h @@ -45,9 +45,16 @@ bool BuildMediaSourceCollection( media::FilterCollection* filter_collection, scoped_refptr<media::FFmpegVideoDecoder>* video_decoder); -// Builds the required filters for handling regular URLs, adds them to -// |filter_collection| and fills |video_decoder|. -void BuildDefaultCollection(const scoped_refptr<media::DataSource>& data_source, +// Builds the required filters for handling regular URLs and adds them to +// |filter_collection| and fills |video_decoder| returning true if successful. +// +// |local_source| refers to whether the data being fetched requires network +// access. +// +// TODO(scherkus): a data source should be able to tell us this. +void BuildDefaultCollection( + const scoped_refptr<media::DataSource>& data_source, + bool local_source, media::MessageLoopFactory* message_loop_factory, media::FilterCollection* filter_collection, scoped_refptr<media::FFmpegVideoDecoder>* video_decoder); diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 6283c65..146f2839 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -221,7 +221,7 @@ void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { if (BuildMediaStreamCollection(url, media_stream_client_, message_loop_factory_.get(), filter_collection_.get())) { - StartPipeline(gurl); + StartPipeline(); return; } @@ -231,8 +231,8 @@ void WebMediaPlayerImpl::load(const WebKit::WebURL& url) { message_loop_factory_.get(), filter_collection_.get(), &video_decoder)) { - StartPipeline(gurl); proxy_->set_video_decoder(video_decoder); + StartPipeline(); return; } @@ -827,20 +827,24 @@ void WebMediaPlayerImpl::DataSourceInitialized( return; } + // TODO(scherkus): this is leftover from removing DemuxerFactory -- instead + // our DataSource should report this information. See http://crbug.com/120426 + bool local_source = !gurl.SchemeIs("http") && !gurl.SchemeIs("https"); + scoped_refptr<media::FFmpegVideoDecoder> video_decoder; BuildDefaultCollection(proxy_->data_source(), + local_source, message_loop_factory_.get(), filter_collection_.get(), &video_decoder); proxy_->set_video_decoder(video_decoder); - StartPipeline(gurl); + StartPipeline(); } -void WebMediaPlayerImpl::StartPipeline(const GURL& gurl) { +void WebMediaPlayerImpl::StartPipeline() { started_ = true; pipeline_->Start( filter_collection_.Pass(), - gurl.spec(), base::Bind(&WebMediaPlayerProxy::PipelineEndedCallback, proxy_.get()), base::Bind(&WebMediaPlayerProxy::PipelineErrorCallback, proxy_.get()), base::Bind(&WebMediaPlayerProxy::NetworkEventCallback, proxy_.get()), diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h index bb96828..fc803a3 100644 --- a/webkit/media/webmediaplayer_impl.h +++ b/webkit/media/webmediaplayer_impl.h @@ -205,7 +205,7 @@ class WebMediaPlayerImpl void DataSourceInitialized(const GURL& gurl, media::PipelineStatus status); // Finishes starting the pipeline due to a call to load(). - void StartPipeline(const GURL& gurl); + void StartPipeline(); // Helpers that set the network/ready state and notifies the client if // they've changed. |