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. 4 5 // SeekableBuffer to support backward and forward seeking in a buffer for 6 // reading a media data source. 7 // 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. 11 // 12 // The amount of data buffered is regulated by two variables at construction, 13 // |backward_capacity| and |forward_capacity|. 14 // 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. 21 // 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. 32 33 #ifndef MEDIA_BASE_SEEKABLE_BUFFER_H_ 34 #define MEDIA_BASE_SEEKABLE_BUFFER_H_ 35 36 #include <list> 37 38 #include "base/basictypes.h" 39 #include "base/memory/ref_counted.h" 40 #include "media/base/buffers.h" 41 42 namespace media { 43 44 class DataBuffer; 45 46 class MEDIA_EXPORT SeekableBuffer { 47 public: 48 // Constructs an instance with |forward_capacity| and |backward_capacity|. 49 // The values are in bytes. 50 SeekableBuffer(int backward_capacity, int forward_capacity); 51 52 ~SeekableBuffer(); 53 54 // Clears the buffer queue. 55 void Clear(); 56 57 // Reads a maximum of |size| bytes into |data| from the current read 58 // position. Returns the number of bytes read. 59 // The current read position will advance by the amount of bytes read. If 60 // reading caused backward_bytes() to exceed backward_capacity(), an eviction 61 // of the backward buffer will be done internally. 62 int Read(uint8* data, int size); 63 64 // Copies up to |size| bytes from current position to |data|. Returns 65 // number of bytes copied. Doesn't advance current position. Optionally 66 // starts at a |forward_offset| from current position. Peek(uint8 * data,int size)67 int Peek(uint8* data, int size) { return Peek(data, size, 0); } 68 int Peek(uint8* data, int size, int forward_offset); 69 70 // Returns pointer to the current chunk of data that is being consumed. 71 // If there is no data left in the buffer false is returned, otherwise 72 // true is returned and |data| and |size| are updated. The returned 73 // |data| value becomes invalid when Read(), Append() or Seek() 74 // are called. 75 bool GetCurrentChunk(const uint8** data, int* size) const; 76 77 // Appends |buffer_in| to this buffer. Returns false if forward_bytes() is 78 // greater than or equals to forward_capacity(), true otherwise. The data 79 // is added to the buffer in any case. 80 bool Append(const scoped_refptr<DataBuffer>& buffer_in); 81 82 // Appends |size| bytes of |data| to the buffer. Result is the same 83 // as for Append(Buffer*). 84 bool Append(const uint8* data, int size); 85 86 // Moves the read position by |offset| bytes. If |offset| is positive, the 87 // current read position is moved forward. If negative, the current read 88 // position is moved backward. A zero |offset| value will keep the current 89 // read position stationary. 90 // If |offset| exceeds bytes buffered in either direction, reported by 91 // forward_bytes() when seeking forward and backward_bytes() when seeking 92 // backward, the seek operation will fail and return value will be false. 93 // If the seek operation fails, the current read position will not be updated. 94 // If a forward seeking caused backward_bytes() to exceed backward_capacity(), 95 // this method call will cause an eviction of the backward buffer. 96 bool Seek(int32 offset); 97 98 // Returns the number of bytes buffered beyond the current read position. forward_bytes()99 int forward_bytes() const { return forward_bytes_; } 100 101 // Returns the number of bytes buffered that precedes the current read 102 // position. backward_bytes()103 int backward_bytes() const { return backward_bytes_; } 104 105 // Sets the forward_capacity to |new_forward_capacity| bytes. set_forward_capacity(int new_forward_capacity)106 void set_forward_capacity(int new_forward_capacity) { 107 forward_capacity_ = new_forward_capacity; 108 } 109 110 // Sets the backward_capacity to |new_backward_capacity| bytes. set_backward_capacity(int new_backward_capacity)111 void set_backward_capacity(int new_backward_capacity) { 112 backward_capacity_ = new_backward_capacity; 113 } 114 115 // Returns the maximum number of bytes that should be kept in the forward 116 // direction. forward_capacity()117 int forward_capacity() const { return forward_capacity_; } 118 119 // Returns the maximum number of bytes that should be kept in the backward 120 // direction. backward_capacity()121 int backward_capacity() const { return backward_capacity_; } 122 123 // Returns the current timestamp, taking into account current offset. The 124 // value calculated based on the timestamp of the current buffer. If 125 // timestamp for the current buffer is set to 0 or the data was added with 126 // Append(const uint*, int), then returns value that corresponds to the 127 // last position in a buffer that had timestamp set. 128 // kNoTimestamp() is returned if no buffers we read from had timestamp set. current_time()129 base::TimeDelta current_time() const { return current_time_; } 130 131 private: 132 // Definition of the buffer queue. 133 typedef std::list<scoped_refptr<DataBuffer> > BufferQueue; 134 135 // A helper method to evict buffers in the backward direction until backward 136 // bytes is within the backward capacity. 137 void EvictBackwardBuffers(); 138 139 // An internal method shared by Read() and SeekForward() that actually does 140 // reading. It reads a maximum of |size| bytes into |data|. Returns the number 141 // of bytes read. The current read position will be moved forward by the 142 // number of bytes read. If |data| is NULL, only the current read position 143 // will advance but no data will be copied. 144 int InternalRead( 145 uint8* data, int size, bool advance_position, int forward_offset); 146 147 // A helper method that moves the current read position forward by |size| 148 // bytes. 149 // If the return value is true, the operation completed successfully. 150 // If the return value is false, |size| is greater than forward_bytes() and 151 // the seek operation failed. The current read position is not updated. 152 bool SeekForward(int size); 153 154 // A helper method that moves the current read position backward by |size| 155 // bytes. 156 // If the return value is true, the operation completed successfully. 157 // If the return value is false, |size| is greater than backward_bytes() and 158 // the seek operation failed. The current read position is not updated. 159 bool SeekBackward(int size); 160 161 // Updates |current_time_| with the time that corresponds to the 162 // specified position in the buffer. 163 void UpdateCurrentTime(BufferQueue::iterator buffer, int offset); 164 165 BufferQueue::iterator current_buffer_; 166 BufferQueue buffers_; 167 int current_buffer_offset_; 168 169 int backward_capacity_; 170 int backward_bytes_; 171 172 int forward_capacity_; 173 int forward_bytes_; 174 175 // Keeps track of the most recent time we've seen in case the |buffers_| is 176 // empty when our owner asks what time it is. 177 base::TimeDelta current_time_; 178 179 DISALLOW_COPY_AND_ASSIGN(SeekableBuffer); 180 }; 181 182 } // namespace media 183 184 #endif // MEDIA_BASE_SEEKABLE_BUFFER_H_ 185