diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-19 00:26:39 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-19 00:26:39 +0000 |
commit | c029795f77cf332b95a2966af82dd2fe256649bb (patch) | |
tree | 93839cb805b9630ecfe10e73b813f677337936bc /media/base/seekable_buffer.h | |
parent | 2248044b2b21b8e9803aa56cad2a48b1bfb66924 (diff) | |
download | chromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.zip chromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.tar.gz chromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.tar.bz2 |
SeekableBuffer to implement a window of buffer which has short seeking ability.
Defined the base interface SeekableBuffer and a thread safe implemntation of
ThreadSafeSeekableBuffer. This class is to be used for media resource loading
that does the meat of buffer queueing and handles short seeking for short distance
out-of-order read patterns.
Review URL: http://codereview.chromium.org/113213
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16348 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/seekable_buffer.h')
-rw-r--r-- | media/base/seekable_buffer.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/media/base/seekable_buffer.h b/media/base/seekable_buffer.h new file mode 100644 index 0000000..7360bfd --- /dev/null +++ b/media/base/seekable_buffer.h @@ -0,0 +1,132 @@ +// Copyright (c) 2009 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. + +// SeekableBuffer to support backward and forward seeking in a buffer for +// reading a media data source. +// +// In order to support backward and forward seeking, this class buffers data in +// both backward and forward directions, the current read position can be reset +// to anywhere in the buffered data. +// +// The amount of data buffered is regulated by two variables at construction, +// |backward_capacity| and |forward_capacity|. +// +// In the case of reading and seeking forward, the current read position +// advances and there will be more data in the backward direction. If backward +// bytes exceeds |backward_capacity|, the exceeding bytes are evicted and thus +// backward_bytes() will always be less than or equal to |backward_capacity|. +// The eviction will be caused by Read() and Seek() in the forward direction and +// is done internally when the mentioned criteria is fulfilled. +// +// In the case of appending data to the buffer, there is an advisory limit of +// how many bytes can be kept in the forward direction, regulated by +// |forward_capacity|. The append operation (by calling Append()) that caused +// forward bytes to exceed |forward_capacity| will have a return value that +// advises a halt of append operation, further append operations are allowed but +// are not advised. Since this class is used as a backend buffer for caching +// media files downloaded from network we cannot afford losing data, we can +// only advise a halt of further writing to this buffer. +// This class is not inherently thread-safe. Concurrent access must be +// externally serialized. + +#ifndef MEDIA_BASE_SEEKABLE_BUFFER_H_ +#define MEDIA_BASE_SEEKABLE_BUFFER_H_ + +#include <list> + +#include "base/basictypes.h" +#include "base/lock.h" +#include "base/scoped_ptr.h" + +namespace media { + +class SeekableBuffer { + public: + // Construct an instance with forward capacity of |forward_capacity| + // and backward capacity of |backward_capacity|. The values are in bytes. + SeekableBuffer(size_t backward_capacity, size_t forward_capacity); + + ~SeekableBuffer(); + + // Read a maximum of |size| bytes into |buffer| from the current read + // position. Return the number of bytes read. + // The current read position will advances by the amount of bytes read. If + // reading caused backward bytes to exceed backward_capacity(), an eviction + // of backward buffer will be done internally. + size_t Read(size_t size, uint8* buffer); + + // Append |data| with |size| bytes to this buffer. If this buffer becomes full + // or is already full then return false, otherwise true. + // Append operations are always successful, a return value of false only means + // that there's more forward bytes than the capacity, data is still in this + // buffer, but user is advised not to write any more. + bool Append(size_t size, const uint8* data); + + // Move the read position by an offset of |offset| bytes. If |offset| is + // positive, the current read position is moved forward. If negative, the + // current read position is moved backward. A zero |offset| value will keep + // the current read position stationary. + // If |offset| exceeds bytes buffered in either direction, reported by + // forward_bytes() when seeking forward and backward_bytes() when seeking + // backward, the seek operation will fail and return value will be false. + // If the seek operation fails, the current read position will not be updated. + // If a forward seeking caused backward bytes to exceed backward_capacity(), + // this method call will cause an eviction of backward buffer. + bool Seek(int32 offset); + + // Returns the number of bytes buffered beyond the current read position. + size_t forward_bytes() const { return forward_bytes_; } + + // Returns the number of bytes buffered that precedes the current read + // position. + size_t backward_bytes() const { return backward_bytes_; } + + // Returns the maximum number of bytes that should be kept in the forward + // direction. + size_t forward_capacity() const { return forward_capacity_; } + + // Returns the maximum number of bytes that should be kept in the backward + // direction. + size_t backward_capacity() const { return backward_capacity_; } + + private: + // A helper method to evict buffers in the backward direction until backward + // bytes is within the backward capacity. + void EvictBackwardBuffers(); + + // An internal method shared by Read() and SeekForward() that actually does + // reading. It reads a maximum of |size| bytes into |data|. Returns the number + // of bytes read. The current read position will be moved forward by the + // number of bytes read. If |data| is NULL, only the current read position + // will advance but no data will be copied. + size_t InternalRead(size_t size, uint8* data); + + bool SeekForward(size_t size); + + bool SeekBackward(size_t size); + + // A structure that contains a block of data. + struct Buffer { + explicit Buffer(size_t len) : data(new uint8[len]), size(len) {} + // Pointer to data. + scoped_array<uint8> data; + // Size of this block. + size_t size; + }; + + typedef std::list<Buffer*> BufferQueue; + BufferQueue::iterator current_buffer_; + BufferQueue buffers_; + size_t current_buffer_offset_; + + size_t backward_capacity_; + size_t backward_bytes_; + + size_t forward_capacity_; + size_t forward_bytes_; +}; + +} // namespace media + +#endif // MEDIA_BASE_SEEKABLE_BUFFER_H_ |