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

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: refactor Created 5 years, 1 month 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/bind.h"
6 #include "base/callback_helpers.h"
7 #include "base/message_loop/message_loop.h"
8 #include "media/blink/multibuffer_reader.h"
9 #include "net/base/net_errors.h"
10
11 namespace media {
12
13 MultiBufferReader::MultiBufferReader(
14 MultiBuffer* multibuffer,
15 int64_t start,
16 int64_t end,
17 base::Callback<void(int64_t, int64_t)> progress_callback) :
18 multibuffer_(multibuffer),
19 end_(end == -1LL ? (1LL << (multibuffer->block_size_shift() + 30)) : end),
20 preload_high_(0),
21 preload_low_(0),
22 max_buffer_forward_(0),
23 max_buffer_backward_(0),
24 pos_(start),
25 preload_pos_(),
26 loading_(true),
27 current_wait_size_(0),
28 progress_callback_(progress_callback),
29 weak_factory_(this) {
30 DCHECK_GE(start, 0);
31 DCHECK_GE(end_, 0);
32 }
33
34 MultiBufferReader::~MultiBufferReader() {
35 multibuffer_->RemoveReader(preload_pos_, this);
36 multibuffer_->IncrementMaxSize(
37 -block_ceil(max_buffer_forward_ + max_buffer_backward_));
38 multibuffer_->PinRange(block(pos_ - max_buffer_backward_),
39 block_ceil(pos_ + max_buffer_forward_),
40 -1);
41 multibuffer_->CleanupWriters(preload_pos_);
42 }
43
44 MultiBuffer::BlockId MultiBufferReader::block(int64_t byte_pos) const {
45 return byte_pos >> multibuffer_->block_size_shift();
46 }
47
48 MultiBuffer::BlockId MultiBufferReader::block_ceil(int64_t byte_pos) const {
49 return block(byte_pos + (1LL << multibuffer_->block_size_shift()) - 1);
50 }
51
52 void MultiBufferReader::Seek(int64_t pos) {
53 DCHECK_GE(pos, 0);
54 if (pos == pos_)
55 return;
56 // Use a rangemap to compute the diff in pinning.
57 RangeMap<MultiBuffer::BlockId, int32_t> tmp;
58 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
59 block_ceil(pos_ + max_buffer_forward_),
60 -1);
61 tmp.IncrementRange(block(pos - max_buffer_backward_),
62 block_ceil(pos + max_buffer_forward_),
63 1);
64
65 multibuffer_->PinRanges(tmp);
66
67 multibuffer_->RemoveReader(preload_pos_, this);
68 MultiBufferBlockId old_preload_pos = preload_pos_;
69 preload_pos_ = block(pos);
70 pos_ = pos;
71 IncrementPreloadPos();
72 multibuffer_->CleanupWriters(old_preload_pos);
73 }
74
75 void MultiBufferReader::SetMaxBuffer(int64_t backward, int64_t forward) {
76 // Safe, because we know this doesn't actually prune the cache right away.
77 multibuffer_->IncrementMaxSize(
78 -block_ceil(max_buffer_forward_ + max_buffer_backward_));
79 // Use a rangemap to compute the diff in pinning.
80 RangeMap<MultiBuffer::BlockId, int32_t> tmp;
81 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
82 block_ceil(pos_ + max_buffer_forward_),
83 -1);
84 max_buffer_backward_ = backward;
85 max_buffer_forward_ = forward;
86 tmp.IncrementRange(block(pos_ - max_buffer_backward_),
87 block_ceil(pos_ + max_buffer_forward_),
88 1);
89 multibuffer_->PinRanges(tmp);
90
91 multibuffer_->IncrementMaxSize(
92 block_ceil(max_buffer_forward_ + max_buffer_backward_));
93 }
94
95
96 int64_t MultiBufferReader::Available() const {
97 MultiBufferBlockId current_block = block(pos_);
98 int64_t unavailable_byte_pos =
99 static_cast<int64_t>(
100 multibuffer_->FindNextUnavailable(block(pos_))) <<
101 multibuffer_->block_size_shift();
102 return std::max<int64_t>(0, unavailable_byte_pos - pos_);
103 }
104
105 int64_t MultiBufferReader::TryRead(unsigned char *data, int64_t len) {
106 DCHECK_GT(len, 0);
107 current_wait_size_ = 0;
108 cb_ = base::Closure();
109 DCHECK_LE(pos_ + len, end_);
110 const MultiBuffer::DataMap& data_map = multibuffer_->map();
111 MultiBuffer::DataMap::const_iterator i = data_map.find(block(pos_));
112 int64_t p = pos_;
113 int64_t bytes_read = 0;
114 while (bytes_read < len) {
115 if (i == data_map.end()) break;
116 if (i->first != block(p)) break;
117 if (i->second->end_of_stream()) break;
118 size_t offset = p & ((1LL << multibuffer_->block_size_shift()) - 1);
119 size_t tocopy = std::min<size_t>(len - bytes_read,
120 i->second->data_size() - offset);
121 memcpy(data, i->second->data() + offset, tocopy);
122 data += tocopy;
123 bytes_read += tocopy;
124 p += tocopy;
125 ++i;
126 }
127 Seek(p);
128 return bytes_read;
129 }
130
131 int MultiBufferReader::Wait(int64_t len, base::Closure cb) {
132 DCHECK_LE(pos_ + len, end_);
133 DCHECK_NE(Available(), -1);
134 DCHECK_LE(len, max_buffer_forward_);
135 current_wait_size_ = len;
136
137 cb_= base::Closure();
DaleCurtis 2015/10/28 23:06:13 Why? cb_.Reset() ?
hubbe 2015/10/29 17:52:44 Done. (Also fixed in TryRead())
138 IncrementPreloadPos();
139
140 if (Available() >= current_wait_size_) {
141 return net::OK;
142 } else {
143 cb_ = cb;
144 return net::ERR_IO_PENDING;
145 }
146 }
147
148 void MultiBufferReader::SetPreload(int64_t preload_high, int64_t preload_low) {
149 multibuffer_->RemoveReader(preload_pos_, this);
150 preload_pos_ = block(pos_);
151 preload_high_ = preload_high;
152 preload_low_ = preload_low;
153 IncrementPreloadPos();
154 }
155
156 bool MultiBufferReader::IsLoading() const {
157 return loading_;
158 }
159
160 void MultiBufferReader::CheckWait() {
161 if (!cb_.is_null() && (Available() >= current_wait_size_ ||
162 Available() == -1)) {
163 base::MessageLoop::current()->PostTask(
164 FROM_HERE,
165 base::Bind(&MultiBufferReader::Call, weak_factory_.GetWeakPtr(),
166 base::ResetAndReturn(&cb_)));
167 }
168 }
169
170 void MultiBufferReader::Call(const base::Closure& cb) const {
DaleCurtis 2015/10/28 23:06:13 Should be a way to avoid this by making cb_ a Canc
hubbe 2015/10/29 17:52:44 That doesn't seem like it would be better. Unless
DaleCurtis 2015/10/29 17:59:05 It'll auto cancel when the member variable goes ou
hubbe 2015/10/29 21:45:06 Interesting, but I'm still not convinced it's bett
171 cb.Run();
172 }
173
174 void MultiBufferReader::NotifyAvailableRange(
175 const Range<MultiBufferBlockId>& range) {
176 // Update end_ if we can.
177 if (range.end > range.begin) {
178 auto i = multibuffer_->map().find(range.end - 1);
179 DCHECK(i != multibuffer_->map().end());
180 if (i->second->end_of_stream()) {
181 // This is an upper limit because the last-to-one block is allowed
182 // to be smaller than the rest of the blocks.
183 int64_t size_upper_limit =
184 static_cast<int64_t>(range.end) << multibuffer_->block_size_shift();
185 end_ = std::min(end_, size_upper_limit);
186 }
187 }
188 IncrementPreloadPos();
189 if (!progress_callback_.is_null()) {
190 progress_callback_.Run(static_cast<int64_t>(range.begin) <<
191 multibuffer_->block_size_shift(),
192 static_cast<int64_t>(range.end) <<
193 multibuffer_->block_size_shift());
194 // We may be destroyed, do not touch |this|.
195 }
196 }
197
198 void MultiBufferReader::IncrementPreloadPos() {
199 int64_t effective_preload = loading_ ? preload_high_ : preload_low_;
200
201 loading_ = false;
202 if (preload_pos_ == MultiBuffer::BlockId()) {
203 preload_pos_ = block(pos_);
204 DCHECK_GE(preload_pos_, 0);
205 }
206 MultiBuffer::BlockId max_preload = block_ceil(
207 std::min(end_, pos_ + std::max(effective_preload, current_wait_size_)));
208
209 multibuffer_->RemoveReader(preload_pos_, this);
210
211 preload_pos_ = multibuffer_->FindNextUnavailable(preload_pos_);
212 DCHECK_GE(preload_pos_, 0);
213
214 DVLOG(3) << "IncrementPreloadPos"
215 << " pp = " << preload_pos_
216 << " block_ceil(end_) = " << block_ceil(end_)
217 << " end_ = " << end_
218 << " max_preload " << max_preload;
219
220 if (preload_pos_ < block_ceil(end_)) {
221 if (preload_pos_ < max_preload) {
222 loading_ = true;
223 multibuffer_->AddReader(preload_pos_, this);
224 } else if (multibuffer_->Contains(preload_pos_ - 1)) {
225 --preload_pos_;
226 multibuffer_->AddReader(preload_pos_, this);
227 }
228 }
229 CheckWait();
230 }
231
232 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698