Home | History | Annotate | Download | only in base
      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.
     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.
     99   int forward_bytes() const { return forward_bytes_; }
    100 
    101   // Returns the number of bytes buffered that precedes the current read
    102   // position.
    103   int backward_bytes() const { return backward_bytes_; }
    104 
    105   // Sets the forward_capacity to |new_forward_capacity| bytes.
    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.
    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.
    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.
    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.
    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