diff options
author | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-23 01:04:53 +0000 |
---|---|---|
committer | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-23 01:04:53 +0000 |
commit | a4f94d30e7a4218c4da5be8e57c9e7928cce6edd (patch) | |
tree | f5168e9bcc866e75fc4e60bc4505169013cd80fa /media/base | |
parent | ce6d4a00954320ed3b1713296f9eddd73445926b (diff) | |
download | chromium_src-a4f94d30e7a4218c4da5be8e57c9e7928cce6edd.zip chromium_src-a4f94d30e7a4218c4da5be8e57c9e7928cce6edd.tar.gz chromium_src-a4f94d30e7a4218c4da5be8e57c9e7928cce6edd.tar.bz2 |
Ensure media's buffered ranges always have a range that includes currentTime.
Avoids buffering bar disappearing/reappearing when the bytes are distributed
unevenly throughout the media.
BUG=133567,131444
Review URL: https://chromiumcodereview.appspot.com/10581050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143765 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/data_source.h | 7 | ||||
-rw-r--r-- | media/base/demuxer_stream.h | 4 | ||||
-rw-r--r-- | media/base/mock_data_source_host.h | 2 | ||||
-rw-r--r-- | media/base/mock_demuxer_host.h | 2 | ||||
-rw-r--r-- | media/base/mock_filters.h | 1 | ||||
-rw-r--r-- | media/base/pipeline.cc | 12 | ||||
-rw-r--r-- | media/base/pipeline.h | 3 | ||||
-rw-r--r-- | media/base/pipeline_unittest.cc | 13 | ||||
-rw-r--r-- | media/base/ranges.cc | 15 | ||||
-rw-r--r-- | media/base/ranges.h | 15 |
10 files changed, 73 insertions, 1 deletions
diff --git a/media/base/data_source.h b/media/base/data_source.h index 037c645..f2a6a17 100644 --- a/media/base/data_source.h +++ b/media/base/data_source.h @@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/time.h" #include "media/base/media_export.h" namespace media { @@ -19,7 +20,13 @@ class MEDIA_EXPORT DataSourceHost { virtual void SetTotalBytes(int64 total_bytes) = 0; // Notify the host that byte range [start,end] has been buffered. + // TODO(fischman): remove this method when demuxing is push-based instead of + // pull-based. http://crbug.com/131444 virtual void AddBufferedByteRange(int64 start, int64 end) = 0; + + // Notify the host that time range [start,end] has been buffered. + virtual void AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) = 0; }; class MEDIA_EXPORT DataSource : public base::RefCountedThreadSafe<DataSource> { diff --git a/media/base/demuxer_stream.h b/media/base/demuxer_stream.h index 4168d04..1266a71 100644 --- a/media/base/demuxer_stream.h +++ b/media/base/demuxer_stream.h @@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "media/base/media_export.h" +#include "media/base/ranges.h" namespace media { @@ -41,6 +42,9 @@ class MEDIA_EXPORT DemuxerStream // if type() != VIDEO. virtual const VideoDecoderConfig& video_decoder_config() = 0; + // Returns time ranges known to have been seen by this stream. + virtual Ranges<base::TimeDelta> GetBufferedRanges() = 0; + // Returns the type of stream. virtual Type type() = 0; diff --git a/media/base/mock_data_source_host.h b/media/base/mock_data_source_host.h index 83db550..914d055 100644 --- a/media/base/mock_data_source_host.h +++ b/media/base/mock_data_source_host.h @@ -20,6 +20,8 @@ class MockDataSourceHost : public DataSourceHost { // DataSourceHost implementation. MOCK_METHOD1(SetTotalBytes, void(int64 total_bytes)); MOCK_METHOD2(AddBufferedByteRange, void(int64 start, int64 end)); + MOCK_METHOD2(AddBufferedTimeRange, void(base::TimeDelta start, + base::TimeDelta end)); private: DISALLOW_COPY_AND_ASSIGN(MockDataSourceHost); diff --git a/media/base/mock_demuxer_host.h b/media/base/mock_demuxer_host.h index dab553a..597c132 100644 --- a/media/base/mock_demuxer_host.h +++ b/media/base/mock_demuxer_host.h @@ -20,6 +20,8 @@ class MockDemuxerHost : public DemuxerHost { // DataSourceHost implementation. MOCK_METHOD1(SetTotalBytes, void(int64 total_bytes)); MOCK_METHOD2(AddBufferedByteRange, void(int64 start, int64 end)); + MOCK_METHOD2(AddBufferedTimeRange, void(base::TimeDelta start, + base::TimeDelta end)); // DemuxerHost implementation. MOCK_METHOD1(OnDemuxerError, void(PipelineStatus error)); diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index e3d50ff..88e16bf 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -103,6 +103,7 @@ class MockDemuxerStream : public DemuxerStream { MOCK_METHOD0(audio_decoder_config, const AudioDecoderConfig&()); MOCK_METHOD0(video_decoder_config, const VideoDecoderConfig&()); MOCK_METHOD0(EnableBitstreamConverter, void()); + MOCK_METHOD0(GetBufferedRanges, Ranges<base::TimeDelta>()); protected: virtual ~MockDemuxerStream(); diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index de70983..b8f7755f 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc @@ -204,6 +204,10 @@ Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { Ranges<TimeDelta> time_ranges; if (clock_->Duration() == TimeDelta() || total_bytes_ == 0) return time_ranges; + for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) { + time_ranges.Add(buffered_time_ranges_.start(i), + buffered_time_ranges_.end(i)); + } for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) { TimeDelta start = TimeForByteOffset_Locked(buffered_byte_ranges_.start(i)); TimeDelta end = TimeForByteOffset_Locked(buffered_byte_ranges_.end(i)); @@ -457,6 +461,14 @@ void Pipeline::AddBufferedByteRange(int64 start, int64 end) { did_loading_progress_ = true; } +void Pipeline::AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) { + DCHECK(IsRunning()); + base::AutoLock auto_lock(lock_); + buffered_time_ranges_.Add(start, end); + did_loading_progress_ = true; +} + void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { DCHECK(IsRunning()); media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 45fdd33..5a13633 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -288,6 +288,8 @@ class MEDIA_EXPORT Pipeline // DataSourceHost (by way of DemuxerHost) implementation. virtual void SetTotalBytes(int64 total_bytes) OVERRIDE; virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE; + virtual void AddBufferedTimeRange(base::TimeDelta start, + base::TimeDelta end) OVERRIDE; // DemuxerHost implementaion. virtual void SetDuration(base::TimeDelta duration) OVERRIDE; @@ -460,6 +462,7 @@ class MEDIA_EXPORT Pipeline // Amount of available buffered data. Set by filters. Ranges<int64> buffered_byte_ranges_; + Ranges<base::TimeDelta> buffered_time_ranges_; // True when AddBufferedByteRange() has been called more recently than // DidLoadingProgress(). diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index b2c08eb..5133695 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -480,11 +480,15 @@ TEST_F(PipelineTest, GetBufferedTimeRanges) { EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size()); EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); + pipeline_->AddBufferedTimeRange(base::TimeDelta(), kDuration / 8); + EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); + EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); base::TimeDelta kSeekTime = kDuration / 2; ExpectSeek(kSeekTime); DoSeek(kSeekTime); + EXPECT_TRUE(pipeline_->DidLoadingProgress()); EXPECT_FALSE(pipeline_->DidLoadingProgress()); pipeline_->AddBufferedByteRange(kTotalBytes / 2, kTotalBytes / 2 + kTotalBytes / 8); @@ -496,6 +500,15 @@ TEST_F(PipelineTest, GetBufferedTimeRanges) { EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(1)); EXPECT_EQ(kDuration / 2 + kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1)); + + pipeline_->AddBufferedTimeRange(kDuration / 4, 3 * kDuration / 8); + EXPECT_EQ(base::TimeDelta(), pipeline_->GetBufferedTimeRanges().start(0)); + EXPECT_EQ(kDuration / 8, pipeline_->GetBufferedTimeRanges().end(0)); + EXPECT_EQ(kDuration / 4, pipeline_->GetBufferedTimeRanges().start(1)); + EXPECT_EQ(3* kDuration / 8, pipeline_->GetBufferedTimeRanges().end(1)); + EXPECT_EQ(kDuration / 2, pipeline_->GetBufferedTimeRanges().start(2)); + EXPECT_EQ(kDuration / 2 + kDuration / 8, + pipeline_->GetBufferedTimeRanges().end(2)); } TEST_F(PipelineTest, DisableAudioRenderer) { diff --git a/media/base/ranges.cc b/media/base/ranges.cc new file mode 100644 index 0000000..b7b2b55 --- /dev/null +++ b/media/base/ranges.cc @@ -0,0 +1,15 @@ +// 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/ranges.h" + +namespace media { + +template<> +void Ranges<base::TimeDelta>::DCheckLT(const base::TimeDelta& lhs, + const base::TimeDelta& rhs) const { + DCHECK(lhs < rhs) << lhs.ToInternalValue() << " < " << rhs.ToInternalValue(); +} + +} // namespace media diff --git a/media/base/ranges.h b/media/base/ranges.h index 1117ae5..82bf7a0 100644 --- a/media/base/ranges.h +++ b/media/base/ranges.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/logging.h" +#include "base/time.h" #include "media/base/media_export.h" namespace media { @@ -41,6 +42,9 @@ class Ranges { Ranges<T> IntersectionWith(const Ranges<T>& other); private: + // Wrapper around DCHECK_LT allowing comparisons of operator<<'able T's. + void DCheckLT(const T& lhs, const T& rhs) const; + // Disjoint, in increasing order of start. std::vector<std::pair<T, T> > ranges_; }; @@ -54,7 +58,7 @@ size_t Ranges<T>::Add(T start, T end) { if (start == end) // Nothing to be done with empty ranges. return ranges_.size(); - DCHECK(start < end); + DCheckLT(start, end); size_t i; // Walk along the array of ranges until |start| is no longer larger than the // current interval's end. @@ -99,6 +103,15 @@ size_t Ranges<T>::Add(T start, T end) { return ranges_.size(); } +template<> +void Ranges<base::TimeDelta>::DCheckLT(const base::TimeDelta& lhs, + const base::TimeDelta& rhs) const; + +template<class T> +void Ranges<T>::DCheckLT(const T& lhs, const T& rhs) const { + DCHECK_LT(lhs, rhs); +} + template<class T> size_t Ranges<T>::size() const { return ranges_.size(); |