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 |