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

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

Issue 1399603003: Tie multibuffers to URLs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_cache
Patch Set: formatted Created 5 years 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
« no previous file with comments | « media/blink/multibuffer.h ('k') | media/blink/multibuffer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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 <utility>
6
5 #include "media/blink/multibuffer.h" 7 #include "media/blink/multibuffer.h"
6 8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 10
9 namespace media { 11 namespace media {
10 12
11 // Returns the block ID closest to (but less or equal than) |pos| from |index|. 13 // Returns the block ID closest to (but less or equal than) |pos| from |index|.
12 template <class T> 14 template <class T>
13 static MultiBuffer::BlockId ClosestPreviousEntry( 15 static MultiBuffer::BlockId ClosestPreviousEntry(
14 const std::map<MultiBuffer::BlockId, T>& index, 16 const std::map<MultiBuffer::BlockId, T>& index,
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 108 }
107 109
108 // 110 //
109 // MultiBuffer 111 // MultiBuffer
110 // 112 //
111 MultiBuffer::MultiBuffer(int32_t block_size_shift, 113 MultiBuffer::MultiBuffer(int32_t block_size_shift,
112 const scoped_refptr<GlobalLRU>& global_lru) 114 const scoped_refptr<GlobalLRU>& global_lru)
113 : max_size_(0), block_size_shift_(block_size_shift), lru_(global_lru) {} 115 : max_size_(0), block_size_shift_(block_size_shift), lru_(global_lru) {}
114 116
115 MultiBuffer::~MultiBuffer() { 117 MultiBuffer::~MultiBuffer() {
116 // Delete all writers.
117 for (const auto& i : writer_index_) {
118 delete i.second;
119 }
120 // Remove all blocks from the LRU. 118 // Remove all blocks from the LRU.
121 for (const auto& i : data_) { 119 for (const auto& i : data_) {
122 lru_->Remove(this, i.first); 120 lru_->Remove(this, i.first);
123 } 121 }
124 lru_->IncrementDataSize(-static_cast<int64_t>(data_.size())); 122 lru_->IncrementDataSize(-static_cast<int64_t>(data_.size()));
125 lru_->IncrementMaxSize(-max_size_); 123 lru_->IncrementMaxSize(-max_size_);
126 } 124 }
127 125
128 void MultiBuffer::AddReader(const BlockId& pos, Reader* reader) { 126 void MultiBuffer::AddReader(const BlockId& pos, Reader* reader) {
129 std::set<Reader*>* set_of_readers = &readers_[pos]; 127 std::set<Reader*>* set_of_readers = &readers_[pos];
(...skipping 18 matching lines...) Expand all
148 closest_block = pos; 146 closest_block = pos;
149 } else if (i == present_.begin()) { 147 } else if (i == present_.begin()) {
150 closest_block = -1; 148 closest_block = -1;
151 } else { 149 } else {
152 closest_block = i.interval_begin() - 1; 150 closest_block = i.interval_begin() - 1;
153 } 151 }
154 152
155 // Make sure that there are no present blocks between the writer and 153 // Make sure that there are no present blocks between the writer and
156 // the requested position, as that will cause the writer to quit. 154 // the requested position, as that will cause the writer to quit.
157 if (closest_writer > closest_block) { 155 if (closest_writer > closest_block) {
158 provider = writer_index_[closest_writer]; 156 provider = writer_index_[closest_writer].get();
159 DCHECK(provider); 157 DCHECK(provider);
160 } 158 }
161 } 159 }
162 if (!provider) { 160 if (!provider) {
163 DCHECK(writer_index_.find(pos) == writer_index_.end()); 161 DCHECK(writer_index_.find(pos) == writer_index_.end());
164 provider = writer_index_[pos] = CreateWriter(pos); 162 writer_index_[pos] = CreateWriter(pos);
165 provider->SetAvailableCallback(base::Bind( 163 provider = writer_index_[pos].get();
166 &MultiBuffer::DataProviderEvent, base::Unretained(this), provider));
167 } 164 }
168 provider->SetDeferred(false); 165 provider->SetDeferred(false);
169 } 166 }
170 167
171 void MultiBuffer::RemoveReader(const BlockId& pos, Reader* reader) { 168 void MultiBuffer::RemoveReader(const BlockId& pos, Reader* reader) {
172 auto i = readers_.find(pos); 169 auto i = readers_.find(pos);
173 if (i == readers_.end()) 170 if (i == readers_.end())
174 return; 171 return;
175 i->second.erase(reader); 172 i->second.erase(reader);
176 if (i->second.empty()) { 173 if (i->second.empty()) {
177 readers_.erase(i); 174 readers_.erase(i);
178 } 175 }
179 } 176 }
180 177
181 void MultiBuffer::CleanupWriters(const BlockId& pos) { 178 void MultiBuffer::CleanupWriters(const BlockId& pos) {
182 BlockId p2 = pos + kMaxWaitForReaderOffset; 179 BlockId p2 = pos + kMaxWaitForReaderOffset;
183 BlockId closest_writer = ClosestPreviousEntry(writer_index_, p2); 180 BlockId closest_writer = ClosestPreviousEntry(writer_index_, p2);
184 while (closest_writer > pos - kMaxWaitForWriterOffset) { 181 while (closest_writer > pos - kMaxWaitForWriterOffset) {
185 DCHECK(writer_index_[closest_writer]); 182 DCHECK(writer_index_[closest_writer]);
186 DataProviderEvent(writer_index_[closest_writer]); 183 OnDataProviderEvent(writer_index_[closest_writer].get());
187 closest_writer = ClosestPreviousEntry(writer_index_, closest_writer - 1); 184 closest_writer = ClosestPreviousEntry(writer_index_, closest_writer - 1);
188 } 185 }
189 } 186 }
190 187
191 bool MultiBuffer::Contains(const BlockId& pos) const { 188 bool MultiBuffer::Contains(const BlockId& pos) const {
192 DCHECK(present_[pos] == 0 || present_[pos] == 1) 189 DCHECK(present_[pos] == 0 || present_[pos] == 1)
193 << " pos = " << pos << " present_[pos] " << present_[pos]; 190 << " pos = " << pos << " present_[pos] " << present_[pos];
194 DCHECK_EQ(present_[pos], data_.find(pos) != data_.end() ? 1 : 0); 191 DCHECK_EQ(present_[pos], data_.find(pos) != data_.end() ? 1 : 0);
195 return !!present_[pos]; 192 return !!present_[pos];
196 } 193 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 } 248 }
252 if (i.interval_end() == freed_range.first.end) { 249 if (i.interval_end() == freed_range.first.end) {
253 // Notify the following range that it contains fewer blocks. 250 // Notify the following range that it contains fewer blocks.
254 auto j = i; 251 auto j = i;
255 ++j; 252 ++j;
256 DCHECK_EQ(j.value(), 1); 253 DCHECK_EQ(j.value(), 1);
257 NotifyAvailableRange(j.interval(), j.interval()); 254 NotifyAvailableRange(j.interval(), j.interval());
258 } 255 }
259 } 256 }
260 } 257 }
258 if (data_.empty())
259 OnEmpty();
261 } 260 }
262 261
262 void MultiBuffer::OnEmpty() {}
263
263 void MultiBuffer::AddProvider(scoped_ptr<DataProvider> provider) { 264 void MultiBuffer::AddProvider(scoped_ptr<DataProvider> provider) {
264 // If there is already a provider in the same location, we delete it. 265 // If there is already a provider in the same location, we delete it.
265 DCHECK(!provider->Available()); 266 DCHECK(!provider->Available());
266 BlockId pos = provider->Tell(); 267 BlockId pos = provider->Tell();
267 DataProvider** place = &writer_index_[pos]; 268 writer_index_[pos] = std::move(provider);
268 DCHECK_NE(*place, provider.get());
269 if (*place)
270 delete *place;
271 *place = provider.release();
272 } 269 }
273 270
274 scoped_ptr<MultiBuffer::DataProvider> MultiBuffer::RemoveProvider( 271 scoped_ptr<MultiBuffer::DataProvider> MultiBuffer::RemoveProvider(
275 DataProvider* provider) { 272 DataProvider* provider) {
276 BlockId pos = provider->Tell(); 273 BlockId pos = provider->Tell();
277 DCHECK_EQ(writer_index_[pos], provider); 274 auto iter = writer_index_.find(pos);
278 writer_index_.erase(pos); 275 DCHECK(iter != writer_index_.end());
279 return scoped_ptr<DataProvider>(provider); 276 DCHECK_EQ(iter->second.get(), provider);
277 scoped_ptr<DataProvider> ret = std::move(iter->second);
278 writer_index_.erase(iter);
279 return ret;
280 } 280 }
281 281
282 MultiBuffer::ProviderState MultiBuffer::SuggestProviderState( 282 MultiBuffer::ProviderState MultiBuffer::SuggestProviderState(
283 const BlockId& pos) const { 283 const BlockId& pos) const {
284 MultiBufferBlockId next_reader_pos = ClosestNextEntry(readers_, pos); 284 MultiBufferBlockId next_reader_pos = ClosestNextEntry(readers_, pos);
285 if (next_reader_pos != std::numeric_limits<MultiBufferBlockId>::max() && 285 if (next_reader_pos != std::numeric_limits<MultiBufferBlockId>::max() &&
286 (next_reader_pos - pos <= kMaxWaitForWriterOffset || !RangeSupported())) { 286 (next_reader_pos - pos <= kMaxWaitForWriterOffset || !RangeSupported())) {
287 // Check if there is another writer between us and the next reader. 287 // Check if there is another writer between us and the next reader.
288 MultiBufferBlockId next_writer_pos = 288 MultiBufferBlockId next_writer_pos =
289 ClosestNextEntry(writer_index_, pos + 1); 289 ClosestNextEntry(writer_index_, pos + 1);
(...skipping 27 matching lines...) Expand all
317 if (RangeSupported() && Contains(id)) 317 if (RangeSupported() && Contains(id))
318 return true; 318 return true;
319 319
320 return false; 320 return false;
321 } 321 }
322 322
323 void MultiBuffer::Prune(size_t max_to_free) { 323 void MultiBuffer::Prune(size_t max_to_free) {
324 lru_->Prune(max_to_free); 324 lru_->Prune(max_to_free);
325 } 325 }
326 326
327 void MultiBuffer::DataProviderEvent(DataProvider* provider_tmp) { 327 void MultiBuffer::OnDataProviderEvent(DataProvider* provider_tmp) {
328 scoped_ptr<DataProvider> provider(RemoveProvider(provider_tmp)); 328 scoped_ptr<DataProvider> provider(RemoveProvider(provider_tmp));
329 BlockId start_pos = provider->Tell(); 329 BlockId start_pos = provider->Tell();
330 BlockId pos = start_pos; 330 BlockId pos = start_pos;
331 bool eof = false; 331 bool eof = false;
332 int64_t blocks_before = data_.size(); 332 int64_t blocks_before = data_.size();
333 333
334 while (!ProviderCollision(pos) && !eof) { 334 while (!ProviderCollision(pos) && !eof) {
335 if (!provider->Available()) { 335 if (!provider->Available()) {
336 AddProvider(provider.Pass()); 336 AddProvider(std::move(provider));
337 break; 337 break;
338 } 338 }
339 DCHECK_GE(pos, 0); 339 DCHECK_GE(pos, 0);
340 scoped_refptr<DataBuffer> data = provider->Read(); 340 scoped_refptr<DataBuffer> data = provider->Read();
341 data_[pos] = data; 341 data_[pos] = data;
342 eof = data->end_of_stream(); 342 eof = data->end_of_stream();
343 if (!pinned_[pos]) 343 if (!pinned_[pos])
344 lru_->Use(this, pos); 344 lru_->Use(this, pos);
345 ++pos; 345 ++pos;
346 } 346 }
347 int64_t blocks_after = data_.size(); 347 int64_t blocks_after = data_.size();
348 int64_t blocks_added = blocks_after - blocks_before; 348 int64_t blocks_added = blocks_after - blocks_before;
349 349
350 if (pos > start_pos) { 350 if (pos > start_pos) {
351 present_.SetInterval(start_pos, pos, 1); 351 present_.SetInterval(start_pos, pos, 1);
352 Interval<BlockId> expanded_range = present_.find(start_pos).interval(); 352 Interval<BlockId> expanded_range = present_.find(start_pos).interval();
353 NotifyAvailableRange(expanded_range, expanded_range); 353 NotifyAvailableRange(expanded_range, expanded_range);
354 354
355 lru_->IncrementDataSize(blocks_added); 355 lru_->IncrementDataSize(blocks_added);
356 Prune(blocks_added * kMaxFreesPerAdd + 1); 356 Prune(blocks_added * kMaxFreesPerAdd + 1);
357 } 357 }
358 358
359 // Check that it's still there before we try to delete it. 359 // Check that it's still there before we try to delete it.
360 // In case of EOF or a collision, we might not have called AddProvider above. 360 // In case of EOF or a collision, we might not have called AddProvider above.
361 // Even if we did call AddProvider, calling NotifyAvailableRange can cause 361 // Even if we did call AddProvider, calling NotifyAvailableRange can cause
362 // readers to seek or self-destruct and clean up any associated writers. 362 // readers to seek or self-destruct and clean up any associated writers.
363 auto i = writer_index_.find(pos); 363 auto i = writer_index_.find(pos);
364 if (i != writer_index_.end() && i->second == provider_tmp) { 364 if (i != writer_index_.end() && i->second.get() == provider_tmp) {
365 switch (SuggestProviderState(pos)) { 365 switch (SuggestProviderState(pos)) {
366 case ProviderStateLoad: 366 case ProviderStateLoad:
367 // Not sure we actually need to do this 367 // Not sure we actually need to do this
368 provider_tmp->SetDeferred(false); 368 provider_tmp->SetDeferred(false);
369 break; 369 break;
370 case ProviderStateDefer: 370 case ProviderStateDefer:
371 provider_tmp->SetDeferred(true); 371 provider_tmp->SetDeferred(true);
372 break; 372 break;
373 case ProviderStateDead: 373 case ProviderStateDead:
374 RemoveProvider(provider_tmp); 374 RemoveProvider(provider_tmp);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 } 471 }
472 472
473 void MultiBuffer::IncrementMaxSize(int32_t size) { 473 void MultiBuffer::IncrementMaxSize(int32_t size) {
474 max_size_ += size; 474 max_size_ += size;
475 lru_->IncrementMaxSize(size); 475 lru_->IncrementMaxSize(size);
476 DCHECK_GE(max_size_, 0); 476 DCHECK_GE(max_size_, 0);
477 // Pruning only happens when blocks are added. 477 // Pruning only happens when blocks are added.
478 } 478 }
479 479
480 } // namespace media 480 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/multibuffer.h ('k') | media/blink/multibuffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698