forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultibuffer_reader.h
192 lines (148 loc) · 6.74 KB
/
multibuffer_reader.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BLINK_MULTIBUFFER_READER_H_
#define MEDIA_BLINK_MULTIBUFFER_READER_H_
#include <stdint.h>
#include <limits>
#include <map>
#include <set>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "media/blink/media_blink_export.h"
#include "media/blink/multibuffer.h"
namespace media {
// Wrapper for MultiBuffer that offers a simple byte-reading
// interface with prefetch.
class MEDIA_BLINK_EXPORT MultiBufferReader : public MultiBuffer::Reader {
public:
// Note that |progress_callback| is guaranteed to be called if
// a redirect happens and the url_data is updated. Otherwise
// origin checks will become insecure.
// Users probably want to call SetMaxBuffer & SetPreload after
// creating the a MultiBufferReader.
// The progress callback will be called when the "available range"
// changes. (The number of bytes available for reading before and
// after the current position.) The arguments for the progress
// callback is the first byte available (from beginning of file)
// and the last byte available + 1. Note that there may be other
// regions of available data in the cache as well.
// If |end| is not known, use -1.
MultiBufferReader(
MultiBuffer* multibuffer,
int64_t start,
int64_t end,
const base::Callback<void(int64_t, int64_t)>& progress_callback);
~MultiBufferReader() override;
// Returns number of bytes available for reading. At position |pos|
// When the rest of the file is available, the number returned will
// be greater than the number or readable bytes. If an error occurs,
// -1 is returned.
int64_t AvailableAt(int64_t pos) const;
// Returns number of bytes available for reading at the current position.
int64_t Available() const { return AvailableAt(pos_); }
// Seek to a different position.
// If there is a pending Wait(), it will be cancelled.
void Seek(int64_t pos);
// Returns the current position.
int64_t Tell() const { return pos_; }
// Tries to read |len| bytes from position |pos|.
// Returns number of bytes read.
// Safe to call from any thread.
int64_t TryReadAt(int64_t pos, uint8_t* data, int64_t len);
// Tries to read |len| bytes and update current position.
// Returns number of bytes read.
int64_t TryRead(uint8_t* data, int64_t len);
// Wait until |len| bytes are available for reading.
// Returns net::OK if |len| bytes are already available, otherwise it will
// return net::ERR_IO_PENDING and call |cb| at some point later.
// |len| must be smaller or equal to max_buffer_forward.
int Wait(int64_t len, const base::Closure& cb);
// Set how much data we try to preload into the cache ahead of our current
// location. Normally, we preload until we have preload_high bytes, then
// stop until we fall below preload_low bytes. Note that preload can be
// set higher than max_buffer_forward, but the result is usually that
// some blocks will be freed between the current position and the preload
// position.
void SetPreload(int64_t preload_high, int64_t preload_low);
// Change how much data we pin to the cache.
// The range [current_position - backward ... current_position + forward)
// will be locked in the cache. Calling Wait() or TryRead() with values
// larger than |forward| is not supported.
void SetPinRange(int64_t backward, int64_t forward);
// Set how much memory usage we target. This memory is added to the global
// LRU and shared between all multibuffers. We may end up using more memory
// if no memory can be freed due to pinning.
void SetMaxBuffer(int64_t bytes);
// Returns true if we are currently loading data.
bool IsLoading() const;
// Reader implementation.
void NotifyAvailableRange(const Interval<MultiBufferBlockId>& range) override;
// Getters
int64_t preload_high() const { return preload_high_; }
int64_t preload_low() const { return preload_low_; }
// Setters
void SetIsClientAudioElement(bool is_client_audio_element) {
is_client_audio_element_ = is_client_audio_element;
}
private:
friend class MultibufferDataSourceTest;
// Returns the block for a particular byte position.
MultiBufferBlockId block(int64_t byte_pos) const {
return byte_pos >> multibuffer_->block_size_shift();
}
// Returns the block for a particular byte position, rounding up.
MultiBufferBlockId block_ceil(int64_t byte_pos) const {
return block(byte_pos + (1LL << multibuffer_->block_size_shift()) - 1);
}
// Unpin previous range, then pin the new range.
void PinRange(MultiBuffer::BlockId begin, MultiBuffer::BlockId end);
// Check if wait operation can complete now.
void CheckWait();
// Recalculate preload_pos_ and update our entry in the multibuffer
// reader index. Also call CheckWait(). This function is basically
// called anything changes, like when we get more data or seek to
// a new position.
void UpdateInternalState();
// Update end_ if p-1 contains an end-of-stream block.
void UpdateEnd(MultiBufferBlockId p);
// Indirection function used to call callbacks. When we post a callback
// we indirect it through a weak_ptr and this function to make sure we
// don't call any callbacks after this object has been destroyed.
void Call(const base::Closure& cb) const;
// The multibuffer we're wrapping, not owned.
MultiBuffer* multibuffer_;
// We're not interested in reading past this position.
int64_t end_;
// Defer reading once we have this much data.
int64_t preload_high_;
// Stop deferring once we have this much data.
int64_t preload_low_;
// Pin this much data in the cache from the current position.
int64_t max_buffer_forward_;
int64_t max_buffer_backward_;
// The amount of buffer we've added to the global LRU.
int64_t current_buffer_size_;
// Currently pinned range.
Interval<MultiBuffer::BlockId> pinned_range_;
// Current position in bytes.
int64_t pos_;
// Is the client an audio element?
bool is_client_audio_element_ = false;
// [block(pos_)..preload_pos_) are known to be in the cache.
// preload_pos_ is only allowed to point to a filled
// cache position if it is equal to end_ or pos_+preload_.
// This is a pointer to a slot in the cache, so the unit is
// blocks.
MultiBufferBlockId preload_pos_;
// True if we've requested data from the cache by calling WaitFor().
bool loading_;
// When Available() > current_wait_size_ we call cb_.
int64_t current_wait_size_;
base::Closure cb_;
// Progress callback.
base::Callback<void(int64_t, int64_t)> progress_callback_;
base::WeakPtrFactory<MultiBufferReader> weak_factory_;
};
} // namespace media
#endif // MEDIA_BLINK_MULTIBUFFER_READER_H_