Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 #ifndef MEDIA_BLINK_MULTIBUFFER_H_ | |
| 6 #define MEDIA_BLINK_MULTIBUFFER_H_ | |
| 7 | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <map> | |
| 11 | |
| 12 #include "base/callback.h" | |
| 13 #include "base/memory/ref_counted.h" | |
| 14 #include "media/base/data_buffer.h" | |
| 15 #include "media/blink/lru.h" | |
| 16 #include "media/blink/rangemap.h" | |
| 17 #include "media/blink/waiter_index.h" | |
| 18 | |
| 19 namespace media { | |
| 20 | |
| 21 const int kMaxFreesPerAdd = 10; | |
| 22 const int kMaxWaitForWriterOffset = 5; | |
| 23 | |
| 24 // MultiBuffers are multi-reader multi-writer cache/buffers with | |
| 25 // prefetching and pinning. Data is stored internally in ref-counted | |
| 26 // blocks of identical size. |block_size_shift| is log2 of the block | |
| 27 // size. | |
| 28 class MultiBuffer { | |
|
liberato (no reviews please)
2015/06/09 15:00:54
the name "MultiBuffer" is a little confusing. may
hubbe
2015/06/09 21:23:48
It's meant to replace multiple preloading buffers.
| |
| 29 public: | |
| 30 explicit MultiBuffer(int32_t block_size_shift); | |
| 31 virtual ~MultiBuffer(); | |
| 32 | |
| 33 typedef std::map<int32_t, scoped_refptr<DataBuffer> > DataMap; | |
| 34 | |
| 35 // Adds a writer. This writer becomes responsible | |
| 36 // for writing data at |pos| and forwards. | |
| 37 // Takes ownership of |writer|. | |
| 38 void AddWriter(int32_t pos, Waiter* writer); | |
|
liberato (no reviews please)
2015/06/09 15:00:53
are all the positions in byte offsets or block off
hubbe
2015/06/09 21:23:48
Yes. (the new typedef makes that clear)
| |
| 39 | |
| 40 // Remove a writer. | |
| 41 // Caller takes ownership of |writer|. | |
| 42 void RemoveWriter(int32_t pos, Waiter* writer); | |
| 43 | |
| 44 // Wait for block |pos| to become available. | |
| 45 // Starts new Writers as needed. | |
| 46 void WaitFor(int32_t pos, Waiter* reader); | |
| 47 | |
| 48 // Let the buffer that we're going to want to read | |
| 49 // block |pos|, but we're ok with the current level | |
| 50 // of buffering, so no worries. | |
| 51 void DeferredWaitFor(int32_t pos, Waiter* reader); | |
|
liberato (no reviews please)
2015/06/09 15:00:53
why do we need WaitFor vs DeferredWaitFor? should
hubbe
2015/06/09 21:23:48
This class doesn't know about any preload specs.
| |
| 52 | |
| 53 // Stop waiting for block |pos|. | |
| 54 // Often followed by a call to WaitFor(pos + 1, ...); | |
| 55 void StopWaitFor(int32_t pos, Waiter* reader); | |
| 56 | |
| 57 // Returns true if block |pos| is available in the cache. | |
| 58 bool Contains(int32_t pos) const; | |
| 59 | |
| 60 // Returns true if some reader is currently waiting for | |
| 61 // block |pos|. | |
| 62 bool WantNow(int32_t pos) const; | |
| 63 | |
| 64 // Returns true if some reader is will want block |pos| soon. | |
| 65 bool WantSoon(int32_t pos) const; | |
| 66 | |
| 67 // Add a data block to the cache, notifying readers as | |
| 68 // needed and prune old blocks if cache is too big. | |
| 69 void AddData(int32_t pos, scoped_refptr<DataBuffer> data); | |
| 70 | |
| 71 // Change the pin count for a range of data blocks. | |
| 72 // Note that blocks do not have to be present in the | |
| 73 // cache to be pinned. | |
| 74 // Examples: | |
| 75 // Pin block 3, 4 & 5: PinRange(3, 6, 1); | |
| 76 // Unpin block 4 & 5: PinRange(4, 6, -1); | |
| 77 void PinRange(int32_t from, int32_t to, int32_t howmuch); | |
| 78 | |
| 79 // Increment max cache size by |size|. | |
| 80 void IncrementMaxSize(int32_t size); | |
| 81 | |
| 82 // Accessors. | |
| 83 const DataMap& map() const { return data_; } | |
| 84 int32_t block_size_shift() const { return block_size_shift_; } | |
| 85 | |
| 86 protected: | |
| 87 // Start a new writer at |pos|. | |
| 88 // Should call AddWriter(). | |
| 89 virtual void StartWriter(int32_t pos) = 0; | |
|
liberato (no reviews please)
2015/06/09 15:00:53
MultiBuffer::StartWriter => new Writer => MultiBuf
hubbe
2015/06/09 21:23:48
I could break out the cache itself into something
| |
| 90 | |
| 91 private: | |
| 92 // Free elements from cache if needed and possible. | |
| 93 void Prune(); | |
| 94 | |
| 95 // Current number of blocks. | |
| 96 int32_t size_; | |
| 97 | |
| 98 // Max number of blocks. | |
| 99 int32_t max_size_; | |
| 100 | |
| 101 // log2 of block size. | |
| 102 int32_t block_size_shift_; | |
| 103 | |
| 104 // Stores the actual data. | |
| 105 DataMap data_; | |
| 106 | |
| 107 // Keeps track of readers waiting for data. | |
| 108 WaiterIndex reader_index_; | |
| 109 | |
| 110 // Keeps track of readers that will want data soon. | |
| 111 WaiterIndex deferred_reader_index_; | |
| 112 | |
| 113 // Keeps track of what writers are waiting. | |
| 114 WaiterIndex writer_index_; | |
| 115 | |
| 116 // The LRU should contain all blocks which are not pinned. | |
| 117 LRU<int32_t> lru_; | |
| 118 | |
| 119 // Keeps track of what blocks are pinned. If block p is pinned, | |
| 120 // then pinned_[p] > 0. Pinned blocks cannot be freed and are | |
| 121 // not present in |lru_|. | |
| 122 RangeMap<int32_t, int32_t> pinned_; | |
| 123 }; | |
| 124 | |
| 125 // Typically, calling MultiBuffer::StartWriter() will | |
| 126 // instantiate a subclass of this class. Writers are | |
| 127 // responsible for writing data into the cache. | |
| 128 // Writers are owned by the MultiBuffer. | |
| 129 class MultiBufferWriter : public Waiter { | |
|
liberato (no reviews please)
2015/06/09 15:00:54
this might be better off in another .h
hubbe
2015/06/09 21:23:48
They really are meant to be used as a set.
Origina
| |
| 130 MultiBufferWriter(MultiBuffer* multibuffer, int32_t pos); | |
| 131 | |
| 132 ~MultiBufferWriter() override; | |
| 133 | |
| 134 // Waiter implementation. | |
| 135 void Continue() override; | |
| 136 | |
| 137 protected: | |
| 138 virtual void SetDeferred(bool deferred) = 0; | |
| 139 | |
| 140 // Write |data| to |pos_| in the cache and update |pos_|. | |
| 141 void Write(scoped_refptr<DataBuffer> data); | |
| 142 | |
| 143 int32_t pos_; | |
| 144 MultiBuffer* multibuffer_; | |
| 145 }; | |
| 146 | |
| 147 // Wrapper for MultiBuffer that offers a simple byte-reading | |
| 148 // interface with prefetch. | |
| 149 class MultiBufferReader : public Waiter { | |
| 150 public: | |
| 151 MultiBufferReader(MultiBuffer* multibuffer, | |
| 152 int64_t start, | |
| 153 int64_t end, | |
| 154 int64_t preload, | |
| 155 int64_t max_buffer_forward, | |
| 156 int64_t max_buffer_backward); | |
| 157 | |
| 158 ~MultiBufferReader() override; | |
| 159 | |
| 160 // Returns number of bytes available for reading. | |
| 161 // If the actual number of bytes available is greater | |
| 162 // than |preload|, then it might return a number between | |
| 163 // |preload| and and the actual number. | |
| 164 int64_t Available() const; | |
| 165 | |
| 166 // Seek to a different position. | |
| 167 void Seek(int64_t pos); | |
| 168 | |
| 169 // Tries to read |len| bytes and advance position. | |
| 170 // Returns true if successful. | |
| 171 bool TryRead(unsigned char *data, int64_t len); | |
| 172 | |
| 173 // Wait until |len| bytes are available for reading. | |
| 174 void Wait(int64_t len, base::Closure cb); | |
| 175 | |
| 176 // Waiter implementation. | |
| 177 void Continue() override; | |
| 178 | |
| 179 private: | |
| 180 // Returns the block for a particular byte position. | |
| 181 int32_t block(int64_t byte_pos) const; | |
| 182 | |
| 183 // Returns the block for a particular byte position, rounding up. | |
| 184 int32_t block_ciel(int64_t byte_pos) const; | |
| 185 | |
| 186 // Check if wait operation can complete now. | |
| 187 void CheckWait(); | |
| 188 | |
| 189 // Increment preload position if data has been added to the buffer. | |
| 190 void IncrementPreloadPos(); | |
| 191 | |
| 192 // We're not interested in reading past this position. | |
| 193 const int64_t end_; | |
| 194 | |
| 195 // Defer reading once we have this much data. | |
| 196 const int64_t preload_; | |
| 197 | |
| 198 // Pin this much data in the cache from the current position. | |
| 199 const int64_t max_buffer_forward_; | |
| 200 const int64_t max_buffer_backward_; | |
| 201 | |
| 202 // Current position in bytes. | |
| 203 int64_t pos_; | |
| 204 | |
| 205 // [block(pos_)..preload_pos_) are known to be in the cache. | |
| 206 // preload_pos_ is only allowed to point to a filled | |
| 207 // cache position if it is equal to end_ or pos_+preload_. | |
| 208 // This is a pointer to a slot in the cache, so the unit is | |
| 209 // blocks. | |
| 210 int32_t preload_pos_; | |
| 211 | |
| 212 // When Available() > current_wait_size_ we call cb_. | |
| 213 int64_t current_wait_size_; | |
| 214 base::Closure cb_; | |
| 215 | |
| 216 // The multibuffer we're wrapping, not owned. | |
| 217 MultiBuffer* multibuffer_; | |
| 218 }; | |
| 219 | |
| 220 } // namespace media | |
| 221 | |
| 222 #endif // MEDIA_BLINK_MULTIBUFFER_H_ | |
| OLD | NEW |