diff options
-rw-r--r-- | media/base/filter_host.h | 3 | ||||
-rw-r--r-- | media/base/mock_filter_host.h | 1 | ||||
-rw-r--r-- | media/base/pipeline.h | 4 | ||||
-rw-r--r-- | media/base/pipeline_impl.cc | 12 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 6 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source.cc | 3 | ||||
-rw-r--r-- | webkit/glue/media/buffered_data_source_unittest.cc | 44 | ||||
-rw-r--r-- | webkit/glue/media/simple_data_source.cc | 2 | ||||
-rw-r--r-- | webkit/glue/media/simple_data_source_unittest.cc | 24 | ||||
-rw-r--r-- | webkit/glue/webmediaplayer_impl.cc | 13 |
10 files changed, 86 insertions, 26 deletions
diff --git a/media/base/filter_host.h b/media/base/filter_host.h index 02ae399..2b288d2 100644 --- a/media/base/filter_host.h +++ b/media/base/filter_host.h @@ -61,6 +61,9 @@ class FilterHost { // endpoints such as renderers. virtual void NotifyEnded() = 0; + // Sets the flag to indicate that our media is now loaded. + virtual void SetLoaded(bool loaded) = 0; + // Broadcast a message of type |message| to all other filters from |source|. virtual void BroadcastMessage(FilterMessage message) = 0; diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h index 439eda8..dfcf403 100644 --- a/media/base/mock_filter_host.h +++ b/media/base/mock_filter_host.h @@ -37,6 +37,7 @@ class MockFilterHost : public FilterHost { MOCK_METHOD1(SetBufferedBytes, void(int64 buffered_bytes)); MOCK_METHOD2(SetVideoSize, void(size_t width, size_t height)); MOCK_METHOD1(SetStreaming, void(bool streamed)); + MOCK_METHOD1(SetLoaded, void(bool loaded)); MOCK_METHOD0(NotifyEnded, void()); MOCK_METHOD1(BroadcastMessage, void(FilterMessage message)); diff --git a/media/base/pipeline.h b/media/base/pipeline.h index b54d442..dd571c9 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -151,6 +151,10 @@ class Pipeline : public base::RefCountedThreadSafe<Pipeline> { // data source. Seeking may not be possible. virtual bool IsStreaming() const = 0; + // If this method returns true, that means the data source has fully loaded + // the media and that the network is no longer needed. + virtual bool IsLoaded() const = 0; + // Gets the current error status for the pipeline. If the pipeline is // operating correctly, this will return OK. virtual PipelineError GetError() const = 0; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 270347c..49ebe4a 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -262,6 +262,11 @@ bool PipelineImpl::IsStreaming() const { return streaming_; } +bool PipelineImpl::IsLoaded() const { + AutoLock auto_lock(lock_); + return loaded_; +} + PipelineError PipelineImpl::GetError() const { AutoLock auto_lock(lock_); return error_; @@ -287,6 +292,7 @@ void PipelineImpl::ResetState() { buffered_time_ = kZero; buffered_bytes_ = 0; streaming_ = false; + loaded_ = false; total_bytes_ = 0; video_width_ = 0; video_height_ = 0; @@ -405,6 +411,12 @@ void PipelineImpl::NotifyEnded() { NewRunnableMethod(this, &PipelineImpl::NotifyEndedTask)); } +void PipelineImpl::SetLoaded(bool loaded) { + DCHECK(IsRunning()); + AutoLock auto_lock(lock_); + loaded_ = loaded; +} + void PipelineImpl::BroadcastMessage(FilterMessage message) { DCHECK(IsRunning()); diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index c448106..891404a 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -84,6 +84,7 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual int64 GetTotalBytes() const; virtual void GetVideoSize(size_t* width_out, size_t* height_out) const; virtual bool IsStreaming() const; + virtual bool IsLoaded() const; virtual PipelineError GetError() const; // Sets a permanent callback owned by the pipeline that will be executed when @@ -143,6 +144,7 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual void SetBufferedBytes(int64 buffered_bytes); virtual void SetVideoSize(size_t width, size_t height); virtual void SetStreaming(bool streamed); + virtual void SetLoaded(bool loaded); virtual void NotifyEnded(); virtual void BroadcastMessage(FilterMessage message); @@ -293,6 +295,10 @@ class PipelineImpl : public Pipeline, public FilterHost { // source. bool streaming_; + // Sets by the filters to indicate whether the data source is a fully + // loaded source. + bool loaded_; + // Current volume level (from 0.0f to 1.0f). This value is set immediately // via SetVolume() and a task is dispatched on the message loop to notify the // filters. diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc index 5b6ef7e..f081f04 100644 --- a/webkit/glue/media/buffered_data_source.cc +++ b/webkit/glue/media/buffered_data_source.cc @@ -764,6 +764,9 @@ void BufferedDataSource::InitialStartCallback(int error) { host()->SetStreaming(true); } + // Currently, only files can be used reliably w/o a network. + host()->SetLoaded(url_.SchemeIsFile()); + initial_response_received_ = true; if (probe_response_received_) DoneInitialization(); diff --git a/webkit/glue/media/buffered_data_source_unittest.cc b/webkit/glue/media/buffered_data_source_unittest.cc index 4d9efe8..003313c 100644 --- a/webkit/glue/media/buffered_data_source_unittest.cc +++ b/webkit/glue/media/buffered_data_source_unittest.cc @@ -30,8 +30,15 @@ using ::testing::WithArgs; namespace { const char* kHttpUrl = "http://test"; +const char* kFileUrl = "file://test"; const int kDataSize = 1024; +enum NetworkState { + NONE, + LOADED, + LOADING +}; + } // namespace namespace webkit_glue { @@ -400,7 +407,7 @@ class BufferedDataSourceTest : public testing::Test { } } - ~BufferedDataSourceTest() { + virtual ~BufferedDataSourceTest() { if (data_source_) { // Release the bridge factory because we don't own it. // Expects bridge factory to be destroyed along with data source. @@ -414,7 +421,7 @@ class BufferedDataSourceTest : public testing::Test { } void InitializeDataSource(const char* url, int error, int probe_error, - int64 instance_size) { + int64 instance_size, NetworkState networkState) { // Saves the url first. gurl_ = GURL(url); @@ -432,6 +439,14 @@ class BufferedDataSourceTest : public testing::Test { loader_ = new StrictMock<MockBufferedResourceLoader>(); probe_loader_ = new StrictMock<MockBufferedResourceLoader>(); + if (networkState == LOADED) { + EXPECT_CALL(host_, SetLoaded(true)); + } else if (networkState == LOADING) { + EXPECT_CALL(host_, SetLoaded(false)); + } + + // TODO(ajwong): This mock is too strict. We do not need to guarantee a + // full sequencing each of these expectations. InSequence s; StrictMock<media::MockFilterCallback> callback; @@ -448,6 +463,7 @@ class BufferedDataSourceTest : public testing::Test { .WillOnce(DoAll(Assign(&error_, error), Invoke(this, &BufferedDataSourceTest::InvokeStartCallback))); + if (error == net::OK) { EXPECT_CALL(*loader_, instance_size()) .WillOnce(Return(instance_size)); @@ -689,36 +705,36 @@ class BufferedDataSourceTest : public testing::Test { }; TEST_F(BufferedDataSourceTest, InitializationSuccess) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024); + InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, InitiailizationFailed) { InitializeDataSource(kHttpUrl, net::ERR_FILE_NOT_FOUND, - net::ERR_FILE_NOT_FOUND, 0); + net::ERR_FILE_NOT_FOUND, 0, NONE); StopDataSource(); } TEST_F(BufferedDataSourceTest, MissingContentLength) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, -1); + InitializeDataSource(kHttpUrl, net::OK, net::OK, -1, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, RangeRequestNotSupported) { InitializeDataSource(kHttpUrl, net::OK, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, 1024); + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, 1024, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, MissingContentLengthAndRangeRequestNotSupported) { InitializeDataSource(kHttpUrl, net::OK, - net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, -1); + net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, -1, LOADING); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadCacheHit) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 25); + InitializeDataSource(kHttpUrl, net::OK, net::OK, 25, LOADING); // Performs read with cache hit. ReadDataSourceHit(10, 10, 10); @@ -730,21 +746,27 @@ TEST_F(BufferedDataSourceTest, ReadCacheHit) { } TEST_F(BufferedDataSourceTest, ReadCacheMiss) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024); + InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); ReadDataSourceMiss(1000, 10); ReadDataSourceMiss(20, 10); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadFailed) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024); + InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); ReadDataSourceHit(10, 10, 10); ReadDataSourceFailed(10, 10, net::ERR_CONNECTION_RESET); StopDataSource(); } TEST_F(BufferedDataSourceTest, ReadTimesOut) { - InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024); + InitializeDataSource(kHttpUrl, net::OK, net::OK, 1024, LOADING); + ReadDataSourceTimesOut(20, 10); + StopDataSource(); +} + +TEST_F(BufferedDataSourceTest, FileHasLoadedState) { + InitializeDataSource(kFileUrl, net::OK, net::OK, 1024, LOADED); ReadDataSourceTimesOut(20, 10); StopDataSource(); } diff --git a/webkit/glue/media/simple_data_source.cc b/webkit/glue/media/simple_data_source.cc index fd3be2f..bcbec57 100644 --- a/webkit/glue/media/simple_data_source.cc +++ b/webkit/glue/media/simple_data_source.cc @@ -70,6 +70,8 @@ void SimpleDataSource::Initialize(const std::string& url, return; } + host()->SetLoaded(url_.SchemeIsFile()); + // Post a task to the render thread to start loading the resource. render_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &SimpleDataSource::StartTask)); diff --git a/webkit/glue/media/simple_data_source_unittest.cc b/webkit/glue/media/simple_data_source_unittest.cc index 9d367aa..eb5cd78 100644 --- a/webkit/glue/media/simple_data_source_unittest.cc +++ b/webkit/glue/media/simple_data_source_unittest.cc @@ -52,10 +52,7 @@ class SimpleDataSourceTest : public testing::Test { } } - void InitializeDataSource(const char* url) { - // Saves the url first. - gurl_ = GURL(url); - + void InitializeDataSource(const char* url, bool is_loaded) { media::MediaFormat url_format; url_format.SetAsString(media::MediaFormat::kMimeType, media::mime_type::kURL); @@ -66,9 +63,11 @@ class SimpleDataSourceTest : public testing::Test { // There is no need to provide a message loop to data source. data_source_->set_host(&host_); + EXPECT_CALL(host_, SetLoaded(is_loaded)); + // First a bridge is created. InSequence s; - EXPECT_CALL(*bridge_factory_, CreateBridge(gurl_, _, -1, -1)) + EXPECT_CALL(*bridge_factory_, CreateBridge(GURL(url), _, -1, -1)) .WillOnce(Return(bridge_.get())); EXPECT_CALL(*bridge_, Start(data_source_.get())) .WillOnce(Return(true)); @@ -165,32 +164,31 @@ class SimpleDataSourceTest : public testing::Test { scoped_refptr<SimpleDataSource> data_source_; StrictMock<media::MockFilterHost> host_; StrictMock<media::MockFilterCallback> callback_; - GURL gurl_; char data_[kDataSize]; DISALLOW_COPY_AND_ASSIGN(SimpleDataSourceTest); }; TEST_F(SimpleDataSourceTest, InitializeHTTP) { - InitializeDataSource(kHttpUrl); + InitializeDataSource(kHttpUrl, false); RequestSucceeded(); DestroyDataSource(); } TEST_F(SimpleDataSourceTest, InitializeHTTPS) { - InitializeDataSource(kHttpsUrl); + InitializeDataSource(kHttpsUrl, false); RequestSucceeded(); DestroyDataSource(); } TEST_F(SimpleDataSourceTest, InitializeFTP) { - InitializeDataSource(kFtpUrl); + InitializeDataSource(kFtpUrl, false); RequestSucceeded(); DestroyDataSource(); } TEST_F(SimpleDataSourceTest, InitializeFile) { - InitializeDataSource(kFileUrl); + InitializeDataSource(kFileUrl, true); RequestSucceeded(); DestroyDataSource(); } @@ -221,13 +219,13 @@ TEST_F(SimpleDataSourceTest, InitializeInvalid) { } TEST_F(SimpleDataSourceTest, RequestFailed) { - InitializeDataSource(kHttpUrl); + InitializeDataSource(kHttpUrl, false); RequestFailed(); DestroyDataSource(); } TEST_F(SimpleDataSourceTest, StopWhenDownloading) { - InitializeDataSource(kHttpUrl); + InitializeDataSource(kHttpUrl, false); EXPECT_CALL(*bridge_, Cancel()); EXPECT_CALL(*bridge_, OnDestroy()) @@ -237,7 +235,7 @@ TEST_F(SimpleDataSourceTest, StopWhenDownloading) { } TEST_F(SimpleDataSourceTest, AsyncRead) { - InitializeDataSource(kFileUrl); + InitializeDataSource(kFileUrl, true); RequestSucceeded(); AsyncRead(); DestroyDataSource(); diff --git a/webkit/glue/webmediaplayer_impl.cc b/webkit/glue/webmediaplayer_impl.cc index d3d3679..0438e54 100644 --- a/webkit/glue/webmediaplayer_impl.cc +++ b/webkit/glue/webmediaplayer_impl.cc @@ -272,6 +272,7 @@ void WebMediaPlayerImpl::seek(float seconds) { // Try to preserve as much accuracy as possible. float microseconds = seconds * base::Time::kMicrosecondsPerSecond; + SetReadyState(WebKit::WebMediaPlayer::HaveMetadata); pipeline_->Seek( base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)), NewCallback(proxy_.get(), @@ -361,7 +362,10 @@ bool WebMediaPlayerImpl::paused() const { bool WebMediaPlayerImpl::seeking() const { DCHECK(MessageLoop::current() == main_loop_); - return false; + if (ready_state_ == WebKit::WebMediaPlayer::HaveNothing) + return false; + + return ready_state_ == WebKit::WebMediaPlayer::HaveMetadata; } float WebMediaPlayerImpl::duration() const { @@ -467,7 +471,11 @@ void WebMediaPlayerImpl::OnPipelineInitialize() { // TODO(hclam): change this to report the correct status. SetReadyState(WebKit::WebMediaPlayer::HaveMetadata); SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); - SetNetworkState(WebKit::WebMediaPlayer::Loaded); + if (pipeline_->IsLoaded()) { + SetNetworkState(WebKit::WebMediaPlayer::Loaded); + } else { + SetNetworkState(WebKit::WebMediaPlayer::Loading); + } } else { // TODO(hclam): should use pipeline_->GetError() to determine the state // properly and reports error using MediaError. @@ -484,6 +492,7 @@ void WebMediaPlayerImpl::OnPipelineInitialize() { void WebMediaPlayerImpl::OnPipelineSeek() { DCHECK(MessageLoop::current() == main_loop_); if (pipeline_->GetError() == media::PIPELINE_OK) { + SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData); GetClient()->timeChanged(); } } |