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

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

Issue 1165903002: Multi reader/writer cache/buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more tests, comments adressed, minor refactoring + a little code cleanup Created 5 years, 2 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
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/callback_helpers.h"
6 #include "media/blink/multibuffer_reader.h"
7 #include "net/base/net_errors.h"
8
9 namespace media {
10
11 MultiBufferReader::MultiBufferReader(
12 MultiBuffer* multibuffer,
13 MultiBufferUrlData url_data,
14 int64_t start,
15 int64_t end,
16 base::Callback<void(int64_t, int64_t)> progress_callback) :
17 multibuffer_(multibuffer),
18 url_data_(url_data),
19 end_(end == -1LL ? (1LL << (multibuffer->block_size_shift() + 30)) : end),
20 preload_high_(0),
21 preload_low_(),
liberato (no reviews please) 2015/10/14 14:51:34 (0)?
hubbe 2015/10/16 00:17:43 Done.
22 preload_pos_(),
23 loading_(true),
24 max_buffer_forward_(0),
25 max_buffer_backward_(0),
26 pos_(start),
27 progress_callback_(progress_callback),
28 current_wait_size_(0),
29 clear_on_delete_(nullptr) {
30 DCHECK_GE(start, 0);
31 DCHECK_GE(end_, 0);
32 }
33
34 MultiBufferReader::~MultiBufferReader() {
35 if (clear_on_delete_) *clear_on_delete_ = false;
36 multibuffer_->RemoveReader(preload_pos_, this);
37 multibuffer_->IncrementMaxSize(
38 -block_ceil(max_buffer_forward_ + max_buffer_backward_).block_num());
39 multibuffer_->PinRange(block(pos_ - max_buffer_backward_),
40 block_ceil(pos_ + max_buffer_forward_),
41 -1);
42 multibuffer_->CleanupWriters(preload_pos_);
43 }
44
45 MultiBuffer::BlockId MultiBufferReader::block(int64_t byte_pos) const {
46 return MultiBufferBlockId(
47 url_data_,
48 byte_pos >> multibuffer_->block_size_shift());
49 }
50
51 MultiBuffer::BlockId MultiBufferReader::block_ceil(int64_t byte_pos) const {
52 return block(byte_pos + (1LL << multibuffer_->block_size_shift()) - 1);
53 }
54
55 void MultiBufferReader::Seek(int64_t pos) {
56 DCHECK_GE(pos, 0);
57 // Use a rangemap to compute the diff in pinning.
58 RangeMap<MultiBuffer::BlockId, int32_t> tmp;
59 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
60 block_ceil(pos_ + max_buffer_forward_),
61 -1);
62 tmp.IncrementRange(block(pos - max_buffer_backward_),
63 block_ceil(pos + max_buffer_forward_),
64 1);
65
66 multibuffer_->PinRanges(tmp);
67
68 multibuffer_->RemoveReader(preload_pos_, this);
69 MultiBufferBlockId old_preload_pos = preload_pos_;
70 preload_pos_ = block(pos);
71 pos_ = pos;
72 if (IncrementPreloadPos()) {
73 multibuffer_->CleanupWriters(old_preload_pos);
74 }
75 }
76
77 void MultiBufferReader::SetMaxBuffer(int64_t backward, int64_t forward) {
78 // Safe, because we know this doesn't actually prune the cache right away.
79 multibuffer_->IncrementMaxSize(
80 -block_ceil(max_buffer_forward_ + max_buffer_backward_).block_num());
81 // Use a rangemap to compute the diff in pinning.
82 RangeMap<MultiBuffer::BlockId, int32_t> tmp;
83 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
84 block_ceil(pos_ + max_buffer_forward_),
85 -1);
86 max_buffer_backward_ = backward;
87 max_buffer_forward_ = forward;
88 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
89 block_ceil(pos_ + max_buffer_forward_),
90 1);
91 multibuffer_->PinRanges(tmp);
92
93 multibuffer_->IncrementMaxSize(
94 block_ceil(max_buffer_forward_ + max_buffer_backward_).block_num());
95 }
96
97
98 int64_t MultiBufferReader::Available() const {
99 if (url_data_ == kUnknownUrlData)
100 return -1;
101
102 MultiBufferBlockId current_block = block(pos_);
103 int64_t unavailable_byte_pos =
104 static_cast<int64_t>(
105 multibuffer_->FindNextUnavailable(block(pos_)).block_num()) <<
106 multibuffer_->block_size_shift();
107 return std::max<int64_t>(0, unavailable_byte_pos - pos_);
108 }
109
110 int64_t MultiBufferReader::TryRead(unsigned char *data, int64_t len) {
111 DCHECK_GT(len, 0);
112 current_wait_size_ = 0;
113 cb_ = base::Closure();
114 DCHECK_LE(pos_ + len, end_);
115 const MultiBuffer::DataMap& data_map = multibuffer_->map();
116 MultiBuffer::DataMap::const_iterator i = data_map.find(block(pos_));
117 int64_t p = pos_;
118 int64_t bytes_read = 0;
119 while (bytes_read < len) {
120 if (i == data_map.end()) break;
121 if (i->first != block(p)) break;
122 if (i->second->end_of_stream()) break;
123 size_t offset = p & ((1LL << multibuffer_->block_size_shift()) - 1);
124 size_t tocopy = std::min<size_t>(len - bytes_read,
125 i->second->data_size() - offset);
126 memcpy(data, i->second->data() + offset, tocopy);
127 data += tocopy;
128 bytes_read += tocopy;
129 p += tocopy;
130 ++i;
131 }
132 Seek(p);
133 return bytes_read;
134 }
135
136 int MultiBufferReader::Wait(int64_t len, base::Closure cb) {
137 DCHECK_LE(pos_ + len, end_);
138 DCHECK_NE(Available(), -1);
139 DCHECK_LE(len, max_buffer_forward_);
140 current_wait_size_ = len;
141 IncrementPreloadPos();
liberato (no reviews please) 2015/10/14 14:51:34 check return?
hubbe 2015/10/16 00:17:43 Done.
142 if (Available() >= current_wait_size_) {
143 return net::OK;
144 } else {
145 cb_ = cb;
146 return net::ERR_IO_PENDING;
147 }
148 }
149
150 void MultiBufferReader::UpdateUrlData(const MultiBufferUrlData& old_url_data,
151 const MultiBufferUrlData& new_url_data) {
152 DCHECK_EQ(old_url_data, url_data_);
153 multibuffer_->RemoveReader(preload_pos_, this);
154 multibuffer_->PinRange(block(pos_ - max_buffer_backward_),
155 block_ceil(pos_ + max_buffer_forward_),
156 1);
157 url_data_ = new_url_data;
158 if (url_data_ != kUnknownUrlData)
159 multibuffer_->PinRange(block(pos_ - max_buffer_backward_),
160 block_ceil(pos_ + max_buffer_forward_),
161 1);
162
163 MultiBufferBlockId old_preload_pos = preload_pos_;
164 multibuffer_->CleanupWriters(old_preload_pos);
165
166 preload_pos_ = block(pos_);
167 if (IncrementPreloadPos()) {
168 if (!progress_callback_.is_null()) {
169 MultiBuffer::BlockId unavailable_pos =
170 multibuffer_->FindNextUnavailable(preload_pos_);
171 progress_callback_.Run(
172 pos_,
173 static_cast<int64_t>(unavailable_pos.block_num()) <<
174 multibuffer_->block_size_shift());
175 }
176 }
177 }
178
179 void MultiBufferReader::SetPreload(int64_t preload_high, int64_t preload_low) {
180 multibuffer_->RemoveReader(preload_pos_, this);
181 preload_pos_ = block(pos_);
182 preload_high_ = preload_high;
183 preload_low_ = preload_low;
184 IncrementPreloadPos();
185 }
186
187 bool MultiBufferReader::IsLoading() const {
188 return loading_;
189 }
190
191 bool MultiBufferReader::CheckWait() {
192 if (!cb_.is_null() && (Available() >= current_wait_size_ ||
193 Available() == -1)) {
194 current_wait_size_ = 0;
195 bool still_alive = true;
196 clear_on_delete_ = &still_alive;
197 base::ResetAndReturn(&cb_).Run();
198 if (still_alive) {
199 clear_on_delete_ = NULL;
200 } else {
201 return false;
liberato (no reviews please) 2015/10/14 14:51:34 super nitpicky: "return false else fall through to
hubbe 2015/10/16 00:17:43 Done.
202 }
203 }
204 return true;
205 }
206
207 void MultiBufferReader::NotifyAvailableRange(
208 const Range<MultiBufferBlockId>& range) {
209 // Update end_ if we can.
210 if (range.end > range.begin) {
211 auto i = multibuffer_->map().find(range.end - 1);
212 DCHECK(i != multibuffer_->map().end());
213 if (i->second->end_of_stream()) {
214 // This is an upper limit because the last-to-one block is allowed
215 // to be smaller than the rest of the blocks.
216 int64_t size_upper_limit =
217 static_cast<int64_t>(range.end.block_num()) <<
218 multibuffer_->block_size_shift();
219 end_ = std::min(end_, size_upper_limit);
220 }
221 }
222 if (IncrementPreloadPos()) {
223 if (!progress_callback_.is_null()) {
224 progress_callback_.Run(static_cast<int64_t>(range.begin.block_num()) <<
225 multibuffer_->block_size_shift(),
226 static_cast<int64_t>(range.end.block_num()) <<
227 multibuffer_->block_size_shift());
228 }
229 }
230 }
231
232 bool MultiBufferReader::IncrementPreloadPos() {
233 int64_t effective_preload = loading_ ? preload_high_ : preload_low_;
234
235 loading_ = false;
236 if (url_data_ != kUnknownUrlData) {
237 if (preload_pos_ == MultiBuffer::BlockId()) {
238 preload_pos_ = block(pos_);
239 DCHECK_GE(preload_pos_.block_num(), 0);
240 }
241 MultiBuffer::BlockId max_preload = block_ceil(
242 std::min(end_, pos_ + std::max(effective_preload, current_wait_size_)));
243
244 multibuffer_->RemoveReader(preload_pos_, this);
245
246 preload_pos_ = multibuffer_->FindNextUnavailable(preload_pos_);
247 DCHECK_GE(preload_pos_.block_num(), 0);
248
249 DVLOG(3) << "IncrementPreloadPos"
250 << " pp = " << preload_pos_
251 << " block_ceil(end_) = " << block_ceil(end_)
252 << " end_ = " << end_
253 << " max_preload " << max_preload;
254
255 if (preload_pos_ < block_ceil(end_)) {
256 if (preload_pos_ < max_preload) {
257 loading_ = true;
258 multibuffer_->AddReader(preload_pos_, this);
259 } else if (multibuffer_->Contains(preload_pos_ - 1)) {
260 --preload_pos_;
261 multibuffer_->AddReader(preload_pos_, this);
262 }
263 }
264 }
265 return CheckWait();
266 }
267
268 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698