1 // Copyright (c) 2012 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.
5 // SeekableBuffer to support backward and forward seeking in a buffer for
6 // reading a media data source.
8 // In order to support backward and forward seeking, this class buffers data in
9 // both backward and forward directions, the current read position can be reset
10 // to anywhere in the buffered data.
12 // The amount of data buffered is regulated by two variables at construction,
13 // |backward_capacity| and |forward_capacity|.
15 // In the case of reading and seeking forward, the current read position
16 // advances and there will be more data in the backward direction. If backward
17 // bytes exceeds |backward_capacity|, the exceeding bytes are evicted and thus
18 // backward_bytes() will always be less than or equal to |backward_capacity|.
19 // The eviction will be caused by Read() and Seek() in the forward direction and
20 // is done internally when the mentioned criteria is fulfilled.
22 // In the case of appending data to the buffer, there is an advisory limit of
23 // how many bytes can be kept in the forward direction, regulated by
24 // |forward_capacity|. The append operation (by calling Append()) that caused
25 // forward bytes to exceed |forward_capacity| will have a return value that
26 // advises a halt of append operation, further append operations are allowed but
27 // are not advised. Since this class is used as a backend buffer for caching
28 // media files downloaded from network we cannot afford losing data, we can
29 // only advise a halt of further writing to this buffer.
30 // This class is not inherently thread-safe. Concurrent access must be
31 // externally serialized.
33 #ifndef MEDIA_BASE_SEEKABLE_BUFFER_H_
34 #define MEDIA_BASE_SEEKABLE_BUFFER_H_
38 #include "base/basictypes.h"
39 #include "base/memory/ref_counted.h"
40 #include "base/time/time.h"
41 #include "media/base/media_export.h"
47 class MEDIA_EXPORT SeekableBuffer
{
49 // Constructs an instance with |forward_capacity| and |backward_capacity|.
50 // The values are in bytes.
51 SeekableBuffer(int backward_capacity
, int forward_capacity
);
55 // Clears the buffer queue.
58 // Reads a maximum of |size| bytes into |data| from the current read
59 // position. Returns the number of bytes read.
60 // The current read position will advance by the amount of bytes read. If
61 // reading caused backward_bytes() to exceed backward_capacity(), an eviction
62 // of the backward buffer will be done internally.
63 int Read(uint8
* data
, int size
);
65 // Copies up to |size| bytes from current position to |data|. Returns
66 // number of bytes copied. Doesn't advance current position. Optionally
67 // starts at a |forward_offset| from current position.
68 int Peek(uint8
* data
, int size
) { return Peek(data
, size
, 0); }
69 int Peek(uint8
* data
, int size
, int forward_offset
);
71 // Returns pointer to the current chunk of data that is being consumed.
72 // If there is no data left in the buffer false is returned, otherwise
73 // true is returned and |data| and |size| are updated. The returned
74 // |data| value becomes invalid when Read(), Append() or Seek()
76 bool GetCurrentChunk(const uint8
** data
, int* size
) const;
78 // Appends |buffer_in| to this buffer. Returns false if forward_bytes() is
79 // greater than or equals to forward_capacity(), true otherwise. The data
80 // is added to the buffer in any case.
81 bool Append(const scoped_refptr
<DataBuffer
>& buffer_in
);
83 // Appends |size| bytes of |data| to the buffer. Result is the same
84 // as for Append(Buffer*).
85 bool Append(const uint8
* data
, int size
);
87 // Moves the read position by |offset| bytes. If |offset| is positive, the
88 // current read position is moved forward. If negative, the current read
89 // position is moved backward. A zero |offset| value will keep the current
90 // read position stationary.
91 // If |offset| exceeds bytes buffered in either direction, reported by
92 // forward_bytes() when seeking forward and backward_bytes() when seeking
93 // backward, the seek operation will fail and return value will be false.
94 // If the seek operation fails, the current read position will not be updated.
95 // If a forward seeking caused backward_bytes() to exceed backward_capacity(),
96 // this method call will cause an eviction of the backward buffer.
97 bool Seek(int32 offset
);
99 // Returns the number of bytes buffered beyond the current read position.
100 int forward_bytes() const { return forward_bytes_
; }
102 // Returns the number of bytes buffered that precedes the current read
104 int backward_bytes() const { return backward_bytes_
; }
106 // Sets the forward_capacity to |new_forward_capacity| bytes.
107 void set_forward_capacity(int new_forward_capacity
) {
108 forward_capacity_
= new_forward_capacity
;
111 // Sets the backward_capacity to |new_backward_capacity| bytes.
112 void set_backward_capacity(int new_backward_capacity
) {
113 backward_capacity_
= new_backward_capacity
;
116 // Returns the maximum number of bytes that should be kept in the forward
118 int forward_capacity() const { return forward_capacity_
; }
120 // Returns the maximum number of bytes that should be kept in the backward
122 int backward_capacity() const { return backward_capacity_
; }
124 // Returns the current timestamp, taking into account current offset. The
125 // value calculated based on the timestamp of the current buffer. If
126 // timestamp for the current buffer is set to 0 or the data was added with
127 // Append(const uint*, int), then returns value that corresponds to the
128 // last position in a buffer that had timestamp set.
129 // kNoTimestamp() is returned if no buffers we read from had timestamp set.
130 base::TimeDelta
current_time() const { return current_time_
; }
133 // Definition of the buffer queue.
134 typedef std::list
<scoped_refptr
<DataBuffer
> > BufferQueue
;
136 // A helper method to evict buffers in the backward direction until backward
137 // bytes is within the backward capacity.
138 void EvictBackwardBuffers();
140 // An internal method shared by Read() and SeekForward() that actually does
141 // reading. It reads a maximum of |size| bytes into |data|. Returns the number
142 // of bytes read. The current read position will be moved forward by the
143 // number of bytes read. If |data| is NULL, only the current read position
144 // will advance but no data will be copied.
146 uint8
* data
, int size
, bool advance_position
, int forward_offset
);
148 // A helper method that moves the current read position forward by |size|
150 // If the return value is true, the operation completed successfully.
151 // If the return value is false, |size| is greater than forward_bytes() and
152 // the seek operation failed. The current read position is not updated.
153 bool SeekForward(int size
);
155 // A helper method that moves the current read position backward by |size|
157 // If the return value is true, the operation completed successfully.
158 // If the return value is false, |size| is greater than backward_bytes() and
159 // the seek operation failed. The current read position is not updated.
160 bool SeekBackward(int size
);
162 // Updates |current_time_| with the time that corresponds to the
163 // specified position in the buffer.
164 void UpdateCurrentTime(BufferQueue::iterator buffer
, int offset
);
166 BufferQueue::iterator current_buffer_
;
167 BufferQueue buffers_
;
168 int current_buffer_offset_
;
170 int backward_capacity_
;
173 int forward_capacity_
;
176 // Keeps track of the most recent time we've seen in case the |buffers_| is
177 // empty when our owner asks what time it is.
178 base::TimeDelta current_time_
;
180 DISALLOW_COPY_AND_ASSIGN(SeekableBuffer
);
185 #endif // MEDIA_BASE_SEEKABLE_BUFFER_H_