summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorkylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 23:26:26 +0000
committerkylep@chromium.org <kylep@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 23:26:26 +0000
commit9a9c25c6fbbf231a4271165c30074fb847ea5a5d (patch)
tree245c2572021705ba49b8b4c654a05cc3f8a4649b /media
parent143f5f41c37362350380185fadc2f1a6021fabd2 (diff)
downloadchromium_src-9a9c25c6fbbf231a4271165c30074fb847ea5a5d.zip
chromium_src-9a9c25c6fbbf231a4271165c30074fb847ea5a5d.tar.gz
chromium_src-9a9c25c6fbbf231a4271165c30074fb847ea5a5d.tar.bz2
Draft of base and default algorithm class for AudioRendererBase refactor.
Review URL: http://codereview.chromium.org/118395 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18876 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/filters/audio_renderer_algorithm_base.cc69
-rw-r--r--media/filters/audio_renderer_algorithm_base.h109
-rw-r--r--media/filters/audio_renderer_algorithm_default.cc77
-rw-r--r--media/filters/audio_renderer_algorithm_default.h36
-rw-r--r--media/media.gyp4
5 files changed, 295 insertions, 0 deletions
diff --git a/media/filters/audio_renderer_algorithm_base.cc b/media/filters/audio_renderer_algorithm_base.cc
new file mode 100644
index 0000000..5a521cb
--- /dev/null
+++ b/media/filters/audio_renderer_algorithm_base.cc
@@ -0,0 +1,69 @@
+// 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.
+
+#include "media/filters/audio_renderer_algorithm_base.h"
+
+namespace media {
+
+// The maximum size of the queue, which also acts as the number of initial reads
+// to perform for buffering. The size of the queue should never exceed this
+// number since we read only after we've dequeued and released a buffer in
+// callback thread.
+//
+// This is sort of a magic number, but for 44.1kHz stereo audio this will give
+// us enough data to fill approximately 4 complete callback buffers.
+const size_t kDefaultMaxQueueSize = 16;
+
+AudioRendererAlgorithmBase::AudioRendererAlgorithmBase()
+ : channels_(0),
+ sample_rate_(0),
+ sample_bits_(0),
+ playback_rate_(0.0f),
+ expected_queue_size_(0) {
+}
+
+AudioRendererAlgorithmBase::~AudioRendererAlgorithmBase() {}
+
+void AudioRendererAlgorithmBase::Initialize(int channels,
+ int sample_rate,
+ int sample_bits,
+ float initial_playback_rate,
+ RequestReadCallback* callback) {
+ DCHECK_GT(channels, 0);
+ DCHECK_GT(sample_rate, 0);
+ DCHECK_GT(sample_bits, 0);
+ DCHECK_GE(initial_playback_rate, 0.0);
+ DCHECK(callback);
+
+ channels_ = channels;
+ sample_rate_ = sample_rate;
+ sample_bits_ = sample_bits;
+ playback_rate_ = initial_playback_rate;
+ request_read_callback_.reset(callback);
+ FillQueue();
+}
+
+void AudioRendererAlgorithmBase::FlushBuffers() {
+ // Clear the queue of decoded packets (releasing the buffers).
+ queue_.clear();
+}
+
+void AudioRendererAlgorithmBase::EnqueueBuffer(Buffer* buffer_in) {
+ // If we're at end of stream, |buffer_in| contains no data.
+ if (!buffer_in->IsEndOfStream()) {
+ queue_.push_back(buffer_in);
+ DCHECK_LE(queue_.size(), kDefaultMaxQueueSize);
+ }
+}
+
+void AudioRendererAlgorithmBase::SetPlaybackRate(float new_rate) {
+ playback_rate_ = new_rate;
+}
+
+void AudioRendererAlgorithmBase::FillQueue() {
+ for ( ; expected_queue_size_ < kDefaultMaxQueueSize; ++expected_queue_size_)
+ request_read_callback_->Run();
+}
+
+} // namespace media
diff --git a/media/filters/audio_renderer_algorithm_base.h b/media/filters/audio_renderer_algorithm_base.h
new file mode 100644
index 0000000..4b0aec3
--- /dev/null
+++ b/media/filters/audio_renderer_algorithm_base.h
@@ -0,0 +1,109 @@
+// 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.
+
+// AudioRendererAlgorithmBase provides an interface for algorithms that
+// modify playback speed. ARAB owns its own deque of Buffers because
+// subclasses may need more than one to produce output. Subclasses
+// must implement the following method:
+//
+// Process() - fills the buffer passed to it & returns how many bytes copied.
+//
+// Subclasses must also decrement |expected_queue_size_| after a dequeue.
+//
+// The general assumption is that the owner of this class will provide us with
+// Buffers and a playback speed, and we will fill an output buffer when our
+// owner requests it. If we needs more Buffers, we will query our owner via
+// a callback passed during construction. This should be a nonblocking call.
+// When the owner has a Buffer ready for us, it calls EnqueueBuffer().
+//
+// Exectution of ARAB is thread-unsafe. This class should be used as
+// the guts of AudioRendererBase, which should lock calls into us so
+// enqueues and processes do not cause an unpredictable |queue_| size.
+//
+// Most of ARAB is nonvirtual as the only subclasses we expect are those to
+// define Process(). |queue_| management and common property management
+// should not have to change for subclasses, so both are implemented here
+// non-virtually.
+
+// TODO(kylep): Clean this whole class up. Refactor out the |queue_| into a
+// QueueManager or something like that.
+
+#ifndef MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_
+#define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_
+
+#include <deque>
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "media/base/data_buffer.h"
+#include "media/base/buffers.h"
+
+namespace media {
+
+class AudioRendererAlgorithmBase {
+ public:
+ // Used to simplify callback declarations.
+ typedef Callback0::Type RequestReadCallback;
+
+ AudioRendererAlgorithmBase();
+ virtual ~AudioRendererAlgorithmBase();
+
+ // Checks validity of audio parameters and takes ownership of |callback|.
+ virtual void Initialize(int channels,
+ int sample_rate,
+ int sample_bits,
+ float initial_playback_rate,
+ RequestReadCallback* callback);
+
+ // Implement this strategy method in derived classes.
+ // Fills |buffer_out| with possibly scaled data from our |queue_|.
+ // |buffer_out| must be initialized and have a datasize.
+ // Returns the number of bytes copied into |buffer_out|.
+ // TODO(kylep): Think of a better name.
+ virtual size_t Process(DataBuffer* buffer_out) = 0;
+
+ // Clears |queue_|.
+ void FlushBuffers();
+
+ // Enqueues a buffer. It is called from the owner
+ // of the algorithm after a read completes.
+ void EnqueueBuffer(Buffer* buffer_in);
+
+ // Sets the playback rate.
+ void SetPlaybackRate(float new_rate);
+
+ protected:
+ // Fills the |queue_|. This is a helper function called from
+ // Initialize() to initially fill |queue_| and from subclasses'
+ // Process() method to refill |queue_| after buffers have been used.
+ void FillQueue();
+
+ // Audio properties.
+ int channels_;
+ int sample_rate_;
+ int sample_bits_;
+
+ // Used by algorithm to scale output.
+ float playback_rate_;
+
+ // Used to request more data.
+ scoped_ptr<RequestReadCallback> request_read_callback_;
+
+ // Keeps track of the number of buffers we will have in |queue_|
+ // after all reads complete. Subclasses MUST decrement this after
+ // dequeuing.
+ size_t expected_queue_size_;
+
+ // Queued audio data.
+ typedef std::deque< scoped_refptr<Buffer> > BufferQueue;
+ BufferQueue queue_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmBase);
+};
+
+} // namespace media
+
+#endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_BASE_H_
diff --git a/media/filters/audio_renderer_algorithm_default.cc b/media/filters/audio_renderer_algorithm_default.cc
new file mode 100644
index 0000000..3b46af5
--- /dev/null
+++ b/media/filters/audio_renderer_algorithm_default.cc
@@ -0,0 +1,77 @@
+// 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.
+
+#include "media/filters/audio_renderer_algorithm_default.h"
+
+namespace media {
+
+AudioRendererAlgorithmDefault::AudioRendererAlgorithmDefault()
+ : data_offset_(0) {
+}
+
+AudioRendererAlgorithmDefault::~AudioRendererAlgorithmDefault() {
+}
+
+size_t AudioRendererAlgorithmDefault::Process(DataBuffer* buffer_out) {
+ size_t dest_written = 0;
+ if (playback_rate_ == 0.0f) {
+ return 0;
+ }
+ if (playback_rate_ == 1.0f) {
+ size_t dest_length = buffer_out->GetDataSize();
+ uint8* dest = buffer_out->GetWritableData(dest_length);
+ while (dest_length > 0 && !queue_.empty()) {
+ scoped_refptr<Buffer> buffer = queue_.front();
+ size_t data_length = buffer->GetDataSize() - data_offset_;
+
+ // Prevent writing past end of the buffer.
+ if (data_length > dest_length)
+ data_length = dest_length;
+ memcpy(dest, buffer->GetData() + data_offset_, data_length);
+ dest += data_length;
+ dest_length -= data_length;
+ dest_written += data_length;
+
+ data_offset_ += data_length;
+
+ // We should not have run over the end of the buffer.
+ DCHECK_GE(buffer->GetDataSize(), data_offset_);
+ // but if we've reached the end, dequeue it.
+ if (buffer->GetDataSize() - data_offset_ == 0) {
+ queue_.pop_front();
+ data_offset_ = 0;
+ }
+ }
+ } else {
+ // Mute (we will write to the whole buffer, so set |dest_written|
+ // to the requested size).
+ dest_written = buffer_out->GetDataSize();
+ memset(buffer_out->GetWritableData(dest_written), 0, dest_written);
+
+ // Discard any buffers that should be "used".
+ size_t scaled_dest_length_remaining =
+ static_cast<size_t>(dest_written * playback_rate_);
+ while (scaled_dest_length_remaining > 0 && !queue_.empty()) {
+ size_t data_length = queue_.front()->GetDataSize() - data_offset_;
+
+ // Last buffer we need.
+ if (data_length > scaled_dest_length_remaining) {
+ data_offset_ += scaled_dest_length_remaining;
+ } else {
+ scaled_dest_length_remaining -= data_length;
+ queue_.pop_front();
+ data_offset_ = 0;
+ }
+ }
+ // If we ran out, don't report we used more than we did.
+ if (queue_.empty()) {
+ dest_written -=
+ static_cast<size_t>(scaled_dest_length_remaining / playback_rate_);
+ }
+ }
+ FillQueue();
+ return dest_written;
+}
+
+} // namespace media
diff --git a/media/filters/audio_renderer_algorithm_default.h b/media/filters/audio_renderer_algorithm_default.h
new file mode 100644
index 0000000..073c83b
--- /dev/null
+++ b/media/filters/audio_renderer_algorithm_default.h
@@ -0,0 +1,36 @@
+// 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.
+
+// AudioRendererAlgorithmDefault is the default implementation of
+// AudioRendererAlgorithmBase. For speeds other than 1.0f, Process() fills
+// |buffer_out| with 0s and returns the expected size. As ARAB is
+// thread-unsafe, so is ARAD.
+
+#ifndef MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_DEFAULT_H_
+#define MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_DEFAULT_H_
+
+#include "base/time.h"
+#include "media/base/data_buffer.h"
+#include "media/filters/audio_renderer_algorithm_base.h"
+
+namespace media {
+
+class AudioRendererAlgorithmDefault : public AudioRendererAlgorithmBase {
+ public:
+ AudioRendererAlgorithmDefault();
+ virtual ~AudioRendererAlgorithmDefault();
+
+ // AudioRendererAlgorithmBase implementation
+ virtual size_t Process(DataBuffer* buffer_out);
+
+ private:
+ // Remembers the amount of remaining audio data for the front buffer.
+ size_t data_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioRendererAlgorithmDefault);
+};
+
+} // namespace media
+
+#endif // MEDIA_FILTERS_AUDIO_RENDERER_ALGORITHM_DEFAULT_H_
diff --git a/media/media.gyp b/media/media.gyp
index e3f3b3a..d5c1a3d 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -72,6 +72,10 @@
'base/yuv_row_mac.cc',
'base/yuv_row_linux.cc',
'base/yuv_row.h',
+ 'filters/audio_renderer_algorithm_base.cc',
+ 'filters/audio_renderer_algorithm_base.h',
+ 'filters/audio_renderer_algorithm_default.cc',
+ 'filters/audio_renderer_algorithm_default.h',
'filters/audio_renderer_base.cc',
'filters/audio_renderer_base.h',
'filters/audio_renderer_impl.cc',