Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: media/filters/audio_renderer_base.cc

Issue 155695: Replace the guts of AudioRendererBase with calls to scaling algorithm. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/audio_renderer_base.h ('k') | media/filters/audio_renderer_base_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/audio_renderer_base.cc
===================================================================
--- media/filters/audio_renderer_base.cc (revision 22189)
+++ media/filters/audio_renderer_base.cc (working copy)
@@ -2,34 +2,24 @@
// 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_base.h"
+
#include <algorithm>
#include "media/base/filter_host.h"
-#include "media/filters/audio_renderer_base.h"
+#include "media/filters/audio_renderer_algorithm_ola.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 AudioRendererBase::kDefaultMaxQueueSize = 16;
-
-AudioRendererBase::AudioRendererBase(size_t max_queue_size)
- : max_queue_size_(max_queue_size),
- data_offset_(0),
- state_(kUninitialized),
+AudioRendererBase::AudioRendererBase()
+ : state_(kUninitialized),
pending_reads_(0) {
}
AudioRendererBase::~AudioRendererBase() {
- // Stop() should have been called and OnReadComplete() should have stopped
- // enqueuing data.
+ // Stop() should have been called and |algorithm_| should have been destroyed.
DCHECK(state_ == kUninitialized || state_ == kStopped);
- DCHECK(queue_.empty());
+ DCHECK(!algorithm_.get());
}
void AudioRendererBase::Play(FilterCallback* callback) {
@@ -57,10 +47,9 @@
void AudioRendererBase::Stop() {
OnStop();
-
AutoLock auto_lock(lock_);
state_ = kStopped;
- queue_.clear();
+ algorithm_.reset(NULL);
}
void AudioRendererBase::Seek(base::TimeDelta time, FilterCallback* callback) {
@@ -72,11 +61,9 @@
// Throw away everything and schedule our reads.
last_fill_buffer_time_ = base::TimeDelta();
- queue_.clear();
- data_offset_ = 0;
- for (size_t i = 0; i < max_queue_size_; ++i) {
- ScheduleRead_Locked();
- }
+
+ // |algorithm_| will request more reads.
+ algorithm_->FlushBuffers();
}
void AudioRendererBase::Initialize(AudioDecoder* decoder,
@@ -94,6 +81,34 @@
return;
}
+ // Get the media properties to initialize our algorithms.
+ int channels = 0;
+ int sample_rate = 0;
+ int sample_bits = 0;
+ bool ret = ParseMediaFormat(decoder_->media_format(),
+ &channels,
+ &sample_rate,
+ &sample_bits);
+
+ // We should have successfully parsed the media format, or we would not have
+ // been created.
+ DCHECK(ret);
+
+ // Create a callback so our algorithm can request more reads.
+ AudioRendererAlgorithmBase::RequestReadCallback* cb =
+ NewCallback(this, &AudioRendererBase::ScheduleRead_Locked);
+
+ // Construct the algorithm.
+ algorithm_.reset(new AudioRendererAlgorithmOLA());
+
+ // Initialize our algorithm with media properties, initial playback rate
+ // (may be 0), and a callback to request more reads from the data source.
+ algorithm_->Initialize(channels,
+ sample_rate,
+ sample_bits,
+ GetPlaybackRate(),
+ cb);
+
// Finally, execute the start callback.
state_ = kPaused;
callback->Run();
@@ -105,18 +120,14 @@
DCHECK_GT(pending_reads_, 0u);
--pending_reads_;
- // If we have stopped don't enqueue, same for end of stream buffer since
- // it has no data.
- if (!buffer_in->IsEndOfStream()) {
- queue_.push_back(buffer_in);
- DCHECK(queue_.size() <= max_queue_size_);
- }
+ // Note: Calling this may schedule more reads.
+ algorithm_->EnqueueBuffer(buffer_in);
// Check for our preroll complete condition.
if (state_ == kSeeking) {
DCHECK(seek_callback_.get());
- if (queue_.size() == max_queue_size_ || buffer_in->IsEndOfStream()) {
- // Transition into paused whether we have data in |queue_| or not.
+ if (algorithm_->IsQueueFull() || buffer_in->IsEndOfStream()) {
+ // Transition into paused whether we have data in |algorithm_| or not.
// FillBuffer() will play silence if there's nothing to fill.
state_ = kPaused;
seek_callback_->Run();
@@ -131,16 +142,13 @@
}
}
-// TODO(scherkus): clean up FillBuffer().. it's overly complex!!
size_t AudioRendererBase::FillBuffer(uint8* dest,
size_t dest_len,
- float rate,
const base::TimeDelta& playback_delay) {
- size_t dest_written = 0;
-
// The timestamp of the last buffer written during the last call to
// FillBuffer().
base::TimeDelta last_fill_buffer_time;
+ size_t dest_written = 0;
{
AutoLock auto_lock(lock_);
@@ -160,89 +168,16 @@
last_fill_buffer_time = last_fill_buffer_time_;
last_fill_buffer_time_ = base::TimeDelta();
- // Loop until the buffer has been filled.
- while (dest_len > 0 && !queue_.empty()) {
- scoped_refptr<Buffer> buffer = queue_.front();
+ // Do the fill.
+ dest_written = algorithm_->FillBuffer(dest, dest_len);
- // Determine how much to copy.
- DCHECK_LE(data_offset_, buffer->GetDataSize());
- const uint8* data = buffer->GetData() + data_offset_;
- size_t data_len = buffer->GetDataSize() - data_offset_;
-
- // New scaled packet size aligned to 16 to ensure it's on a
- // channel/sample boundary. Only guaranteed to work for power of 2
- // number of channels and sample size.
- size_t scaled_data_len = (rate <= 0.0f) ? 0 :
- static_cast<size_t>(data_len / rate) & ~15;
- if (scaled_data_len > dest_len) {
- data_len = (data_len * dest_len / scaled_data_len) & ~15;
- scaled_data_len = dest_len;
- }
-
- // Handle playback rate in three different cases:
- // 1. If rate >= 1.0
- // Speed up the playback, we copy partial amount of decoded samples
- // into target buffer.
- // 2. If 0.5 <= rate < 1.0
- // Slow down the playback, duplicate the decoded samples to fill a
- // larger size of target buffer.
- // 3. If rate < 0.5
- // Playback is too slow, simply mute the audio.
- // TODO(hclam): the logic for handling playback rate is too complex and
- // is not careful enough. I should do some bounds checking and even better
- // replace this with a better/clearer implementation.
- if (rate >= 1.0f) {
- memcpy(dest, data, scaled_data_len);
- } else if (rate >= 0.5) {
- memcpy(dest, data, data_len);
- memcpy(dest + data_len, data, scaled_data_len - data_len);
- } else {
- memset(dest, 0, data_len);
- }
- dest += scaled_data_len;
- dest_len -= scaled_data_len;
- dest_written += scaled_data_len;
-
- data_offset_ += data_len;
-
- if (rate == 0.0f) {
- dest_written = 0;
- break;
- }
-
- // Check to see if we're finished with the front buffer.
- if (buffer->GetDataSize() - data_offset_ < 16) {
- // Update the time. If this is the last buffer in the queue, we'll
- // drop out of the loop before len == 0, so we need to always update
- // the time here.
- if (buffer->GetTimestamp().InMicroseconds() > 0) {
- last_fill_buffer_time_ = buffer->GetTimestamp() +
- buffer->GetDuration();
- }
-
- // Dequeue the buffer and request another.
- queue_.pop_front();
- ScheduleRead_Locked();
-
- // Reset our offset into the front buffer.
- data_offset_ = 0;
- } else {
- // If we're done with the read, compute the time.
- // Integer divide so multiply before divide to work properly.
- int64 us_written = (buffer->GetDuration().InMicroseconds() *
- data_offset_) / buffer->GetDataSize();
-
- if (buffer->GetTimestamp().InMicroseconds() > 0) {
- last_fill_buffer_time_ =
- buffer->GetTimestamp() +
- base::TimeDelta::FromMicroseconds(us_written);
- }
- }
- }
+ // Get the current time.
+ last_fill_buffer_time_ = algorithm_->GetTime();
}
// Update the pipeline's time if it was set last time.
- if (last_fill_buffer_time.InMicroseconds() > 0) {
+ if (last_fill_buffer_time.InMicroseconds() > 0 &&
+ last_fill_buffer_time != last_fill_buffer_time_) {
// Adjust the |last_fill_buffer_time| with the playback delay.
// TODO(hclam): If there is a playback delay, the pipeline would not be
// updated with a correct timestamp when the stream is played at the very
@@ -259,7 +194,6 @@
void AudioRendererBase::ScheduleRead_Locked() {
lock_.AssertAcquired();
- DCHECK_LT(pending_reads_, max_queue_size_);
++pending_reads_;
decoder_->Read(NewCallback(this, &AudioRendererBase::OnReadComplete));
}
@@ -278,4 +212,12 @@
mime_type.compare(mime_type::kUncompressedAudio) == 0;
}
+void AudioRendererBase::SetPlaybackRate(float playback_rate) {
+ algorithm_->set_playback_rate(playback_rate);
+}
+
+float AudioRendererBase::GetPlaybackRate() {
+ return algorithm_->playback_rate();
+}
+
} // namespace media
« no previous file with comments | « media/filters/audio_renderer_base.h ('k') | media/filters/audio_renderer_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698