Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: media/blink/buffered_data_source_host_impl.cc

Issue 2796193002: fix canplaythrough (Closed)
Patch Set: comments addressed Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/buffered_data_source_host_impl.h" 5 #include "media/blink/buffered_data_source_host_impl.h"
6 6
7 #include "media/base/timestamp_constants.h" 7 #include "media/base/timestamp_constants.h"
8 8
9 namespace media { 9 namespace media {
10 10
11 BufferedDataSourceHostImpl::BufferedDataSourceHostImpl() 11 // We want a relatively small window for estimating bandwidth,
12 // that way we don't need to worry too much about seeks and pause
13 // throwing off the estimates.
14 const double kDownloadHistoryWindowSeconds = 10.0;
15
16 // Limit the number of entries in the rate estimator queue.
17 // 1024 entries should be more than enough.
18 const size_t kDownloadHistoryMaxEntries = 1024;
19
20 // Just in case someone gives progress one byte at a time,
21 // let's aggregate progress updates together until we reach
22 // at least this many bytes.
23 const int64_t kDownloadHistoryMinBytesPerEntry = 1000;
24
25 BufferedDataSourceHostImpl::BufferedDataSourceHostImpl(
26 const base::Closure& progress_cb)
12 : total_bytes_(0), 27 : total_bytes_(0),
13 did_loading_progress_(false) { } 28 did_loading_progress_(false),
29 progress_cb_(progress_cb) {}
14 30
15 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { } 31 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { }
16 32
17 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) { 33 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) {
18 total_bytes_ = total_bytes; 34 total_bytes_ = total_bytes;
19 } 35 }
20 36
37 int64_t BufferedDataSourceHostImpl::UnloadedBytesInInterval(
38 const Interval<int64_t>& interval) const {
39 int64_t bytes = 0;
40 auto i = buffered_byte_ranges_.find(interval.begin);
41 while (i != buffered_byte_ranges_.end()) {
42 if (i.interval_begin() >= interval.end)
43 break;
44 if (!i.value()) {
45 Interval<int64_t> intersection = i.interval().Intersect(interval);
46 if (!intersection.Empty())
47 bytes += intersection.end - intersection.begin;
48 }
49 ++i;
50 }
51 return bytes;
52 }
53
21 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start, 54 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start,
22 int64_t end) { 55 int64_t end) {
23 const auto i = buffered_byte_ranges_.find(start); 56 int64_t new_bytes = UnloadedBytesInInterval(Interval<int64_t>(start, end));
24 if (i.value() && i.interval_end() >= end) { 57 if (new_bytes == 0) {
25 // No change 58 // No change
26 return; 59 return;
27 } 60 }
28 buffered_byte_ranges_.SetInterval(start, end, 1); 61 buffered_byte_ranges_.SetInterval(start, end, 1);
29 did_loading_progress_ = true; 62 did_loading_progress_ = true;
63
64 base::TimeTicks now = base::TimeTicks::Now();
65 int64_t bytes_so_far = 0;
66 if (!download_history_.empty())
67 bytes_so_far = download_history_.back().second;
68 bytes_so_far += new_bytes;
69
70 // If the difference between the last entry and the second to last entry is
71 // less than kDownloadHistoryMinBytesPerEntry, just overwrite the last entry.
72 if (download_history_.size() > 1 &&
73 download_history_.back().second - (download_history_.end() - 2)->second <
74 kDownloadHistoryMinBytesPerEntry) {
75 download_history_.back() = std::make_pair(now, bytes_so_far);
76 } else {
77 download_history_.push_back(std::make_pair(now, bytes_so_far));
78 }
79 DCHECK_GE(download_history_.size(), 1u);
80 // Drop entries that are too old.
81 while (download_history_.size() > kDownloadHistoryMaxEntries ||
82 download_history_.back().first - download_history_.front().first >
83 base::TimeDelta::FromSecondsD(kDownloadHistoryWindowSeconds)) {
84 download_history_.pop_front();
85 }
86 progress_cb_.Run();
30 } 87 }
31 88
32 static base::TimeDelta TimeForByteOffset(int64_t byte_offset, 89 static base::TimeDelta TimeForByteOffset(int64_t byte_offset,
33 int64_t total_bytes, 90 int64_t total_bytes,
34 base::TimeDelta duration) { 91 base::TimeDelta duration) {
35 double position = static_cast<double>(byte_offset) / total_bytes; 92 double position = static_cast<double>(byte_offset) / total_bytes;
36 // Snap to the beginning/end where the approximation can look especially bad. 93 // Snap to the beginning/end where the approximation can look especially bad.
37 if (position < 0.01) 94 if (position < 0.01)
38 return base::TimeDelta(); 95 return base::TimeDelta();
39 if (position > 0.99) 96 if (position > 0.99)
(...skipping 19 matching lines...) Expand all
59 } 116 }
60 } 117 }
61 } 118 }
62 119
63 bool BufferedDataSourceHostImpl::DidLoadingProgress() { 120 bool BufferedDataSourceHostImpl::DidLoadingProgress() {
64 bool ret = did_loading_progress_; 121 bool ret = did_loading_progress_;
65 did_loading_progress_ = false; 122 did_loading_progress_ = false;
66 return ret; 123 return ret;
67 } 124 }
68 125
126 double BufferedDataSourceHostImpl::DownloadRate() const {
127 // If the download history is really small, any estimate we make is going to
128 // be wildly inaccurate, so let's not make any estimates until we have more
129 // data.
130 if (download_history_.size() < 5)
131 return 0.0;
132
133 // The data we get is bursty, so we get multiple measuring points very close
134 // together. These bursts will often lead us to over-estimate the download
135 // rate. By iterating over the beginning of the time series and picking the
136 // data point that has the lowest download rate, we avoid over-estimating.
137 const double kVeryLargeRate = 1.0E20;
138 double download_rate = kVeryLargeRate;
139 for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
chcunningham 2017/04/08 00:52:46 I follow the 20 and the 3 now, but it might help t
140 int64_t downloaded_bytes =
141 download_history_.back().second - download_history_[i].second;
142 base::TimeDelta downloaded_seconds =
143 download_history_.back().first - download_history_[i].first;
144 if (downloaded_seconds <= base::TimeDelta())
145 continue;
146 download_rate = std::min(
147 download_rate, downloaded_bytes / downloaded_seconds.InSecondsF());
148 }
149 return download_rate == kVeryLargeRate ? 0.0 : download_rate;
150 }
151
152 bool BufferedDataSourceHostImpl::CanPlayThrough(
153 base::TimeDelta current_position,
154 base::TimeDelta media_duration,
155 double playback_rate) const {
156 DCHECK_GE(playback_rate, 0);
157 if (!total_bytes_ || media_duration <= base::TimeDelta() ||
158 media_duration == kInfiniteDuration)
159 return false;
160 if (current_position > media_duration)
161 return true;
162 double fraction = current_position.InSecondsF() / media_duration.InSecondsF();
163 int64_t byte_pos = total_bytes_ * fraction;
164 if (byte_pos < 0)
165 byte_pos = 0;
166
167 double download_rate = DownloadRate();
168 if (download_rate <= 0.0)
169 return false;
170
171 int64_t unloaded_bytes =
172 UnloadedBytesInInterval(Interval<int64_t>(byte_pos, total_bytes_));
173 return unloaded_bytes / download_rate <
174 (media_duration - current_position).InSecondsF() / playback_rate;
175 }
176
69 } // namespace media 177 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/buffered_data_source_host_impl.h ('k') | media/blink/buffered_data_source_host_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698