diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-25 21:30:39 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-25 21:30:39 +0000 |
commit | f70f8e1b866fc57b29bd317f40e2453e9c9de2a6 (patch) | |
tree | 97e5590a23675b4d0b6e3186cf3df43154aa7c79 /media | |
parent | d265369f2b05102f44e88b3586562060973ecf48 (diff) | |
download | chromium_src-f70f8e1b866fc57b29bd317f40e2453e9c9de2a6.zip chromium_src-f70f8e1b866fc57b29bd317f40e2453e9c9de2a6.tar.gz chromium_src-f70f8e1b866fc57b29bd317f40e2453e9c9de2a6.tar.bz2 |
Reporting a more accurate buffered time for the video tag
Instead of showing that the entire file is buffered when the video first loads, this uses current time, current bytes, and buffered bytes to estimate buffered time.
Reviewed: http://codereview.chromium.org/2085012/
Submitted for: vrk@chromium.org
BUG=42285
TEST=NONE
Review URL: http://codereview.chromium.org/2192001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48199 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/filter_host.h | 6 | ||||
-rw-r--r-- | media/base/mock_filter_host.h | 2 | ||||
-rw-r--r-- | media/base/pipeline.h | 2 | ||||
-rw-r--r-- | media/base/pipeline_impl.cc | 39 | ||||
-rw-r--r-- | media/base/pipeline_impl.h | 13 | ||||
-rw-r--r-- | media/base/pipeline_impl_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.cc | 3 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer_unittest.cc | 2 |
8 files changed, 56 insertions, 13 deletions
diff --git a/media/base/filter_host.h b/media/base/filter_host.h index e90096f..e28a957 100644 --- a/media/base/filter_host.h +++ b/media/base/filter_host.h @@ -74,6 +74,12 @@ class FilterHost { // filters. virtual void DisableAudioRenderer() = 0; + // Sets the byte offset at which the client is requesting the video. + virtual void SetCurrentReadPosition(int64 offset) = 0; + + // Gets the byte offset at which the client is requesting the video. + virtual int64 GetCurrentReadPosition() = 0; + protected: virtual ~FilterHost() {} }; diff --git a/media/base/mock_filter_host.h b/media/base/mock_filter_host.h index a2fada9..691790c 100644 --- a/media/base/mock_filter_host.h +++ b/media/base/mock_filter_host.h @@ -42,6 +42,8 @@ class MockFilterHost : public FilterHost { MOCK_METHOD1(SetNetworkActivity, void(bool network_activity)); MOCK_METHOD0(NotifyEnded, void()); MOCK_METHOD0(DisableAudioRenderer, void()); + MOCK_METHOD1(SetCurrentReadPosition, void(int64 offset)); + MOCK_METHOD0(GetCurrentReadPosition, int64()); private: DISALLOW_COPY_AND_ASSIGN(MockFilterHost); diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 82c551c..8e39d06 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -129,7 +129,7 @@ class Pipeline : public base::RefCountedThreadSafe<Pipeline> { // Get the approximate amount of playable data buffered so far in micro- // seconds. - virtual base::TimeDelta GetBufferedTime() const = 0; + virtual base::TimeDelta GetBufferedTime() = 0; // Get the duration of the media in microseconds. If the duration has not // been determined yet, then returns 0. diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index b5a193e..532236d 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -77,7 +77,8 @@ PipelineImpl::PipelineImpl(MessageLoop* message_loop) clock_(&base::Time::Now), waiting_for_clock_update_(false), state_(kCreated), - remaining_transitions_(0) { + remaining_transitions_(0), + current_bytes_(0) { ResetState(); } @@ -220,24 +221,32 @@ base::TimeDelta PipelineImpl::GetCurrentTime() const { return elapsed; } -base::TimeDelta PipelineImpl::GetBufferedTime() const { + +base::TimeDelta PipelineImpl::GetBufferedTime() { + DCHECK(buffered_bytes_ >= current_bytes_); AutoLock auto_lock(lock_); // If buffered time was set, we report that value directly. if (buffered_time_.ToInternalValue() > 0) return buffered_time_; - // If buffered time was not set, we use duration and buffered bytes to - // estimate the buffered time. - // TODO(hclam): The estimation is based on linear interpolation which is - // not accurate enough. We should find a better way to estimate the value. - if (total_bytes_ == 0) + if (total_bytes_ == 0 || current_bytes_ == 0) return base::TimeDelta(); - double ratio = static_cast<double>(buffered_bytes_); - ratio /= total_bytes_; + // If buffered time was not set, we use current time, current bytes, and + // buffered bytes to estimate the buffered time. + double current_time = static_cast<double>(current_bytes_) / total_bytes_ * + duration_.InMilliseconds(); + double rate = current_time / current_bytes_; + double buffered_time = rate * (buffered_bytes_ - current_bytes_) + + current_time; + + // Only print the max buffered time for smooth buffering. + if (buffered_time > max_buffered_time_) + max_buffered_time_ = buffered_time; + return base::TimeDelta::FromMilliseconds( - static_cast<int64>(duration_.InMilliseconds() * ratio)); + static_cast<int64>(max_buffered_time_)); } base::TimeDelta PipelineImpl::GetMediaDuration() const { @@ -278,6 +287,16 @@ PipelineError PipelineImpl::GetError() const { return error_; } +void PipelineImpl::SetCurrentReadPosition(int64 offset) { + AutoLock auto_lock(lock_); + current_bytes_ = offset; +} + +int64 PipelineImpl::GetCurrentReadPosition() { + AutoLock auto_lock(lock_); + return current_bytes_; +} + void PipelineImpl::SetPipelineEndedCallback(PipelineCallback* ended_callback) { DCHECK(!IsRunning()) << "Permanent callbacks should be set before the pipeline has started"; diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 27ce43f..61f360b 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -79,7 +79,7 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual float GetVolume() const; virtual void SetVolume(float volume); virtual base::TimeDelta GetCurrentTime() const; - virtual base::TimeDelta GetBufferedTime() const; + virtual base::TimeDelta GetBufferedTime(); virtual base::TimeDelta GetMediaDuration() const; virtual int64 GetBufferedBytes() const; virtual int64 GetTotalBytes() const; @@ -153,6 +153,8 @@ class PipelineImpl : public Pipeline, public FilterHost { virtual void SetNetworkActivity(bool network_activity); virtual void NotifyEnded(); virtual void DisableAudioRenderer(); + virtual void SetCurrentReadPosition(int64 offset); + virtual int64 GetCurrentReadPosition(); // Method called during initialization to insert a mime type into the // |rendered_mime_types_| set. @@ -357,6 +359,15 @@ class PipelineImpl : public Pipeline, public FilterHost { // replies. base::TimeDelta seek_timestamp_; + // For GetCurrentBytes()/SetCurrentBytes() we need to know what byte we are + // currently reading. + int64 current_bytes_; + + // Keep track of the maximum buffered position so the buffering appears + // smooth. + // TODO(vrk): This is a hack. + double max_buffered_time_; + // Filter factory as passed in by Start(). scoped_refptr<FilterFactory> filter_factory_; diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc index 86b4e27..82c9fd9 100644 --- a/media/base/pipeline_impl_unittest.cc +++ b/media/base/pipeline_impl_unittest.cc @@ -488,7 +488,7 @@ TEST_F(PipelineImplTest, Properties) { pipeline_->GetMediaDuration().ToInternalValue()); EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes()); EXPECT_EQ(kBufferedBytes, pipeline_->GetBufferedBytes()); - EXPECT_EQ(kDuration.ToInternalValue(), + EXPECT_EQ(0, pipeline_->GetBufferedTime().ToInternalValue()); } diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 5268c59..4092023 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -335,6 +335,9 @@ int FFmpegDemuxer::Read(int size, uint8* data) { return AVERROR_IO; } read_position_ += last_read_bytes; + + host()->SetCurrentReadPosition(read_position_); + return last_read_bytes; } diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 31d575f..ec263a6 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc @@ -716,6 +716,7 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) { EXPECT_CALL(*demuxer, SignalReadCompleted(512)); EXPECT_CALL(*demuxer, WaitForRead()) .WillOnce(Return(512)); + EXPECT_CALL(host_, SetCurrentReadPosition(512)); // Second read. EXPECT_CALL(*data_source_, GetSize(_)) @@ -725,6 +726,7 @@ TEST_F(FFmpegDemuxerTest, ProtocolRead) { EXPECT_CALL(*demuxer, SignalReadCompleted(512)); EXPECT_CALL(*demuxer, WaitForRead()) .WillOnce(Return(512)); + EXPECT_CALL(host_, SetCurrentReadPosition(1024)); // Third read will fail because it exceeds the file size. EXPECT_CALL(*data_source_, GetSize(_)) |