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

Unified Diff: media/blink/buffered_data_source_host_impl.cc

Issue 2796193002: fix canplaythrough (Closed)
Patch Set: test compile fix 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..9faa99a390a132c2634627092fd139084926de27 100644
--- a/media/blink/buffered_data_source_host_impl.cc
+++ b/media/blink/buffered_data_source_host_impl.cc
@@ -8,9 +8,14 @@
namespace media {
-BufferedDataSourceHostImpl::BufferedDataSourceHostImpl()
+const double kDownloadHistoryWindowSeconds = 10.0;
+const size_t kDownloadHistoryMaxEntries = 1024;
+
+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 +23,52 @@ 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()) {
+ 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));
+ 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 (download_history_.size() >= kDownloadHistoryMaxEntries) {
+ download_history_.back() = std::make_pair(now, bytes_so_far);
chcunningham 2017/04/06 16:55:41 why not always push_back? iiuc this is overwriting
hubbe 2017/04/06 21:25:38 We don't loose any data, we just loose precision i
+ } else {
+ download_history_.push_back(std::make_pair(now, bytes_so_far));
+ }
+ while (download_history_.back().first - download_history_.front().first >
+ base::TimeDelta::FromSecondsD(kDownloadHistoryWindowSeconds) ||
+ download_history_.size() >= kDownloadHistoryMaxEntries) {
+ download_history_.pop_front();
+ }
+ if (!progress_cb_.is_null()) {
+ progress_cb_.Run();
+ }
}
static base::TimeDelta TimeForByteOffset(int64_t byte_offset,
@@ -66,4 +108,52 @@ bool BufferedDataSourceHostImpl::DidLoadingProgress() {
return ret;
}
+double BufferedDataSourceHostImpl::DownloadRate() const {
+ if (download_history_.size() < 5)
+ 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;
mlamouri (slow - plz ping) 2017/04/06 11:32:56 Why 1e20 and not a negative value instead?
hubbe 2017/04/06 21:25:38 Because I use std::min() below.
mlamouri (slow - plz ping) 2017/04/07 11:23:44 Missed that. Can you use INT_MAX? `std::numeric_li
+ for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) {
chcunningham 2017/04/06 16:55:41 I don't follow the min(20, ...). If you only want
hubbe 2017/04/06 21:25:38 Each entry contains the cumulative downloaded byte
+ int64_t downloaded_bytes =
+ download_history_.back().second - download_history_[i].second;
+ double downloaded_seconds =
+ (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);
+ }
+ if (download_rate == 1.0E20)
+ 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())
+ 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)
+ 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