OLD | NEW |
---|---|
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 "media/blink/multibuffer.h" | 5 #include "media/blink/multibuffer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 | 8 |
9 namespace media { | 9 namespace media { |
10 | 10 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 } | 106 } |
107 | 107 |
108 // | 108 // |
109 // MultiBuffer | 109 // MultiBuffer |
110 // | 110 // |
111 MultiBuffer::MultiBuffer(int32_t block_size_shift, | 111 MultiBuffer::MultiBuffer(int32_t block_size_shift, |
112 const scoped_refptr<GlobalLRU>& global_lru) | 112 const scoped_refptr<GlobalLRU>& global_lru) |
113 : max_size_(0), block_size_shift_(block_size_shift), lru_(global_lru) {} | 113 : max_size_(0), block_size_shift_(block_size_shift), lru_(global_lru) {} |
114 | 114 |
115 MultiBuffer::~MultiBuffer() { | 115 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. | 116 // Remove all blocks from the LRU. |
121 for (const auto& i : data_) { | 117 for (const auto& i : data_) { |
122 lru_->Remove(this, i.first); | 118 lru_->Remove(this, i.first); |
123 } | 119 } |
124 lru_->IncrementDataSize(-static_cast<int64_t>(data_.size())); | 120 lru_->IncrementDataSize(-static_cast<int64_t>(data_.size())); |
125 lru_->IncrementMaxSize(-max_size_); | 121 lru_->IncrementMaxSize(-max_size_); |
126 } | 122 } |
127 | 123 |
128 void MultiBuffer::AddReader(const BlockId& pos, Reader* reader) { | 124 void MultiBuffer::AddReader(const BlockId& pos, Reader* reader) { |
129 std::set<Reader*>* set_of_readers = &readers_[pos]; | 125 std::set<Reader*>* set_of_readers = &readers_[pos]; |
(...skipping 18 matching lines...) Expand all Loading... | |
148 closest_block = pos; | 144 closest_block = pos; |
149 } else if (i == present_.begin()) { | 145 } else if (i == present_.begin()) { |
150 closest_block = -1; | 146 closest_block = -1; |
151 } else { | 147 } else { |
152 closest_block = i.interval_begin() - 1; | 148 closest_block = i.interval_begin() - 1; |
153 } | 149 } |
154 | 150 |
155 // Make sure that there are no present blocks between the writer and | 151 // Make sure that there are no present blocks between the writer and |
156 // the requested position, as that will cause the writer to quit. | 152 // the requested position, as that will cause the writer to quit. |
157 if (closest_writer > closest_block) { | 153 if (closest_writer > closest_block) { |
158 provider = writer_index_[closest_writer]; | 154 provider = writer_index_[closest_writer].get(); |
159 DCHECK(provider); | 155 DCHECK(provider); |
160 } | 156 } |
161 } | 157 } |
162 if (!provider) { | 158 if (!provider) { |
163 DCHECK(writer_index_.find(pos) == writer_index_.end()); | 159 DCHECK(writer_index_.find(pos) == writer_index_.end()); |
164 provider = writer_index_[pos] = CreateWriter(pos); | 160 writer_index_[pos] = CreateWriter(pos); |
165 provider->SetAvailableCallback(base::Bind( | 161 provider = writer_index_[pos].get(); |
166 &MultiBuffer::DataProviderEvent, base::Unretained(this), provider)); | |
167 } | 162 } |
168 provider->SetDeferred(false); | 163 provider->SetDeferred(false); |
169 } | 164 } |
170 | 165 |
171 void MultiBuffer::RemoveReader(const BlockId& pos, Reader* reader) { | 166 void MultiBuffer::RemoveReader(const BlockId& pos, Reader* reader) { |
172 auto i = readers_.find(pos); | 167 auto i = readers_.find(pos); |
173 if (i == readers_.end()) | 168 if (i == readers_.end()) |
174 return; | 169 return; |
175 i->second.erase(reader); | 170 i->second.erase(reader); |
176 if (i->second.empty()) { | 171 if (i->second.empty()) { |
177 readers_.erase(i); | 172 readers_.erase(i); |
178 } | 173 } |
179 } | 174 } |
180 | 175 |
181 void MultiBuffer::CleanupWriters(const BlockId& pos) { | 176 void MultiBuffer::CleanupWriters(const BlockId& pos) { |
182 BlockId p2 = pos + kMaxWaitForReaderOffset; | 177 BlockId p2 = pos + kMaxWaitForReaderOffset; |
183 BlockId closest_writer = ClosestPreviousEntry(writer_index_, p2); | 178 BlockId closest_writer = ClosestPreviousEntry(writer_index_, p2); |
184 while (closest_writer > pos - kMaxWaitForWriterOffset) { | 179 while (closest_writer > pos - kMaxWaitForWriterOffset) { |
185 DCHECK(writer_index_[closest_writer]); | 180 DCHECK(writer_index_[closest_writer]); |
186 DataProviderEvent(writer_index_[closest_writer]); | 181 OnDataProviderEvent(writer_index_[closest_writer].get()); |
187 closest_writer = ClosestPreviousEntry(writer_index_, closest_writer - 1); | 182 closest_writer = ClosestPreviousEntry(writer_index_, closest_writer - 1); |
188 } | 183 } |
189 } | 184 } |
190 | 185 |
191 bool MultiBuffer::Contains(const BlockId& pos) const { | 186 bool MultiBuffer::Contains(const BlockId& pos) const { |
192 DCHECK(present_[pos] == 0 || present_[pos] == 1) | 187 DCHECK(present_[pos] == 0 || present_[pos] == 1) |
193 << " pos = " << pos << " present_[pos] " << present_[pos]; | 188 << " pos = " << pos << " present_[pos] " << present_[pos]; |
194 DCHECK_EQ(present_[pos], data_.find(pos) != data_.end() ? 1 : 0); | 189 DCHECK_EQ(present_[pos], data_.find(pos) != data_.end() ? 1 : 0); |
195 return !!present_[pos]; | 190 return !!present_[pos]; |
196 } | 191 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 } | 246 } |
252 if (i.interval_end() == freed_range.first.end) { | 247 if (i.interval_end() == freed_range.first.end) { |
253 // Notify the following range that it contains fewer blocks. | 248 // Notify the following range that it contains fewer blocks. |
254 auto j = i; | 249 auto j = i; |
255 ++j; | 250 ++j; |
256 DCHECK_EQ(j.value(), 1); | 251 DCHECK_EQ(j.value(), 1); |
257 NotifyAvailableRange(j.interval(), j.interval()); | 252 NotifyAvailableRange(j.interval(), j.interval()); |
258 } | 253 } |
259 } | 254 } |
260 } | 255 } |
256 if (data_.empty()) | |
257 OnEmpty(); | |
261 } | 258 } |
262 | 259 |
260 void MultiBuffer::OnEmpty() {} | |
261 | |
263 void MultiBuffer::AddProvider(scoped_ptr<DataProvider> provider) { | 262 void MultiBuffer::AddProvider(scoped_ptr<DataProvider> provider) { |
264 // If there is already a provider in the same location, we delete it. | 263 // If there is already a provider in the same location, we delete it. |
265 DCHECK(!provider->Available()); | 264 DCHECK(!provider->Available()); |
266 BlockId pos = provider->Tell(); | 265 BlockId pos = provider->Tell(); |
267 DataProvider** place = &writer_index_[pos]; | 266 writer_index_[pos] = provider.Pass(); |
xhwang
2015/11/25 01:01:44
nit: the new recommendation is to use std::move()
hubbe
2015/11/25 01:15:09
Fixed.
| |
268 DCHECK_NE(*place, provider.get()); | |
269 if (*place) | |
270 delete *place; | |
271 *place = provider.release(); | |
272 } | 267 } |
273 | 268 |
274 scoped_ptr<MultiBuffer::DataProvider> MultiBuffer::RemoveProvider( | 269 scoped_ptr<MultiBuffer::DataProvider> MultiBuffer::RemoveProvider( |
275 DataProvider* provider) { | 270 DataProvider* provider) { |
276 BlockId pos = provider->Tell(); | 271 BlockId pos = provider->Tell(); |
277 DCHECK_EQ(writer_index_[pos], provider); | 272 auto iter = writer_index_.find(pos); |
278 writer_index_.erase(pos); | 273 DCHECK(iter != writer_index_.end()); |
279 return scoped_ptr<DataProvider>(provider); | 274 DCHECK_EQ(iter->second.get(), provider); |
275 scoped_ptr<DataProvider> ret = iter->second.Pass(); | |
276 writer_index_.erase(iter); | |
277 return ret.Pass(); | |
280 } | 278 } |
281 | 279 |
282 MultiBuffer::ProviderState MultiBuffer::SuggestProviderState( | 280 MultiBuffer::ProviderState MultiBuffer::SuggestProviderState( |
283 const BlockId& pos) const { | 281 const BlockId& pos) const { |
284 MultiBufferBlockId next_reader_pos = ClosestNextEntry(readers_, pos); | 282 MultiBufferBlockId next_reader_pos = ClosestNextEntry(readers_, pos); |
285 if (next_reader_pos != std::numeric_limits<MultiBufferBlockId>::max() && | 283 if (next_reader_pos != std::numeric_limits<MultiBufferBlockId>::max() && |
286 (next_reader_pos - pos <= kMaxWaitForWriterOffset || !RangeSupported())) { | 284 (next_reader_pos - pos <= kMaxWaitForWriterOffset || !RangeSupported())) { |
287 // Check if there is another writer between us and the next reader. | 285 // Check if there is another writer between us and the next reader. |
288 MultiBufferBlockId next_writer_pos = | 286 MultiBufferBlockId next_writer_pos = |
289 ClosestNextEntry(writer_index_, pos + 1); | 287 ClosestNextEntry(writer_index_, pos + 1); |
(...skipping 27 matching lines...) Expand all Loading... | |
317 if (RangeSupported() && Contains(id)) | 315 if (RangeSupported() && Contains(id)) |
318 return true; | 316 return true; |
319 | 317 |
320 return false; | 318 return false; |
321 } | 319 } |
322 | 320 |
323 void MultiBuffer::Prune(size_t max_to_free) { | 321 void MultiBuffer::Prune(size_t max_to_free) { |
324 lru_->Prune(max_to_free); | 322 lru_->Prune(max_to_free); |
325 } | 323 } |
326 | 324 |
327 void MultiBuffer::DataProviderEvent(DataProvider* provider_tmp) { | 325 void MultiBuffer::OnDataProviderEvent(DataProvider* provider_tmp) { |
328 scoped_ptr<DataProvider> provider(RemoveProvider(provider_tmp)); | 326 scoped_ptr<DataProvider> provider(RemoveProvider(provider_tmp)); |
329 BlockId start_pos = provider->Tell(); | 327 BlockId start_pos = provider->Tell(); |
330 BlockId pos = start_pos; | 328 BlockId pos = start_pos; |
331 bool eof = false; | 329 bool eof = false; |
332 int64_t blocks_before = data_.size(); | 330 int64_t blocks_before = data_.size(); |
333 | 331 |
334 while (!ProviderCollision(pos) && !eof) { | 332 while (!ProviderCollision(pos) && !eof) { |
335 if (!provider->Available()) { | 333 if (!provider->Available()) { |
336 AddProvider(provider.Pass()); | 334 AddProvider(provider.Pass()); |
337 break; | 335 break; |
(...skipping 16 matching lines...) Expand all Loading... | |
354 | 352 |
355 lru_->IncrementDataSize(blocks_added); | 353 lru_->IncrementDataSize(blocks_added); |
356 Prune(blocks_added * kMaxFreesPerAdd + 1); | 354 Prune(blocks_added * kMaxFreesPerAdd + 1); |
357 } | 355 } |
358 | 356 |
359 // Check that it's still there before we try to delete it. | 357 // 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. | 358 // 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 | 359 // Even if we did call AddProvider, calling NotifyAvailableRange can cause |
362 // readers to seek or self-destruct and clean up any associated writers. | 360 // readers to seek or self-destruct and clean up any associated writers. |
363 auto i = writer_index_.find(pos); | 361 auto i = writer_index_.find(pos); |
364 if (i != writer_index_.end() && i->second == provider_tmp) { | 362 if (i != writer_index_.end() && i->second.get() == provider_tmp) { |
365 switch (SuggestProviderState(pos)) { | 363 switch (SuggestProviderState(pos)) { |
366 case ProviderStateLoad: | 364 case ProviderStateLoad: |
367 // Not sure we actually need to do this | 365 // Not sure we actually need to do this |
368 provider_tmp->SetDeferred(false); | 366 provider_tmp->SetDeferred(false); |
369 break; | 367 break; |
370 case ProviderStateDefer: | 368 case ProviderStateDefer: |
371 provider_tmp->SetDeferred(true); | 369 provider_tmp->SetDeferred(true); |
372 break; | 370 break; |
373 case ProviderStateDead: | 371 case ProviderStateDead: |
374 RemoveProvider(provider_tmp); | 372 RemoveProvider(provider_tmp); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 } | 469 } |
472 | 470 |
473 void MultiBuffer::IncrementMaxSize(int32_t size) { | 471 void MultiBuffer::IncrementMaxSize(int32_t size) { |
474 max_size_ += size; | 472 max_size_ += size; |
475 lru_->IncrementMaxSize(size); | 473 lru_->IncrementMaxSize(size); |
476 DCHECK_GE(max_size_, 0); | 474 DCHECK_GE(max_size_, 0); |
477 // Pruning only happens when blocks are added. | 475 // Pruning only happens when blocks are added. |
478 } | 476 } |
479 | 477 |
480 } // namespace media | 478 } // namespace media |
OLD | NEW |