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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: media/blink/buffered_data_source_host_impl.cc
diff --git a/media/blink/buffered_data_source_host_impl.cc b/media/blink/buffered_data_source_host_impl.cc
index 30542adcf37416f2006fd8acb6dbf5eac57d4833..d0cf38e248228c6a9fc3a8fc34296c0674b55f34 100644
--- a/media/blink/buffered_data_source_host_impl.cc
+++ b/media/blink/buffered_data_source_host_impl.cc
@@ -8,9 +8,15 @@
namespace media {
-BufferedDataSourceHostImpl::BufferedDataSourceHostImpl()
+const double kDownloadHistoryWindowSeconds = 10.0;
DaleCurtis 2017/04/06 22:51:39 Add comments detailing how these were chosen.
hubbe 2017/04/07 19:35:51 Done.
+const size_t kDownloadHistoryMaxEntries = 1024;
+const int64_t kDownloadHistoryMinBytesPerEntry = 1000;
+
+BufferedDataSourceHostImpl::BufferedDataSourceHostImpl(
+ const base::Closure& progress_cb)
: total_bytes_(0),
- did_loading_progress_(false) { }
+ did_loading_progress_(false),
+ progress_cb_(progress_cb) {}
BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { }
@@ -18,15 +24,58 @@ void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) {
total_bytes_ = total_bytes;
}
+int64_t BufferedDataSourceHostImpl::UnloadedBytesInInterval(
+ const Interval<int64_t>& interval) const {
+ int64_t bytes = 0;
+ auto i = buffered_byte_ranges_.find(interval.begin);
+ while (i != buffered_byte_ranges_.end()) {
+ if (i.interval_begin() >= interval.end)
+ break;
+ if (!i.value()) {
+ Interval<int64_t> intersection = i.interval().Intersect(interval);
+ if (!intersection.Empty()) {
DaleCurtis 2017/04/06 22:51:39 Drop single line {}
hubbe 2017/04/07 19:35:51 Done.
+ bytes += intersection.end - intersection.begin;
+ }
+ }
+ ++i;
+ }
+ return bytes;
+}
+
void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start,
int64_t end) {
- const auto i = buffered_byte_ranges_.find(start);
- if (i.value() && i.interval_end() >= end) {
+ int64_t new_bytes = UnloadedBytesInInterval(Interval<int64_t>(start, end));
DaleCurtis 2017/04/06 22:51:39 Seems like there might be a simpler calculation si
hubbe 2017/04/07 19:35:50 Seeks cause non-continuous ranges. The removed cod
+ if (new_bytes == 0) {
// No change
return;
}
buffered_byte_ranges_.SetInterval(start, end, 1);
did_loading_progress_ = true;
+
+ base::TimeTicks now = base::TimeTicks::Now();
+ int64_t bytes_so_far = 0;
+ if (!download_history_.empty())
+ bytes_so_far = download_history_.back().second;
+ bytes_so_far += new_bytes;
+
+ // If the difference between the last entry and the second to last entry is
+ // less than kDownloadHistoryMinBytesPerEntry, just overwrite the last entry.
+ if (download_history_.size() > 1 &&
+ download_history_.back().second - (download_history_.end() - 2)->second <
+ kDownloadHistoryMinBytesPerEntry) {
+ download_history_.back() = std::make_pair(now, bytes_so_far);
+ } else {
+ download_history_.push_back(std::make_pair(now, bytes_so_far));
+ }
+ // Drop entries that are too old.
DaleCurtis 2017/04/06 22:51:39 DCHECK_GE(size, 1u) above.
hubbe 2017/04/07 19:35:50 Done.
+ while (download_history_.size() > kDownloadHistoryMaxEntries ||
+ download_history_.back().first - download_history_.front().first >
+ base::TimeDelta::FromSecondsD(kDownloadHistoryWindowSeconds)) {
+ download_history_.pop_front();
+ }
+ if (!progress_cb_.is_null()) {
DaleCurtis 2017/04/06 22:51:39 Drop single line {} Require so you don't have to c
hubbe 2017/04/07 19:35:51 Done.
+ progress_cb_.Run();
+ }
}
static base::TimeDelta TimeForByteOffset(int64_t byte_offset,
@@ -66,4 +115,52 @@ bool BufferedDataSourceHostImpl::DidLoadingProgress() {
return ret;
}
+double BufferedDataSourceHostImpl::DownloadRate() const {
+ if (download_history_.size() < 5)
DaleCurtis 2017/04/06 22:51:39 Comment.
hubbe 2017/04/07 19:35:51 Done.
+ return 0.0;
+
+ // The data we get is bursty, so we get multiple measuring points very close
+ // together. These bursts will often lead us to over-estimate the download
+ // rate. By iterating over the beginning of the time series and picking the
+ // data point that has the lowest download rate, we avoid over-estimating.
+ double download_rate = 1.0E20;
+ for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
+ int64_t downloaded_bytes =
+ download_history_.back().second - download_history_[i].second;
+ double downloaded_seconds =
DaleCurtis 2017/04/06 22:51:39 base::TimeDelta?
hubbe 2017/04/07 19:35:50 Done.
+ (download_history_.back().first - download_history_[i].first)
+ .InSecondsF();
+ if (downloaded_seconds <= 0.0)
+ continue;
+ download_rate =
+ std::min(download_rate, downloaded_bytes / downloaded_seconds);
DaleCurtis 2017/04/06 22:51:39 Then just InSecondsF() here.
hubbe 2017/04/07 19:35:51 Done.
+ }
+ if (download_rate == 1.0E20)
DaleCurtis 2017/04/06 22:51:39 Ternary. Extract value to constant with explanatio
hubbe 2017/04/07 19:35:51 Done.
+ return 0.0;
+ return download_rate;
+}
+
+bool BufferedDataSourceHostImpl::CanPlayThrough(
+ base::TimeDelta current_position,
+ base::TimeDelta media_duration,
+ double playback_rate) const {
+ if (!total_bytes_ || media_duration <= base::TimeDelta())
DaleCurtis 2017/04/06 22:51:39 DCHECK_GE(playback_rate, 0); Also keep in mind me
+ return false;
+ if (current_position > media_duration)
+ return true;
+ double fraction = current_position.InSecondsF() / media_duration.InSecondsF();
+ int64_t byte_pos = total_bytes_ * fraction;
+ if (byte_pos < 0)
+ byte_pos = 0;
+
+ double download_rate = DownloadRate();
+ if (download_rate == 0.0)
DaleCurtis 2017/04/06 22:51:39 Seems a risky test due to precision. <= 0?
hubbe 2017/04/07 19:35:50 Sure. This was just to avoid a division by zero wh
+ return false;
+
+ int64_t unloaded_bytes =
+ UnloadedBytesInInterval(Interval<int64_t>(byte_pos, total_bytes_));
+ return unloaded_bytes / download_rate <
+ (media_duration - current_position).InSecondsF() / playback_rate;
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698