summaryrefslogtreecommitdiffstats
path: root/media/base/seekable_buffer.h
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-19 00:26:39 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-19 00:26:39 +0000
commitc029795f77cf332b95a2966af82dd2fe256649bb (patch)
tree93839cb805b9630ecfe10e73b813f677337936bc /media/base/seekable_buffer.h
parent2248044b2b21b8e9803aa56cad2a48b1bfb66924 (diff)
downloadchromium_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.h132
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_