summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-23 01:04:53 +0000
committerfischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-23 01:04:53 +0000
commita4f94d30e7a4218c4da5be8e57c9e7928cce6edd (patch)
treef5168e9bcc866e75fc4e60bc4505169013cd80fa /media/base
parentce6d4a00954320ed3b1713296f9eddd73445926b (diff)
downloadchromium_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.h7
-rw-r--r--media/base/demuxer_stream.h4
-rw-r--r--media/base/mock_data_source_host.h2
-rw-r--r--media/base/mock_demuxer_host.h2
-rw-r--r--media/base/mock_filters.h1
-rw-r--r--media/base/pipeline.cc12
-rw-r--r--media/base/pipeline.h3
-rw-r--r--media/base/pipeline_unittest.cc13
-rw-r--r--media/base/ranges.cc15
-rw-r--r--media/base/ranges.h15
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();