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

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

Issue 2796193002: fix canplaythrough (Closed)
Patch Set: merged Created 3 years, 7 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 constexpr base::TimeDelta kDownloadHistoryWindowSeconds =
15 base::TimeDelta::FromSecondsD(10.0);
16
17 // Limit the number of entries in the rate estimator queue.
18 // 1024 entries should be more than enough.
19 constexpr size_t kDownloadHistoryMaxEntries = 1024;
20
21 // Just in case someone gives progress one byte at a time,
22 // let's aggregate progress updates together until we reach
23 // at least this many bytes.
24 constexpr int64_t kDownloadHistoryMinBytesPerEntry = 1000;
25
26 BufferedDataSourceHostImpl::BufferedDataSourceHostImpl(
27 base::Closure&& progress_cb,
28 base::TickClock* tick_clock)
12 : total_bytes_(0), 29 : total_bytes_(0),
13 did_loading_progress_(false) { } 30 did_loading_progress_(false),
31 progress_cb_(std::move(progress_cb)),
32 tick_clock_(tick_clock) {}
14 33
15 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { } 34 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { }
16 35
17 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) { 36 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) {
18 total_bytes_ = total_bytes; 37 total_bytes_ = total_bytes;
19 } 38 }
20 39
40 int64_t BufferedDataSourceHostImpl::UnloadedBytesInInterval(
41 const Interval<int64_t>& interval) const {
42 int64_t bytes = 0;
43 auto i = buffered_byte_ranges_.find(interval.begin);
44 while (i != buffered_byte_ranges_.end()) {
45 if (i.interval_begin() >= interval.end)
46 break;
47 if (!i.value()) {
48 Interval<int64_t> intersection = i.interval().Intersect(interval);
49 if (!intersection.Empty())
50 bytes += intersection.end - intersection.begin;
51 }
52 ++i;
53 }
54 return bytes;
55 }
56
21 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start, 57 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start,
22 int64_t end) { 58 int64_t end) {
23 const auto i = buffered_byte_ranges_.find(start); 59 int64_t new_bytes = UnloadedBytesInInterval(Interval<int64_t>(start, end));
24 if (i.value() && i.interval_end() >= end) { 60 if (new_bytes == 0) {
25 // No change 61 // No change
26 return; 62 return;
27 } 63 }
28 buffered_byte_ranges_.SetInterval(start, end, 1); 64 buffered_byte_ranges_.SetInterval(start, end, 1);
29 did_loading_progress_ = true; 65 did_loading_progress_ = true;
66
67 base::TimeTicks now = tick_clock_->NowTicks();
68 int64_t bytes_so_far = 0;
69 if (!download_history_.empty())
70 bytes_so_far = download_history_.back().second;
71 bytes_so_far += new_bytes;
72
73 // If the difference between the last entry and the second to last entry is
DaleCurtis 2017/05/01 19:05:52 Do your tests hit both of these paths?
hubbe 2017/05/01 21:26:10 Does now.
74 // less than kDownloadHistoryMinBytesPerEntry, just overwrite the last entry.
75 if (download_history_.size() > 1 &&
76 download_history_.back().second - (download_history_.end() - 2)->second <
77 kDownloadHistoryMinBytesPerEntry) {
78 download_history_.back() = std::make_pair(now, bytes_so_far);
79 } else {
80 download_history_.push_back(std::make_pair(now, bytes_so_far));
DaleCurtis 2017/05/01 19:05:52 emplace_back?
hubbe 2017/05/01 21:26:10 Done.
81 }
82 DCHECK_GE(download_history_.size(), 1u);
83 // Drop entries that are too old.
84 while (download_history_.size() > kDownloadHistoryMaxEntries ||
85 download_history_.back().first - download_history_.front().first >
86 kDownloadHistoryWindowSeconds) {
87 download_history_.pop_front();
88 }
89 progress_cb_.Run();
30 } 90 }
31 91
32 static base::TimeDelta TimeForByteOffset(int64_t byte_offset, 92 static base::TimeDelta TimeForByteOffset(int64_t byte_offset,
33 int64_t total_bytes, 93 int64_t total_bytes,
34 base::TimeDelta duration) { 94 base::TimeDelta duration) {
35 double position = static_cast<double>(byte_offset) / total_bytes; 95 double position = static_cast<double>(byte_offset) / total_bytes;
36 // Snap to the beginning/end where the approximation can look especially bad. 96 // Snap to the beginning/end where the approximation can look especially bad.
37 if (position < 0.01) 97 if (position < 0.01)
38 return base::TimeDelta(); 98 return base::TimeDelta();
39 if (position > 0.99) 99 if (position > 0.99)
(...skipping 19 matching lines...) Expand all
59 } 119 }
60 } 120 }
61 } 121 }
62 122
63 bool BufferedDataSourceHostImpl::DidLoadingProgress() { 123 bool BufferedDataSourceHostImpl::DidLoadingProgress() {
64 bool ret = did_loading_progress_; 124 bool ret = did_loading_progress_;
65 did_loading_progress_ = false; 125 did_loading_progress_ = false;
66 return ret; 126 return ret;
67 } 127 }
68 128
129 double BufferedDataSourceHostImpl::DownloadRate() const {
130 // If the download history is really small, any estimate we make is going to
131 // be wildly inaccurate, so let's not make any estimates until we have more
132 // data.
133 if (download_history_.size() < 5)
134 return 0.0;
135
136 // The data we get is bursty, so we get multiple measuring points very close
137 // together. These bursts will often lead us to over-estimate the download
138 // rate. By iterating over the beginning of the time series and picking the
139 // data point that has the lowest download rate, we avoid over-estimating.
140 const double kVeryLargeRate = 1.0E20;
141 double download_rate = kVeryLargeRate;
142 for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
143 int64_t downloaded_bytes =
144 download_history_.back().second - download_history_[i].second;
145 base::TimeTicks now = tick_clock_->NowTicks();
146 base::TimeDelta downloaded_seconds = now - download_history_[i].first;
147 if (downloaded_seconds <= base::TimeDelta())
148 continue;
149 download_rate = std::min(
150 download_rate, downloaded_bytes / downloaded_seconds.InSecondsF());
151 }
152 return download_rate == kVeryLargeRate ? 0.0 : download_rate;
153 }
154
155 bool BufferedDataSourceHostImpl::CanPlayThrough(
156 base::TimeDelta current_position,
157 base::TimeDelta media_duration,
158 double playback_rate) const {
159 DCHECK_GE(playback_rate, 0);
160 if (!total_bytes_ || media_duration <= base::TimeDelta() ||
DaleCurtis 2017/05/01 19:05:52 needs {} for multiline if.
hubbe 2017/05/01 21:26:10 Done.
161 media_duration == kInfiniteDuration)
162 return false;
163 if (current_position > media_duration)
164 return true;
165 double fraction = current_position.InSecondsF() / media_duration.InSecondsF();
166 int64_t byte_pos = total_bytes_ * fraction;
167 if (byte_pos < 0)
168 byte_pos = 0;
169
170 int64_t unloaded_bytes =
171 UnloadedBytesInInterval(Interval<int64_t>(byte_pos, total_bytes_));
172
173 if (unloaded_bytes == 0)
174 return true;
175
176 double download_rate = DownloadRate();
177 if (download_rate <= 0.0)
178 return false;
179
180 return unloaded_bytes / download_rate <
181 (media_duration - current_position).InSecondsF() / playback_rate;
182 }
183
184 void BufferedDataSourceHostImpl::SetTickClockForTest(
185 base::TickClock* tick_clock) {
186 tick_clock_ = tick_clock;
187 }
188
69 } // namespace media 189 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698