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 #ifndef MEDIA_BLINK_MULTIBUFFER_H_ | 5 #ifndef MEDIA_BLINK_MULTIBUFFER_H_ |
6 #define MEDIA_BLINK_MULTIBUFFER_H_ | 6 #define MEDIA_BLINK_MULTIBUFFER_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
11 #include <map> | 11 #include <map> |
12 #include <set> | 12 #include <set> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/containers/hash_tables.h" | 16 #include "base/containers/hash_tables.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
| 19 #include "base/memory/scoped_ptr.h" |
19 #include "media/base/data_buffer.h" | 20 #include "media/base/data_buffer.h" |
20 #include "media/blink/interval_map.h" | 21 #include "media/blink/interval_map.h" |
21 #include "media/blink/lru.h" | 22 #include "media/blink/lru.h" |
22 #include "media/blink/media_blink_export.h" | 23 #include "media/blink/media_blink_export.h" |
23 | 24 |
24 namespace media { | 25 namespace media { |
25 | 26 |
| 27 // Used to identify a block of data in the multibuffer. |
| 28 // Our blocks are 32kb (1 << 15), so our maximum cacheable file size |
| 29 // is 1 << (15 + 31) = 64Tb |
26 typedef int32_t MultiBufferBlockId; | 30 typedef int32_t MultiBufferBlockId; |
27 class MultiBuffer; | 31 class MultiBuffer; |
| 32 |
| 33 // This type is used to identify a block in the LRU, which is shared between |
| 34 // multibuffers. |
28 typedef std::pair<MultiBuffer*, MultiBufferBlockId> MultiBufferGlobalBlockId; | 35 typedef std::pair<MultiBuffer*, MultiBufferBlockId> MultiBufferGlobalBlockId; |
29 | 36 |
30 } // namespace media | 37 } // namespace media |
31 | 38 |
32 namespace BASE_HASH_NAMESPACE { | 39 namespace BASE_HASH_NAMESPACE { |
33 | 40 |
34 template <> | 41 template <> |
35 struct hash<media::MultiBufferGlobalBlockId> { | 42 struct hash<media::MultiBufferGlobalBlockId> { |
36 std::size_t operator()(const media::MultiBufferGlobalBlockId& key) const { | 43 std::size_t operator()(const media::MultiBufferGlobalBlockId& key) const { |
37 // It would be nice if we could use intptr_t instead of int64_t here, but | 44 // It would be nice if we could use intptr_t instead of int64_t here, but |
(...skipping 27 matching lines...) Expand all Loading... |
65 // When new readers are added, new data providers are created if | 72 // When new readers are added, new data providers are created if |
66 // the new reader doesn't fall into the look-ahead region of | 73 // the new reader doesn't fall into the look-ahead region of |
67 // an existing data provider. | 74 // an existing data provider. |
68 | 75 |
69 // This is the size of the look-ahead region. | 76 // This is the size of the look-ahead region. |
70 const int kMaxWaitForWriterOffset = 5; | 77 const int kMaxWaitForWriterOffset = 5; |
71 | 78 |
72 // This is the size of the look-behind region. | 79 // This is the size of the look-behind region. |
73 const int kMaxWaitForReaderOffset = 50; | 80 const int kMaxWaitForReaderOffset = 50; |
74 | 81 |
75 class MultiBuffer; | |
76 | |
77 // MultiBuffers are multi-reader multi-writer cache/buffers with | 82 // MultiBuffers are multi-reader multi-writer cache/buffers with |
78 // prefetching and pinning. Data is stored internally in ref-counted | 83 // prefetching and pinning. Data is stored internally in ref-counted |
79 // blocks of identical size. |block_size_shift| is log2 of the block | 84 // blocks of identical size. |block_size_shift| is log2 of the block |
80 // size. | 85 // size. |
81 // | 86 // |
82 // Users should inherit this class and implement CreateWriter(). | 87 // Users should inherit this class and implement CreateWriter(). |
83 // TODO(hubbe): Make the multibuffer respond to memory pressure. | 88 // TODO(hubbe): Make the multibuffer respond to memory pressure. |
84 class MEDIA_BLINK_EXPORT MultiBuffer { | 89 class MEDIA_BLINK_EXPORT MultiBuffer { |
85 public: | 90 public: |
86 // Interface for clients wishing to read data out of this cache. | 91 // Interface for clients wishing to read data out of this cache. |
(...skipping 25 matching lines...) Expand all Loading... |
112 // Returns true if one (or more) blocks are | 117 // Returns true if one (or more) blocks are |
113 // availble to read. | 118 // availble to read. |
114 virtual bool Available() const = 0; | 119 virtual bool Available() const = 0; |
115 | 120 |
116 // Returns the next block. Only valid if Available() | 121 // Returns the next block. Only valid if Available() |
117 // returns true. Last block might be of a smaller size | 122 // returns true. Last block might be of a smaller size |
118 // and after the last block we will get an end-of-stream | 123 // and after the last block we will get an end-of-stream |
119 // DataBuffer. | 124 // DataBuffer. |
120 virtual scoped_refptr<DataBuffer> Read() = 0; | 125 virtual scoped_refptr<DataBuffer> Read() = 0; |
121 | 126 |
122 // |cb| is called every time Available() becomes true. | |
123 virtual void SetAvailableCallback(const base::Closure& cb) = 0; | |
124 | |
125 // Ask the data provider to stop giving us data. | 127 // Ask the data provider to stop giving us data. |
126 // It's ok if the effect is not immediate. | 128 // It's ok if the effect is not immediate. |
127 virtual void SetDeferred(bool deferred) = 0; | 129 virtual void SetDeferred(bool deferred) = 0; |
128 }; | 130 }; |
129 | 131 |
130 // Multibuffers use a global shared LRU to free memory. | 132 // Multibuffers use a global shared LRU to free memory. |
131 // This effectively means that recently used multibuffers can | 133 // This effectively means that recently used multibuffers can |
132 // borrow memory from less recently used ones. | 134 // borrow memory from less recently used ones. |
133 class MEDIA_BLINK_EXPORT GlobalLRU : public base::RefCounted<GlobalLRU> { | 135 class MEDIA_BLINK_EXPORT GlobalLRU : public base::RefCounted<GlobalLRU> { |
134 public: | 136 public: |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 // function for applying multiple changes to the pinned ranges. | 224 // function for applying multiple changes to the pinned ranges. |
223 void PinRanges(const IntervalMap<BlockId, int32_t>& ranges); | 225 void PinRanges(const IntervalMap<BlockId, int32_t>& ranges); |
224 | 226 |
225 // Increment max cache size by |size| (counted in blocks). | 227 // Increment max cache size by |size| (counted in blocks). |
226 void IncrementMaxSize(int32_t size); | 228 void IncrementMaxSize(int32_t size); |
227 | 229 |
228 // Caller takes ownership of 'provider', cache will | 230 // Caller takes ownership of 'provider', cache will |
229 // not call it anymore. | 231 // not call it anymore. |
230 scoped_ptr<DataProvider> RemoveProvider(DataProvider* provider); | 232 scoped_ptr<DataProvider> RemoveProvider(DataProvider* provider); |
231 | 233 |
232 // Add a writer to this cache. Cache takes ownership and | 234 // Add a writer to this cache. Cache takes ownership, and may |
233 // may choose to destroy it. | 235 // destroy |provider| later. (Not during this call.) |
234 void AddProvider(scoped_ptr<DataProvider> provider); | 236 void AddProvider(scoped_ptr<DataProvider> provider); |
235 | 237 |
236 // Transfer all data from |other| to this. | 238 // Transfer all data from |other| to this. |
237 void MergeFrom(MultiBuffer* other); | 239 void MergeFrom(MultiBuffer* other); |
238 | 240 |
239 // Accessors. | 241 // Accessors. |
240 const DataMap& map() const { return data_; } | 242 const DataMap& map() const { return data_; } |
241 int32_t block_size_shift() const { return block_size_shift_; } | 243 int32_t block_size_shift() const { return block_size_shift_; } |
242 | 244 |
| 245 // Callback which notifies us that a data provider has |
| 246 // some data for us. Also called when it might be appropriate |
| 247 // for a provider in a deferred state to wake up. |
| 248 void OnDataProviderEvent(DataProvider* provider); |
| 249 |
243 protected: | 250 protected: |
244 // Create a new writer at |pos| and return it. | 251 // Create a new writer at |pos| and return it. |
245 // Users needs to implemement this method. | 252 // Users needs to implemement this method. |
246 virtual DataProvider* CreateWriter(const BlockId& pos) = 0; | 253 virtual scoped_ptr<DataProvider> CreateWriter(const BlockId& pos) = 0; |
247 | 254 |
248 virtual bool RangeSupported() const = 0; | 255 virtual bool RangeSupported() const = 0; |
249 | 256 |
| 257 // Called when the cache becomes empty. Implementations can use this |
| 258 // as a signal for when we should free this object and any metadata |
| 259 // that goes with it. |
| 260 virtual void OnEmpty(); |
| 261 |
250 private: | 262 private: |
251 // For testing. | 263 // For testing. |
252 friend class TestMultiBuffer; | 264 friend class TestMultiBuffer; |
253 | 265 |
254 enum ProviderState { | 266 enum ProviderState { |
255 ProviderStateDead, | 267 ProviderStateDead, |
256 ProviderStateDefer, | 268 ProviderStateDefer, |
257 ProviderStateLoad | 269 ProviderStateLoad |
258 }; | 270 }; |
259 | 271 |
260 // Can be overriden for testing. | 272 // Can be overriden for testing. |
261 virtual void Prune(size_t max_to_free); | 273 virtual void Prune(size_t max_to_free); |
262 | 274 |
263 // Remove the given blocks from the multibuffer, called from | 275 // Remove the given blocks from the multibuffer, called from |
264 // GlobalLRU::Prune(). | 276 // GlobalLRU::Prune(). |
265 void ReleaseBlocks(const std::vector<MultiBufferBlockId>& blocks); | 277 void ReleaseBlocks(const std::vector<MultiBufferBlockId>& blocks); |
266 | 278 |
267 // Figure out what state a writer at |pos| should be in. | 279 // Figure out what state a writer at |pos| should be in. |
268 ProviderState SuggestProviderState(const BlockId& pos) const; | 280 ProviderState SuggestProviderState(const BlockId& pos) const; |
269 | 281 |
270 // Returns true if a writer at |pos| is colliding with | 282 // Returns true if a writer at |pos| is colliding with |
271 // output of another writer. | 283 // output of another writer. |
272 bool ProviderCollision(const BlockId& pos) const; | 284 bool ProviderCollision(const BlockId& pos) const; |
273 | 285 |
274 // Call NotifyAvailableRange(new_range) on all readers waiting | 286 // Call NotifyAvailableRange(new_range) on all readers waiting |
275 // for a block in |observer_range| | 287 // for a block in |observer_range| |
276 void NotifyAvailableRange(const Interval<MultiBufferBlockId>& observer_range, | 288 void NotifyAvailableRange(const Interval<MultiBufferBlockId>& observer_range, |
277 const Interval<MultiBufferBlockId>& new_range); | 289 const Interval<MultiBufferBlockId>& new_range); |
278 | 290 |
279 // Callback which notifies us that a data provider has | |
280 // some data for us. Also called when it might be apprperiate | |
281 // for a provider in a deferred state to wake up. | |
282 void DataProviderEvent(DataProvider* provider); | |
283 | |
284 // Max number of blocks. | 291 // Max number of blocks. |
285 int64_t max_size_; | 292 int64_t max_size_; |
286 | 293 |
287 // log2 of block size. | 294 // log2 of block size. |
288 int32_t block_size_shift_; | 295 int32_t block_size_shift_; |
289 | 296 |
290 // Stores the actual data. | 297 // Stores the actual data. |
291 DataMap data_; | 298 DataMap data_; |
292 | 299 |
293 // Keeps track of readers waiting for data. | 300 // Keeps track of readers waiting for data. |
294 std::map<MultiBufferBlockId, std::set<Reader*>> readers_; | 301 std::map<MultiBufferBlockId, std::set<Reader*>> readers_; |
295 | 302 |
296 // Keeps track of writers by their position. | 303 // Keeps track of writers by their position. |
297 // The writers are owned by this class. | 304 // The writers are owned by this class. |
298 // TODO(hubbe): Use ScopedPtrMap here. (must add upper/lower_bound first) | 305 std::map<BlockId, scoped_ptr<DataProvider>> writer_index_; |
299 std::map<BlockId, DataProvider*> writer_index_; | |
300 | 306 |
301 // Gloabally shared LRU, decides which block to free next. | 307 // Gloabally shared LRU, decides which block to free next. |
302 scoped_refptr<GlobalLRU> lru_; | 308 scoped_refptr<GlobalLRU> lru_; |
303 | 309 |
304 // Keeps track of what blocks are pinned. If block p is pinned, | 310 // Keeps track of what blocks are pinned. If block p is pinned, |
305 // then pinned_[p] > 0. Pinned blocks cannot be freed and should not | 311 // then pinned_[p] > 0. Pinned blocks cannot be freed and should not |
306 // be present in |lru_|. | 312 // be present in |lru_|. |
307 IntervalMap<BlockId, int32_t> pinned_; | 313 IntervalMap<BlockId, int32_t> pinned_; |
308 | 314 |
309 // present_[block] should be 1 for all blocks that are present | 315 // present_[block] should be 1 for all blocks that are present |
310 // and 0 for all blocks that are not. Used to quickly figure out | 316 // and 0 for all blocks that are not. Used to quickly figure out |
311 // ranges of available/unavailable blocks without iterating. | 317 // ranges of available/unavailable blocks without iterating. |
312 IntervalMap<BlockId, int32_t> present_; | 318 IntervalMap<BlockId, int32_t> present_; |
| 319 |
| 320 DISALLOW_COPY_AND_ASSIGN(MultiBuffer); |
313 }; | 321 }; |
314 | 322 |
315 } // namespace media | 323 } // namespace media |
316 | 324 |
317 #endif // MEDIA_BLINK_MULTIBUFFER_H_ | 325 #endif // MEDIA_BLINK_MULTIBUFFER_H_ |
OLD | NEW |