Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 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.
| |
| 12 const size_t kDownloadHistoryMaxEntries = 1024; | |
| 13 const int64_t kDownloadHistoryMinBytesPerEntry = 1000; | |
| 14 | |
| 15 BufferedDataSourceHostImpl::BufferedDataSourceHostImpl( | |
| 16 const base::Closure& progress_cb) | |
| 12 : total_bytes_(0), | 17 : total_bytes_(0), |
| 13 did_loading_progress_(false) { } | 18 did_loading_progress_(false), |
| 19 progress_cb_(progress_cb) {} | |
| 14 | 20 |
| 15 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { } | 21 BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { } |
| 16 | 22 |
| 17 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) { | 23 void BufferedDataSourceHostImpl::SetTotalBytes(int64_t total_bytes) { |
| 18 total_bytes_ = total_bytes; | 24 total_bytes_ = total_bytes; |
| 19 } | 25 } |
| 20 | 26 |
| 27 int64_t BufferedDataSourceHostImpl::UnloadedBytesInInterval( | |
| 28 const Interval<int64_t>& interval) const { | |
| 29 int64_t bytes = 0; | |
| 30 auto i = buffered_byte_ranges_.find(interval.begin); | |
| 31 while (i != buffered_byte_ranges_.end()) { | |
| 32 if (i.interval_begin() >= interval.end) | |
| 33 break; | |
| 34 if (!i.value()) { | |
| 35 Interval<int64_t> intersection = i.interval().Intersect(interval); | |
| 36 if (!intersection.Empty()) { | |
|
DaleCurtis
2017/04/06 22:51:39
Drop single line {}
hubbe
2017/04/07 19:35:51
Done.
| |
| 37 bytes += intersection.end - intersection.begin; | |
| 38 } | |
| 39 } | |
| 40 ++i; | |
| 41 } | |
| 42 return bytes; | |
| 43 } | |
| 44 | |
| 21 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start, | 45 void BufferedDataSourceHostImpl::AddBufferedByteRange(int64_t start, |
| 22 int64_t end) { | 46 int64_t end) { |
| 23 const auto i = buffered_byte_ranges_.find(start); | 47 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
| |
| 24 if (i.value() && i.interval_end() >= end) { | 48 if (new_bytes == 0) { |
| 25 // No change | 49 // No change |
| 26 return; | 50 return; |
| 27 } | 51 } |
| 28 buffered_byte_ranges_.SetInterval(start, end, 1); | 52 buffered_byte_ranges_.SetInterval(start, end, 1); |
| 29 did_loading_progress_ = true; | 53 did_loading_progress_ = true; |
| 54 | |
| 55 base::TimeTicks now = base::TimeTicks::Now(); | |
| 56 int64_t bytes_so_far = 0; | |
| 57 if (!download_history_.empty()) | |
| 58 bytes_so_far = download_history_.back().second; | |
| 59 bytes_so_far += new_bytes; | |
| 60 | |
| 61 // If the difference between the last entry and the second to last entry is | |
| 62 // less than kDownloadHistoryMinBytesPerEntry, just overwrite the last entry. | |
| 63 if (download_history_.size() > 1 && | |
| 64 download_history_.back().second - (download_history_.end() - 2)->second < | |
| 65 kDownloadHistoryMinBytesPerEntry) { | |
| 66 download_history_.back() = std::make_pair(now, bytes_so_far); | |
| 67 } else { | |
| 68 download_history_.push_back(std::make_pair(now, bytes_so_far)); | |
| 69 } | |
| 70 // 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.
| |
| 71 while (download_history_.size() > kDownloadHistoryMaxEntries || | |
| 72 download_history_.back().first - download_history_.front().first > | |
| 73 base::TimeDelta::FromSecondsD(kDownloadHistoryWindowSeconds)) { | |
| 74 download_history_.pop_front(); | |
| 75 } | |
| 76 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.
| |
| 77 progress_cb_.Run(); | |
| 78 } | |
| 30 } | 79 } |
| 31 | 80 |
| 32 static base::TimeDelta TimeForByteOffset(int64_t byte_offset, | 81 static base::TimeDelta TimeForByteOffset(int64_t byte_offset, |
| 33 int64_t total_bytes, | 82 int64_t total_bytes, |
| 34 base::TimeDelta duration) { | 83 base::TimeDelta duration) { |
| 35 double position = static_cast<double>(byte_offset) / total_bytes; | 84 double position = static_cast<double>(byte_offset) / total_bytes; |
| 36 // Snap to the beginning/end where the approximation can look especially bad. | 85 // Snap to the beginning/end where the approximation can look especially bad. |
| 37 if (position < 0.01) | 86 if (position < 0.01) |
| 38 return base::TimeDelta(); | 87 return base::TimeDelta(); |
| 39 if (position > 0.99) | 88 if (position > 0.99) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 59 } | 108 } |
| 60 } | 109 } |
| 61 } | 110 } |
| 62 | 111 |
| 63 bool BufferedDataSourceHostImpl::DidLoadingProgress() { | 112 bool BufferedDataSourceHostImpl::DidLoadingProgress() { |
| 64 bool ret = did_loading_progress_; | 113 bool ret = did_loading_progress_; |
| 65 did_loading_progress_ = false; | 114 did_loading_progress_ = false; |
| 66 return ret; | 115 return ret; |
| 67 } | 116 } |
| 68 | 117 |
| 118 double BufferedDataSourceHostImpl::DownloadRate() const { | |
| 119 if (download_history_.size() < 5) | |
|
DaleCurtis
2017/04/06 22:51:39
Comment.
hubbe
2017/04/07 19:35:51
Done.
| |
| 120 return 0.0; | |
| 121 | |
| 122 // The data we get is bursty, so we get multiple measuring points very close | |
| 123 // together. These bursts will often lead us to over-estimate the download | |
| 124 // rate. By iterating over the beginning of the time series and picking the | |
| 125 // data point that has the lowest download rate, we avoid over-estimating. | |
| 126 double download_rate = 1.0E20; | |
| 127 for (int i = 0; i < std::min<int>(20, download_history_.size() - 3); i++) { | |
| 128 int64_t downloaded_bytes = | |
| 129 download_history_.back().second - download_history_[i].second; | |
| 130 double downloaded_seconds = | |
|
DaleCurtis
2017/04/06 22:51:39
base::TimeDelta?
hubbe
2017/04/07 19:35:50
Done.
| |
| 131 (download_history_.back().first - download_history_[i].first) | |
| 132 .InSecondsF(); | |
| 133 if (downloaded_seconds <= 0.0) | |
| 134 continue; | |
| 135 download_rate = | |
| 136 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.
| |
| 137 } | |
| 138 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.
| |
| 139 return 0.0; | |
| 140 return download_rate; | |
| 141 } | |
| 142 | |
| 143 bool BufferedDataSourceHostImpl::CanPlayThrough( | |
| 144 base::TimeDelta current_position, | |
| 145 base::TimeDelta media_duration, | |
| 146 double playback_rate) const { | |
| 147 if (!total_bytes_ || media_duration <= base::TimeDelta()) | |
|
DaleCurtis
2017/04/06 22:51:39
DCHECK_GE(playback_rate, 0);
Also keep in mind me
| |
| 148 return false; | |
| 149 if (current_position > media_duration) | |
| 150 return true; | |
| 151 double fraction = current_position.InSecondsF() / media_duration.InSecondsF(); | |
| 152 int64_t byte_pos = total_bytes_ * fraction; | |
| 153 if (byte_pos < 0) | |
| 154 byte_pos = 0; | |
| 155 | |
| 156 double download_rate = DownloadRate(); | |
| 157 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
| |
| 158 return false; | |
| 159 | |
| 160 int64_t unloaded_bytes = | |
| 161 UnloadedBytesInInterval(Interval<int64_t>(byte_pos, total_bytes_)); | |
| 162 return unloaded_bytes / download_rate < | |
| 163 (media_duration - current_position).InSecondsF() / playback_rate; | |
| 164 } | |
| 165 | |
| 69 } // namespace media | 166 } // namespace media |
| OLD | NEW |