summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 20:10:32 +0000
committerhclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-30 20:10:32 +0000
commit1ce1f40ba144705c5a52bccf6c7cf82c2bf405d9 (patch)
tree2c20c121e89f9802a67b59125cef3f477a1c5bcd /media
parentc16ca81ff44eba2d8d5b66b14aa35f1629202c58 (diff)
downloadchromium_src-1ce1f40ba144705c5a52bccf6c7cf82c2bf405d9.zip
chromium_src-1ce1f40ba144705c5a52bccf6c7cf82c2bf405d9.tar.gz
chromium_src-1ce1f40ba144705c5a52bccf6c7cf82c2bf405d9.tar.bz2
Missing buffered attribute for <video>/<audio>
BUG=16056 TEST=LayoutTests/media/video-buffered.html The current implementation of the buffered attribute for <video> and <audio> is broken. There are several problems around this attribute: 1. We don't have any caching on disk, so we only keep a recent range of bytes close to current playback position. 2. WebKit reports buffered as one range (0, max_time_buffered). But we only cache a short partial range which doesn't start with 0. The correct implementation is a list of ranges buffered. But this has to go into WebKit first. 3. We don't have an accurate mapping between byte offset < - > timestamp. So the current implementation is to lie about what we have buffered. We always say we have buffered everything before the current download position. And we only report one range. The calculation of time is also based on scaling the duration with current buffered bytes. Review URL: http://codereview.chromium.org/160300 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22087 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/mock_filters.h12
-rw-r--r--media/base/pipeline_impl.cc17
-rw-r--r--media/base/pipeline_impl_unittest.cc37
3 files changed, 64 insertions, 2 deletions
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index d3546c4..533ced7 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -342,6 +342,18 @@ ACTION_P2(SetDuration, filter, duration) {
filter->host()->SetDuration(duration);
}
+// Helper gmock action that calls SetTotalBytes() on behalf of the provided
+// filter.
+ACTION_P2(SetTotalBytes, filter, bytes) {
+ filter->host()->SetTotalBytes(bytes);
+}
+
+// Helper gmock action that calls SetBufferedBytes() on behalf of the provided
+// filter.
+ACTION_P2(SetBufferedBytes, filter, bytes) {
+ filter->host()->SetBufferedBytes(bytes);
+}
+
} // namespace media
#endif // MEDIA_BASE_MOCK_FILTERS_H_
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index 05ee62e..cc1c3b2 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -211,7 +211,22 @@ base::TimeDelta PipelineImpl::GetCurrentTime() const {
base::TimeDelta PipelineImpl::GetBufferedTime() const {
AutoLock auto_lock(lock_);
- return buffered_time_;
+
+ // 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)
+ return base::TimeDelta();
+
+ double ratio = static_cast<double>(buffered_bytes_);
+ ratio /= total_bytes_;
+ return base::TimeDelta::FromMilliseconds(
+ static_cast<int64>(duration_.InMilliseconds() * ratio));
}
base::TimeDelta PipelineImpl::GetDuration() const {
diff --git a/media/base/pipeline_impl_unittest.cc b/media/base/pipeline_impl_unittest.cc
index 068b095..6400049 100644
--- a/media/base/pipeline_impl_unittest.cc
+++ b/media/base/pipeline_impl_unittest.cc
@@ -20,6 +20,16 @@ using ::testing::NotNull;
using ::testing::Return;
using ::testing::StrictMock;
+namespace {
+
+// Total bytes of the data source.
+const int kTotalBytes = 1024;
+
+// Buffered bytes of the data source.
+const int kBufferedBytes = 1024;
+
+} // namespace
+
namespace media {
// Used for setting expectations on pipeline callbacks. Using a StrictMock
@@ -70,7 +80,9 @@ class PipelineImplTest : public ::testing::Test {
// Sets up expectations to allow the data source to initialize.
void InitializeDataSource() {
EXPECT_CALL(*mocks_->data_source(), Initialize("", NotNull()))
- .WillOnce(Invoke(&RunFilterCallback));
+ .WillOnce(DoAll(SetTotalBytes(mocks_->data_source(), kTotalBytes),
+ SetBufferedBytes(mocks_->data_source(), kBufferedBytes),
+ Invoke(&RunFilterCallback)));
EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(0.0f));
EXPECT_CALL(*mocks_->data_source(), Seek(base::TimeDelta(), NotNull()))
.WillOnce(Invoke(&RunFilterCallback));
@@ -404,4 +416,27 @@ TEST_F(PipelineImplTest, SetVolume) {
pipeline_->SetVolume(expected);
}
+TEST_F(PipelineImplTest, Properties) {
+ scoped_refptr<StrictMock<MockDemuxerStream> > stream =
+ new StrictMock<MockDemuxerStream>("video/x-foo");
+ MockDemuxerStreamVector streams;
+ streams.push_back(stream);
+
+ InitializeDataSource();
+ base::TimeDelta kDuration = base::TimeDelta::FromSeconds(100);
+ InitializeDemuxer(&streams, kDuration);
+ InitializeVideoDecoder(stream);
+ InitializeVideoRenderer();
+
+ InitializePipeline();
+ EXPECT_TRUE(pipeline_->IsInitialized());
+ EXPECT_EQ(PIPELINE_OK, pipeline_->GetError());
+ EXPECT_EQ(kDuration.ToInternalValue(),
+ pipeline_->GetDuration().ToInternalValue());
+ EXPECT_EQ(kTotalBytes, pipeline_->GetTotalBytes());
+ EXPECT_EQ(kBufferedBytes, pipeline_->GetBufferedBytes());
+ EXPECT_EQ(kDuration.ToInternalValue(),
+ pipeline_->GetBufferedTime().ToInternalValue());
+}
+
} // namespace media