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