15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SeekableBuffer to support backward and forward seeking in a buffer for 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reading a media data source. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In order to support backward and forward seeking, this class buffers data in 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// both backward and forward directions, the current read position can be reset 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to anywhere in the buffered data. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of data buffered is regulated by two variables at construction, 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |backward_capacity| and |forward_capacity|. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the case of reading and seeking forward, the current read position 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// advances and there will be more data in the backward direction. If backward 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes exceeds |backward_capacity|, the exceeding bytes are evicted and thus 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// backward_bytes() will always be less than or equal to |backward_capacity|. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The eviction will be caused by Read() and Seek() in the forward direction and 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is done internally when the mentioned criteria is fulfilled. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the case of appending data to the buffer, there is an advisory limit of 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// how many bytes can be kept in the forward direction, regulated by 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |forward_capacity|. The append operation (by calling Append()) that caused 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// forward bytes to exceed |forward_capacity| will have a return value that 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// advises a halt of append operation, further append operations are allowed but 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are not advised. Since this class is used as a backend buffer for caching 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// media files downloaded from network we cannot afford losing data, we can 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only advise a halt of further writing to this buffer. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is not inherently thread-safe. Concurrent access must be 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// externally serialized. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_BASE_SEEKABLE_BUFFER_H_ 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_BASE_SEEKABLE_BUFFER_H_ 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/buffers.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DataBuffer; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT SeekableBuffer { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constructs an instance with |forward_capacity| and |backward_capacity|. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The values are in bytes. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SeekableBuffer(int backward_capacity, int forward_capacity); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SeekableBuffer(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clears the buffer queue. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads a maximum of |size| bytes into |data| from the current read 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position. Returns the number of bytes read. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current read position will advance by the amount of bytes read. If 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reading caused backward_bytes() to exceed backward_capacity(), an eviction 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the backward buffer will be done internally. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Read(uint8* data, int size); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copies up to |size| bytes from current position to |data|. Returns 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number of bytes copied. Doesn't advance current position. Optionally 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // starts at a |forward_offset| from current position. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Peek(uint8* data, int size) { return Peek(data, size, 0); } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Peek(uint8* data, int size, int forward_offset); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns pointer to the current chunk of data that is being consumed. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no data left in the buffer false is returned, otherwise 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // true is returned and |data| and |size| are updated. The returned 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |data| value becomes invalid when Read(), Append() or Seek() 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are called. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool GetCurrentChunk(const uint8** data, int* size) const; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Appends |buffer_in| to this buffer. Returns false if forward_bytes() is 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // greater than or equals to forward_capacity(), true otherwise. The data 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is added to the buffer in any case. 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool Append(const scoped_refptr<DataBuffer>& buffer_in); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Appends |size| bytes of |data| to the buffer. Result is the same 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as for Append(Buffer*). 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Append(const uint8* data, int size); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Moves the read position by |offset| bytes. If |offset| is positive, the 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current read position is moved forward. If negative, the current read 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position is moved backward. A zero |offset| value will keep the current 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // read position stationary. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |offset| exceeds bytes buffered in either direction, reported by 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // forward_bytes() when seeking forward and backward_bytes() when seeking 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // backward, the seek operation will fail and return value will be false. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the seek operation fails, the current read position will not be updated. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a forward seeking caused backward_bytes() to exceed backward_capacity(), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this method call will cause an eviction of the backward buffer. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Seek(int32 offset); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the number of bytes buffered beyond the current read position. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int forward_bytes() const { return forward_bytes_; } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the number of bytes buffered that precedes the current read 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int backward_bytes() const { return backward_bytes_; } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the forward_capacity to |new_forward_capacity| bytes. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_forward_capacity(int new_forward_capacity) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forward_capacity_ = new_forward_capacity; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the backward_capacity to |new_backward_capacity| bytes. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_backward_capacity(int new_backward_capacity) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backward_capacity_ = new_backward_capacity; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the maximum number of bytes that should be kept in the forward 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // direction. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int forward_capacity() const { return forward_capacity_; } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the maximum number of bytes that should be kept in the backward 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // direction. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int backward_capacity() const { return backward_capacity_; } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the current timestamp, taking into account current offset. The 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value calculated based on the timestamp of the current buffer. If 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timestamp for the current buffer is set to 0 or the data was added with 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append(const uint*, int), then returns value that corresponds to the 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last position in a buffer that had timestamp set. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kNoTimestamp() is returned if no buffers we read from had timestamp set. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta current_time() const { return current_time_; } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Definition of the buffer queue. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::list<scoped_refptr<DataBuffer> > BufferQueue; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A helper method to evict buffers in the backward direction until backward 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes is within the backward capacity. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EvictBackwardBuffers(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An internal method shared by Read() and SeekForward() that actually does 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reading. It reads a maximum of |size| bytes into |data|. Returns the number 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of bytes read. The current read position will be moved forward by the 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number of bytes read. If |data| is NULL, only the current read position 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will advance but no data will be copied. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int InternalRead( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* data, int size, bool advance_position, int forward_offset); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A helper method that moves the current read position forward by |size| 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the return value is true, the operation completed successfully. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the return value is false, |size| is greater than forward_bytes() and 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the seek operation failed. The current read position is not updated. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SeekForward(int size); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A helper method that moves the current read position backward by |size| 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the return value is true, the operation completed successfully. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the return value is false, |size| is greater than backward_bytes() and 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the seek operation failed. The current read position is not updated. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SeekBackward(int size); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates |current_time_| with the time that corresponds to the 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified position in the buffer. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateCurrentTime(BufferQueue::iterator buffer, int offset); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue::iterator current_buffer_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BufferQueue buffers_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_buffer_offset_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int backward_capacity_; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int backward_bytes_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int forward_capacity_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int forward_bytes_; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keeps track of the most recent time we've seen in case the |buffers_| is 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // empty when our owner asks what time it is. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta current_time_; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SeekableBuffer); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // MEDIA_BASE_SEEKABLE_BUFFER_H_ 185