summaryrefslogtreecommitdiffstats
path: root/media/base
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-21 02:58:18 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-21 02:58:18 +0000
commit21e3afccb6c9a1cb33b7159d1c17cf346a8fdf46 (patch)
tree89e4993199c8cbeecff14c6270ea1d241c022e82 /media/base
parent88e81a8e2768184d451df062f33cd6ca19f6f718 (diff)
downloadchromium_src-21e3afccb6c9a1cb33b7159d1c17cf346a8fdf46.zip
chromium_src-21e3afccb6c9a1cb33b7159d1c17cf346a8fdf46.tar.gz
chromium_src-21e3afccb6c9a1cb33b7159d1c17cf346a8fdf46.tar.bz2
Revert 118546 because it caused PrerenderHTML5VideoNetwork to timeout on windows and linux
""" Fire canplaythrough as soon as download defers to fix autoplay Reenables delayed firing of canplaythrough for media elements, and fixes the bug that had been introduced where a video with autoplay=true sometimes never starts. With this change, a video with autoplay=true should always (though not necessarily immediately) start playback on its own. BUG=106480,73609 TEST=media_unitests, manually checking video files in various conditions Review URL: https://chromiumcodereview.appspot.com/9113023 TBR=vrk@google.com Review URL: https://chromiumcodereview.appspot.com/9269027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118590 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base')
-rw-r--r--media/base/download_rate_monitor.cc31
-rw-r--r--media/base/download_rate_monitor.h8
-rw-r--r--media/base/download_rate_monitor_unittest.cc231
-rw-r--r--media/base/pipeline.cc8
4 files changed, 109 insertions, 169 deletions
diff --git a/media/base/download_rate_monitor.cc b/media/base/download_rate_monitor.cc
index dd3c7ef..f27b2e8 100644
--- a/media/base/download_rate_monitor.cc
+++ b/media/base/download_rate_monitor.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -91,6 +91,8 @@ void DownloadRateMonitor::SetBufferedBytes(
if (stopped_)
return;
+ is_downloading_data_ = true;
+
// Check monotonically nondecreasing constraint.
base::Time previous_time;
if (!current_sample_.is_null())
@@ -118,11 +120,12 @@ void DownloadRateMonitor::SetBufferedBytes(
}
void DownloadRateMonitor::SetNetworkActivity(bool is_downloading_data) {
- // Record when download defers for the first time.
- if (!is_downloading_data && !has_deferred_) {
- has_deferred_ = true;
- NotifyCanPlayThroughIfNeeded();
- }
+ if (is_downloading_data == is_downloading_data_)
+ return;
+ // Invalidate the current sample if downloading is going from start to stopped
+ // or vice versa.
+ current_sample_.Reset();
+ is_downloading_data_ = is_downloading_data;
}
void DownloadRateMonitor::Stop() {
@@ -136,13 +139,13 @@ void DownloadRateMonitor::Reset() {
has_notified_can_play_through_ = false;
current_sample_.Reset();
sample_window_.clear();
+ is_downloading_data_ = false;
total_bytes_ = -1;
buffered_bytes_ = 0;
local_source_ = false;
bitrate_ = 0;
stopped_ = true;
streaming_ = false;
- has_deferred_ = false;
}
DownloadRateMonitor::~DownloadRateMonitor() { }
@@ -207,9 +210,8 @@ bool DownloadRateMonitor::ShouldNotifyCanPlayThrough() {
if (local_source_ || streaming_)
return true;
- // If all bytes are buffered or if enough bytes were buffered such that
- // downloading has deferred, fire CanPlayThrough.
- if (buffered_bytes_ == total_bytes_ || has_deferred_)
+ // If all bytes are buffered, fire CanPlayThrough.
+ if (buffered_bytes_ == total_bytes_)
return true;
// If bitrate is unknown, optimistically fire CanPlayThrough immediately.
@@ -226,9 +228,12 @@ bool DownloadRateMonitor::ShouldNotifyCanPlayThrough() {
if (download_rate > 0)
return download_rate >= bytes_needed_per_second;
- // With very fast connections, we may want to fire CanPlayThrough before
- // waiting for the sample window size to reach |kNumberOfSamples|. Check for
- // this scenario.
+ // If download rate is unknown, it may be because the media is being
+ // downloaded so fast that it cannot collect an adequate number of samples
+ // before the download gets deferred.
+ //
+ // To catch this case, we also look at how much data is being downloaded
+ // immediately after the download begins.
if (sample_window_.size() < kNumberOfSamples) {
int64 bytes_downloaded_since_start =
bytes_downloaded_in_window() + current_sample_.bytes_downloaded();
diff --git a/media/base/download_rate_monitor.h b/media/base/download_rate_monitor.h
index b26c61b..4fca328 100644
--- a/media/base/download_rate_monitor.h
+++ b/media/base/download_rate_monitor.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -126,6 +126,9 @@ class MEDIA_EXPORT DownloadRateMonitor {
Sample current_sample_;
std::deque<Sample> sample_window_;
+ // True if actively downloading bytes, false otherwise.
+ bool is_downloading_data_;
+
// Total number of bytes in the media file, 0 if unknown or undefined.
int64 total_bytes_;
@@ -146,9 +149,6 @@ class MEDIA_EXPORT DownloadRateMonitor {
// True if the data source is a streaming source, false otherwise.
bool streaming_;
- // True if downloading has been deferred at least once, false otherwise.
- bool has_deferred_;
-
DISALLOW_COPY_AND_ASSIGN(DownloadRateMonitor);
};
diff --git a/media/base/download_rate_monitor_unittest.cc b/media/base/download_rate_monitor_unittest.cc
index 9715526..321ad63 100644
--- a/media/base/download_rate_monitor_unittest.cc
+++ b/media/base/download_rate_monitor_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -15,216 +15,151 @@ namespace media {
class DownloadRateMonitorTest : public ::testing::Test {
public:
- DownloadRateMonitorTest()
- : canplaythrough_cb_(base::Bind(&DownloadRateMonitorTest::CanPlayThrough,
- base::Unretained(this))) { }
+ DownloadRateMonitorTest() {
+ monitor_.set_total_bytes(kMediaSizeInBytes);
+ }
virtual ~DownloadRateMonitorTest() { }
MOCK_METHOD0(CanPlayThrough, void());
protected:
- static const int kMediaDuration = 120;
- static const int kMediaBitrate = 1024 * 1024 * 8;
- static const int kMediaByterate = kMediaBitrate / 8;
- static const int kMediaSizeInBytes = kMediaDuration * kMediaByterate;
- static const int kDeferThreshold = 30 * kMediaByterate;
-
- // Simulates downloading |bytes_to_download| bytes of the media file, at
- // |download_speed_in_bps| bytes per second.
- void SimulateNetwork(int bytes_to_download, int download_speed_in_bps) {
- int bytes_downloaded = 0;
- while (bytes_downloaded < bytes_to_download &&
- !data_source_.is_deferred()) {
- int bytes_left_to_download = bytes_to_download - bytes_downloaded;
- int packet_size = std::min(download_speed_in_bps, bytes_left_to_download);
- time_elapsed_ += base::TimeDelta::FromMilliseconds(
- 1000 * packet_size / download_speed_in_bps);
- data_source_.ReceiveData(
- packet_size, time_elapsed_ + base::Time::UnixEpoch());
- bytes_downloaded += packet_size;
+ static const int kMediaSizeInBytes = 20 * 1024 * 1024;
+
+ // Simulates downloading of the media file. Packets are timed evenly in
+ // |ms_between_packets| intervals, starting at |starting_time|, which is
+ // number of seconds since unix epoch (Jan 1, 1970).
+ // Returns the number of bytes buffered in the media file after the
+ // network activity.
+ int SimulateNetwork(double starting_time,
+ int starting_bytes,
+ int bytes_per_packet,
+ int ms_between_packets,
+ int number_of_packets) {
+ int bytes_buffered = starting_bytes;
+ base::Time packet_time = base::Time::FromDoubleT(starting_time);
+
+ monitor_.SetNetworkActivity(true);
+ // Loop executes (number_of_packets + 1) times because a packet needs a
+ // starting and end point.
+ for (int i = 0; i < number_of_packets + 1; ++i) {
+ monitor_.SetBufferedBytes(bytes_buffered, packet_time);
+ packet_time += base::TimeDelta::FromMilliseconds(ms_between_packets);
+ bytes_buffered += bytes_per_packet;
}
+ monitor_.SetNetworkActivity(false);
+ return bytes_buffered;
}
- void Initialize() {
- Initialize(false, false);
- }
-
- void Initialize(bool streaming, bool local_source) {
- data_source_.Initialize(
- kMediaBitrate, streaming, local_source, canplaythrough_cb_);
- }
-
- bool DownloadIsDeferred() {
- return data_source_.is_deferred();
+ void StartMonitor(int bitrate) {
+ StartMonitor(bitrate, false, false);
}
- void SeekTo(int offset) {
- data_source_.SeekTo(offset);
+ void StartMonitor(int bitrate, bool streaming, bool local_source) {
+ monitor_.Start(base::Bind(&DownloadRateMonitorTest::CanPlayThrough,
+ base::Unretained(this)), bitrate, streaming, local_source);
}
- // Returns the size of |seconds| seconds of media data in bytes.
- int SecondsToBytes(int seconds) {
- return seconds * kMediaByterate;
- }
+ DownloadRateMonitor monitor_;
private:
- // Helper class to simulate a buffered data source.
- class FakeDataSource {
- public:
- FakeDataSource()
- : total_bytes_(kMediaSizeInBytes),
- buffered_bytes_(0),
- offset_(0),
- defer_threshold_(kDeferThreshold),
- is_downloading_data_(true) { }
-
- bool is_deferred() { return !is_downloading_data_; }
-
- void ReceiveData(int bytes_received, base::Time packet_time) {
- CHECK(is_downloading_data_);
- buffered_bytes_ += bytes_received;
- // This simulates that the download is being deferred.
- if (buffered_bytes_ >= defer_threshold_)
- is_downloading_data_ = false;
-
- // Update monitor's state.
- monitor_.SetNetworkActivity(is_downloading_data_);
- monitor_.set_total_bytes(total_bytes_);
- monitor_.SetBufferedBytes(buffered_bytes_ + offset_, packet_time);
- }
-
- void Initialize(int bitrate, bool streaming, bool local_source,
- const base::Closure& canplaythrough_cb) {
- monitor_.Start(canplaythrough_cb, bitrate, streaming, local_source);
- }
-
- void SeekTo(int byte_position) {
- offset_ = byte_position;
- // Simulate recreating the buffer after a seek.
- buffered_bytes_ = 0;
- is_downloading_data_ = true;
- }
-
- private:
- DownloadRateMonitor monitor_;
-
- // Size of the media file being downloaded, in bytes.
- int total_bytes_;
-
- // Number of bytes currently in buffer.
- int buffered_bytes_;
-
- // The byte offset into the file from which the download began.
- int offset_;
-
- // The size of |buffered_bytes_| at which downloading should defer.
- int defer_threshold_;
-
- // True if download is active (not deferred_, false otherwise.
- bool is_downloading_data_;
- };
-
- FakeDataSource data_source_;
- base::Closure canplaythrough_cb_;
-
- // Amount of time elapsed while downloading data.
- base::TimeDelta time_elapsed_;
-
DISALLOW_COPY_AND_ASSIGN(DownloadRateMonitorTest);
};
TEST_F(DownloadRateMonitorTest, DownloadRateGreaterThanBitrate) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+
// Simulate downloading at double the media's bitrate.
- Initialize();
+ StartMonitor(media_bitrate);
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(SecondsToBytes(20), 2 * kMediaByterate);
+ SimulateNetwork(1, 0, 2 * media_bitrate / 8, 1000, 10);
}
-TEST_F(DownloadRateMonitorTest, DownloadRateLessThanBitrate_Defer) {
- Initialize();
+// If the user pauses and the pipeline stops downloading data, make sure the
+// DownloadRateMonitor understands that the download is not stalling.
+TEST_F(DownloadRateMonitorTest, DownloadRateGreaterThanBitrate_Pause) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+ static const int download_byte_rate = 1.1 * media_bitrate / 8;
- // Download slower than the media's bitrate, but buffer enough data such that
- // the data source defers.
+ // Start downloading faster than the media's bitrate.
+ StartMonitor(media_bitrate);
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(kDeferThreshold, 0.3 * kMediaByterate);
- CHECK(DownloadIsDeferred());
+ int buffered = SimulateNetwork(1, 0, download_byte_rate, 1000, 2);
+
+ // Then "pause" for 3 minutes and continue downloading at same rate.
+ SimulateNetwork(60 * 3, buffered, download_byte_rate, 1000, 4);
}
TEST_F(DownloadRateMonitorTest, DownloadRateGreaterThanBitrate_SeekForward) {
- // Start downloading faster than the media's bitrate.
- Initialize();
- SimulateNetwork(SecondsToBytes(3), 1.1 * kMediaByterate);
+ static const int media_bitrate = 1024 * 1024 * 8;
+ static const int download_byte_rate = 1.1 * media_bitrate / 8;
- // Then seek forward mid-file and continue downloading at same rate.
- SeekTo(kMediaSizeInBytes / 2);
+ // Start downloading faster than the media's bitrate.
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(7 * kMediaByterate, 1.1 * kMediaByterate);
+ StartMonitor(media_bitrate);
+ SimulateNetwork(1, 0, download_byte_rate, 1000, 2);
- // Verify deferring is not what caused CanPlayThrough to fire.
- CHECK(!DownloadIsDeferred());
+ // Then seek forward mid-file and continue downloading at same rate.
+ SimulateNetwork(4, kMediaSizeInBytes / 2, download_byte_rate, 1000, 4);
}
TEST_F(DownloadRateMonitorTest, DownloadRateGreaterThanBitrate_SeekBackward) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+ static const int download_byte_rate = 1.1 * media_bitrate / 8;
+
// Start downloading faster than the media's bitrate, in middle of file.
- Initialize();
- SeekTo(kMediaSizeInBytes / 2);
- SimulateNetwork(SecondsToBytes(3), 1.1 * kMediaByterate);
+ StartMonitor(media_bitrate);
+ SimulateNetwork(1, kMediaSizeInBytes / 2, download_byte_rate, 1000, 2);
// Then seek back to beginning and continue downloading at same rate.
- SeekTo(0);
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(SecondsToBytes(7), 1.1 * kMediaByterate);
-
- // Verify deferring is not what caused CanPlayThrough to fire.
- CHECK(!DownloadIsDeferred());
+ SimulateNetwork(4, 0, download_byte_rate, 1000, 4);
}
-TEST_F(DownloadRateMonitorTest, DownloadRateLessThanByterate) {
+TEST_F(DownloadRateMonitorTest, DownloadRateLessThanBitrate) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+
// Simulate downloading at half the media's bitrate.
EXPECT_CALL(*this, CanPlayThrough())
.Times(0);
- Initialize();
- SimulateNetwork(SecondsToBytes(10), kMediaByterate / 2);
+ StartMonitor(media_bitrate);
+ SimulateNetwork(1, 0, media_bitrate / 8 / 2, 1000, 10);
}
TEST_F(DownloadRateMonitorTest, MediaSourceIsLocal) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+
// Simulate no data downloaded.
EXPECT_CALL(*this, CanPlayThrough());
- Initialize(false, true);
+ StartMonitor(media_bitrate, false, true);
}
TEST_F(DownloadRateMonitorTest, MediaSourceIsStreaming) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+
// Simulate downloading at the media's bitrate while streaming.
EXPECT_CALL(*this, CanPlayThrough());
- Initialize(true, false);
- SimulateNetwork(SecondsToBytes(10), kMediaByterate);
+ StartMonitor(media_bitrate, true, false);
+ SimulateNetwork(1, 0, media_bitrate / 8, 1000, 10);
}
TEST_F(DownloadRateMonitorTest, VeryFastDownloadRate) {
+ static const int media_bitrate = 1024 * 1024 * 8;
+
// Simulate downloading half the video very quickly in one chunk.
- Initialize();
+ StartMonitor(media_bitrate);
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(kMediaSizeInBytes / 2, kMediaSizeInBytes * 10);
+ SimulateNetwork(1, 0, kMediaSizeInBytes / 2, 10, 1);
}
TEST_F(DownloadRateMonitorTest, DownloadEntireVideo) {
- // Simulate downloading entire video at half the bitrate of the video.
- Initialize();
- EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(kMediaSizeInBytes, kMediaByterate / 2);
-}
+ static const int seconds_of_data = 20;
+ static const int media_bitrate = kMediaSizeInBytes * 8 / seconds_of_data;
-TEST_F(DownloadRateMonitorTest, DownloadEndOfVideo) {
- Initialize();
- // Seek to 10s before the end of the file, then download the remainder of the
- // file at half the bitrate.
- SeekTo((kMediaDuration - 10) * kMediaByterate);
+ // Simulate downloading entire video at half the bitrate of the video.
+ StartMonitor(media_bitrate);
EXPECT_CALL(*this, CanPlayThrough());
- SimulateNetwork(SecondsToBytes(10), kMediaByterate/ 2);
-
- // Verify deferring is not what caused CanPlayThrough to fire.
- CHECK(!DownloadIsDeferred());
+ SimulateNetwork(1, 0, media_bitrate / 8 / 2, 1000, seconds_of_data * 2);
}
} // namespace media
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
index d1b68fb..7995796 100644
--- a/media/base/pipeline.cc
+++ b/media/base/pipeline.cc
@@ -1020,8 +1020,11 @@ void Pipeline::FilterStateTransitionTask() {
// Start monitoring rate of downloading.
int bitrate = 0;
- if (demuxer_.get())
+ if (demuxer_.get()) {
bitrate = demuxer_->GetBitrate();
+ local_source_ = demuxer_->IsLocalSource();
+ streaming_ = !demuxer_->IsSeekable();
+ }
// Needs to be locked because most other calls to |download_rate_monitor_|
// occur on the renderer thread.
download_rate_monitor_.Start(
@@ -1136,9 +1139,6 @@ void Pipeline::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) {
}
demuxer_ = demuxer;
- // Set fields obtained from demuxer.
- local_source_ = demuxer_->IsLocalSource();
- streaming_ = !demuxer_->IsSeekable();
demuxer_->set_host(this);
{