summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-24 18:00:32 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-24 18:00:32 +0000
commit1328d55d94cf7b973da1a0a884735c8cbdeb2423 (patch)
treebbd05bc64668be46fc3804b8ce46d59ac8b44769 /media
parent21f659de19e3ea874a0958372a311746a0e764c2 (diff)
downloadchromium_src-1328d55d94cf7b973da1a0a884735c8cbdeb2423.zip
chromium_src-1328d55d94cf7b973da1a0a884735c8cbdeb2423.tar.gz
chromium_src-1328d55d94cf7b973da1a0a884735c8cbdeb2423.tar.bz2
Providing unplayed bytes in audio hardware buffer
BUG=20007 TEST=WinAudioTest.PCMWaveStreamPendingBytes We used to guess what is in the hardware audio buffer to perform audio sync. But due the triple buffering and other platforms has other buffering scheme we need to be able to know how many bytes are left in the hardware buffer. We provide this data via AudioCallback::OnMoreData(), so we can predict when the requested buffer will be played. Review URL: http://codereview.chromium.org/174243 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24114 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/audio_output.h6
-rw-r--r--media/audio/fake_audio_output_stream.cc2
-rw-r--r--media/audio/linux/alsa_output.cc8
-rw-r--r--media/audio/linux/alsa_output.h3
-rw-r--r--media/audio/linux/alsa_output_unittest.cc8
-rw-r--r--media/audio/mac/audio_output_mac.cc4
-rw-r--r--media/audio/mac/audio_output_mac_unittest.cc2
-rw-r--r--media/audio/simple_sources.cc8
-rw-r--r--media/audio/simple_sources.h8
-rw-r--r--media/audio/simple_sources_unittest.cc2
-rw-r--r--media/audio/win/audio_output_win_unittest.cc76
-rw-r--r--media/audio/win/waveout_output_win.cc18
-rw-r--r--media/audio/win/waveout_output_win.h3
-rw-r--r--media/filters/audio_renderer_impl.cc11
-rw-r--r--media/filters/audio_renderer_impl.h4
15 files changed, 126 insertions, 37 deletions
diff --git a/media/audio/audio_output.h b/media/audio/audio_output.h
index f27858b..e6a1ee5 100644
--- a/media/audio/audio_output.h
+++ b/media/audio/audio_output.h
@@ -53,8 +53,10 @@ class AudioOutputStream {
// buffer size is usually what is specified in Open(). The source
// will return the number of bytes it filled. The expected structure of
// |dest| is platform and format specific.
- virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) = 0;
+ // |pending_bytes| is the number of bytes will be played before the
+ // requested data is played.
+ virtual size_t OnMoreData(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes) = 0;
// The stream is done with this callback. After this call the audio source
// can go away or be destroyed.
diff --git a/media/audio/fake_audio_output_stream.cc b/media/audio/fake_audio_output_stream.cc
index 6eb5417..af69a2f 100644
--- a/media/audio/fake_audio_output_stream.cc
+++ b/media/audio/fake_audio_output_stream.cc
@@ -33,7 +33,7 @@ bool FakeAudioOutputStream::Open(size_t packet_size) {
void FakeAudioOutputStream::Start(AudioSourceCallback* callback) {
callback_ = callback;
memset(buffer_.get(), 0, packet_size_);
- callback_->OnMoreData(this, buffer_.get(), packet_size_);
+ callback_->OnMoreData(this, buffer_.get(), packet_size_, 0);
}
void FakeAudioOutputStream::Stop() {
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc
index 522b8c4..8a59e33 100644
--- a/media/audio/linux/alsa_output.cc
+++ b/media/audio/linux/alsa_output.cc
@@ -390,8 +390,9 @@ void AlsaPcmOutputStream::BufferPacket(Packet* packet) {
// Request more data if we don't have any cached.
if (packet->used >= packet->size) {
packet->used = 0;
+ // TODO(hclam): Provide pending bytes.
packet->size = shared_data_.OnMoreData(this, packet->buffer.get(),
- packet->capacity);
+ packet->capacity, 0);
CHECK(packet->size <= packet->capacity) << "Data source overran buffer.";
// This should not happen, but incase it does, drop any trailing bytes
@@ -629,10 +630,11 @@ void AlsaPcmOutputStream::SharedData::set_volume(float v) {
size_t AlsaPcmOutputStream::SharedData::OnMoreData(AudioOutputStream* stream,
void* dest,
- size_t max_size) {
+ size_t max_size,
+ int pending_bytes) {
AutoLock l(lock_);
if (source_callback_) {
- return source_callback_->OnMoreData(stream, dest, max_size);
+ return source_callback_->OnMoreData(stream, dest, max_size, pending_bytes);
}
return 0;
diff --git a/media/audio/linux/alsa_output.h b/media/audio/linux/alsa_output.h
index 7d5f381..409b158 100644
--- a/media/audio/linux/alsa_output.h
+++ b/media/audio/linux/alsa_output.h
@@ -168,7 +168,8 @@ class AlsaPcmOutputStream :
// is passed into the output stream, but ownership is not transfered which
// requires a synchronization on access of the |source_callback_| to avoid
// using a deleted callback.
- size_t OnMoreData(AudioOutputStream* stream, void* dest, size_t max_size);
+ size_t OnMoreData(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes);
void OnClose(AudioOutputStream* stream);
void OnError(AudioOutputStream* stream, int code);
diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc
index 8e262b1..d736d93 100644
--- a/media/audio/linux/alsa_output_unittest.cc
+++ b/media/audio/linux/alsa_output_unittest.cc
@@ -40,8 +40,8 @@ class MockAlsaWrapper : public AlsaWrapper {
class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback {
public:
- MOCK_METHOD3(OnMoreData, size_t(AudioOutputStream* stream,
- void* dest, size_t max_size));
+ MOCK_METHOD4(OnMoreData, size_t(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes));
MOCK_METHOD1(OnClose, void(AudioOutputStream* stream));
MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code));
};
@@ -273,7 +273,7 @@ TEST_F(AlsaPcmOutputStreamTest, StartStop) {
// Expect the pre-roll.
MockAudioSourceCallback mock_callback;
EXPECT_CALL(mock_callback,
- OnMoreData(test_stream_.get(), _, kTestPacketSize))
+ OnMoreData(test_stream_.get(), _, kTestPacketSize, 0))
.Times(2)
.WillRepeatedly(Return(kTestPacketSize));
EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
@@ -363,7 +363,7 @@ TEST_F(AlsaPcmOutputStreamTest, BufferPacket) {
MockAudioSourceCallback mock_callback;
EXPECT_CALL(mock_callback,
OnMoreData(test_stream_.get(), packet_.buffer.get(),
- packet_.capacity))
+ packet_.capacity, 0))
.WillOnce(Return(10));
test_stream_->shared_data_.set_source_callback(&mock_callback);
diff --git a/media/audio/mac/audio_output_mac.cc b/media/audio/mac/audio_output_mac.cc
index 657e91a..2f79233 100644
--- a/media/audio/mac/audio_output_mac.cc
+++ b/media/audio/mac/audio_output_mac.cc
@@ -160,7 +160,9 @@ void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this,
if (!source)
return;
size_t capacity = buffer->mAudioDataBytesCapacity;
- size_t filled = source->OnMoreData(audio_stream, buffer->mAudioData, capacity);
+ // TODO(hclam): Provide pending bytes.
+ size_t filled = source->OnMoreData(audio_stream, buffer->mAudioData,
+ capacity, 0);
if (filled > capacity) {
// User probably overran our buffer.
audio_stream->HandleError(0);
diff --git a/media/audio/mac/audio_output_mac_unittest.cc b/media/audio/mac/audio_output_mac_unittest.cc
index d6abefd..d6908cb 100644
--- a/media/audio/mac/audio_output_mac_unittest.cc
+++ b/media/audio/mac/audio_output_mac_unittest.cc
@@ -19,7 +19,7 @@ TEST(MacAudioTest, SineWaveAudio16MonoTest) {
// TODO(cpu): Put the real test when the mock renderer is ported.
int16 buffer[samples] = { 0xffff };
- source.OnMoreData(NULL, buffer, sizeof(buffer));
+ source.OnMoreData(NULL, buffer, sizeof(buffer), 0);
EXPECT_EQ(0, buffer[0]);
EXPECT_EQ(5126, buffer[1]);
}
diff --git a/media/audio/simple_sources.cc b/media/audio/simple_sources.cc
index eaf671d..d9b30c7 100644
--- a/media/audio/simple_sources.cc
+++ b/media/audio/simple_sources.cc
@@ -25,8 +25,8 @@ SineWaveAudioSource::SineWaveAudioSource(Format format, int channels,
// The implementation could be more efficient if a lookup table is constructed
// but it is efficient enough for our simple needs.
-size_t SineWaveAudioSource::OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) {
+size_t SineWaveAudioSource::OnMoreData(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes) {
const double kTwoPi = 2.0 * 3.141592653589;
double f = freq_ / sample_freq_;
int16* sin_tbl = reinterpret_cast<int16*>(dest);
@@ -59,8 +59,8 @@ PushSource::~PushSource() {
CleanUp();
}
-size_t PushSource::OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) {
+size_t PushSource::OnMoreData(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes) {
size_t copied = 0;
while (copied < max_size) {
AutoLock auto_lock(lock_);
diff --git a/media/audio/simple_sources.h b/media/audio/simple_sources.h
index 4a3db8d..d43fcdf 100644
--- a/media/audio/simple_sources.h
+++ b/media/audio/simple_sources.h
@@ -26,7 +26,7 @@ class SineWaveAudioSource : public AudioOutputStream::AudioSourceCallback {
// Implementation of AudioSourceCallback.
virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size);
+ void* dest, size_t max_size, int pending_bytes);
virtual void OnClose(AudioOutputStream* stream);
virtual void OnError(AudioOutputStream* stream, int code);
@@ -73,12 +73,12 @@ class PushSource : public AudioOutputStream::AudioSourceCallback,
// Implementation of AudioSourceCallback.
virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size);
+ void* dest, size_t max_size, int pending_bytes);
virtual void OnClose(AudioOutputStream* stream);
virtual void OnError(AudioOutputStream* stream, int code);
private:
- // Defines the unit of playback. We own the memory pointed by |buffer|.
+ // Defines the unit of playback. We own the memory pointed by |buffer|.
struct Packet {
char* buffer;
size_t size;
@@ -88,7 +88,7 @@ class PushSource : public AudioOutputStream::AudioSourceCallback,
void CleanUp();
const size_t packet_size_;
- typedef std::list<Packet> PacketList;
+ typedef std::list<Packet> PacketList;
PacketList packets_;
size_t buffered_bytes_;
size_t front_buffer_consumed_;
diff --git a/media/audio/simple_sources_unittest.cc b/media/audio/simple_sources_unittest.cc
index ef6a5a7..51eb8db 100644
--- a/media/audio/simple_sources_unittest.cc
+++ b/media/audio/simple_sources_unittest.cc
@@ -54,7 +54,7 @@ TEST(SimpleSourcesTest, PushSourceSmallerWrite) {
// Read everything from the push source.
for (size_t i = 0; i < kDataSize; i += kReadSize) {
size_t size = std::min(kDataSize - i , kReadSize);
- EXPECT_EQ(size, push_source.OnMoreData(NULL, read_data.get(), size));
+ EXPECT_EQ(size, push_source.OnMoreData(NULL, read_data.get(), size, 0));
EXPECT_EQ(0, memcmp(data.get() + i, read_data.get(), size));
}
EXPECT_EQ(0u, push_source.UnProcessedBytes());
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc
index 2393957..38a32f8 100644
--- a/media/audio/win/audio_output_win_unittest.cc
+++ b/media/audio/win/audio_output_win_unittest.cc
@@ -9,8 +9,17 @@
#include "base/file_util.h"
#include "media/audio/audio_output.h"
#include "media/audio/simple_sources.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+
namespace {
const wchar_t kAudioFile1_16b_m_16K[]
@@ -27,7 +36,7 @@ class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
}
// AudioSourceCallback::OnMoreData implementation:
virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) {
+ void* dest, size_t max_size, int pending_bytes) {
++callback_count_;
// Touch the first byte to make sure memory is good.
if (max_size)
@@ -83,9 +92,9 @@ class TestSourceTripleBuffer : public TestSourceBasic {
}
// Override of TestSourceBasic::OnMoreData.
virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) {
+ void* dest, size_t max_size, int pending_bytes) {
// Call the base, which increments the callback_count_.
- TestSourceBasic::OnMoreData(stream, dest, max_size);
+ TestSourceBasic::OnMoreData(stream, dest, max_size, 0);
if (callback_count() % kNumBuffers == 2) {
set_error(!CompareExistingIfNotNULL(2, dest));
} else if (callback_count() % kNumBuffers == 1) {
@@ -119,9 +128,9 @@ class TestSourceLaggy : public TestSourceBasic {
: laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) {
}
virtual size_t OnMoreData(AudioOutputStream* stream,
- void* dest, size_t max_size) {
+ void* dest, size_t max_size, int pending_bytes) {
// Call the base, which increments the callback_count_.
- TestSourceBasic::OnMoreData(stream, dest, max_size);
+ TestSourceBasic::OnMoreData(stream, dest, max_size, 0);
if (callback_count() > kNumBuffers) {
::Sleep(lag_in_ms_);
}
@@ -132,6 +141,14 @@ class TestSourceLaggy : public TestSourceBasic {
int lag_in_ms_;
};
+class MockAudioSource : public AudioOutputStream::AudioSourceCallback {
+ public:
+ MOCK_METHOD4(OnMoreData, size_t(AudioOutputStream* stream, void* dest,
+ size_t max_size, int pending_bytes));
+ MOCK_METHOD1(OnClose, void(AudioOutputStream* stream));
+ MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code));
+};
+
// Helper class to memory map an entire file. The mapping is read-only. Don't
// use for gigabyte-sized files. Attempts to write to this memory generate
// memory access violations.
@@ -479,12 +496,12 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
if (!audio_man->HasAudioDevices())
return;
AudioOutputStream* oas =
- audio_man->MakeAudioStream(AudioManager::AUDIO_PCM_LINEAR, 1,
- AudioManager::kAudioCDSampleRate, 16);
+ audio_man->MakeAudioStream(AudioManager::AUDIO_PCM_LINEAR, 1,
+ AudioManager::kAudioCDSampleRate, 16);
ASSERT_TRUE(NULL != oas);
SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1,
- 200.0, AudioManager::kAudioCDSampleRate);
+ 200.0, AudioManager::kAudioCDSampleRate);
size_t bytes_100_ms = (AudioManager::kAudioCDSampleRate / 10) * 2;
EXPECT_TRUE(oas->Open(bytes_100_ms));
@@ -506,3 +523,46 @@ TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
oas->Close();
}
+// Check that the pending bytes value is correct what the stream starts.
+TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
+ if (IsRunningHeadless())
+ return;
+ AudioManager* audio_man = AudioManager::GetAudioManager();
+ ASSERT_TRUE(NULL != audio_man);
+ if (!audio_man->HasAudioDevices())
+ return;
+ AudioOutputStream* oas =
+ audio_man->MakeAudioStream(AudioManager::AUDIO_PCM_LINEAR, 1,
+ AudioManager::kAudioCDSampleRate, 16);
+ ASSERT_TRUE(NULL != oas);
+
+ NiceMock<MockAudioSource> source;
+ size_t bytes_100_ms = (AudioManager::kAudioCDSampleRate / 10) * 2;
+ EXPECT_TRUE(oas->Open(bytes_100_ms));
+
+ // We expect the amount of pending bytes will reaching 2 times of
+ // |bytes_100_ms| because the audio output stream has a triple buffer scheme.
+ // And then we will try to provide zero data so the amount of pending bytes
+ // will go down and eventually read zero.
+ InSequence s;
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, 0))
+ .WillOnce(Return(bytes_100_ms));
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, bytes_100_ms))
+ .WillOnce(Return(bytes_100_ms));
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(),
+ bytes_100_ms, 2 * bytes_100_ms))
+ .WillOnce(Return(bytes_100_ms));
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(),
+ bytes_100_ms, 2 * bytes_100_ms))
+ .WillOnce(Return(0));
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, bytes_100_ms))
+ .WillOnce(Return(0));
+ EXPECT_CALL(source, OnMoreData(oas, NotNull(), bytes_100_ms, 0))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(0));
+
+ oas->Start(&source);
+ ::Sleep(500);
+ oas->Stop();
+ oas->Close();
+}
diff --git a/media/audio/win/waveout_output_win.cc b/media/audio/win/waveout_output_win.cc
index 0b4cc6f..21532b7 100644
--- a/media/audio/win/waveout_output_win.cc
+++ b/media/audio/win/waveout_output_win.cc
@@ -58,7 +58,8 @@ PCMWaveOutAudioOutputStream::PCMWaveOutAudioOutputStream(
buffer_(NULL),
buffer_size_(0),
volume_(1),
- channels_(channels) {
+ channels_(channels),
+ pending_bytes_(0) {
format_.wFormatTag = WAVE_FORMAT_PCM;
format_.nChannels = channels > 2 ? 2 : channels;
format_.nSamplesPerSec = sampling_rate;
@@ -144,6 +145,7 @@ void PCMWaveOutAudioOutputStream::Start(AudioSourceCallback* callback) {
WAVEHDR* buffer = buffer_;
for (int ix = 0; ix != kNumBuffers; ++ix) {
QueueNextPacket(buffer); // Read more data.
+ pending_bytes_ += buffer->dwBufferLength;
buffer = GetNextBuffer(buffer);
}
buffer = buffer_;
@@ -235,8 +237,12 @@ void PCMWaveOutAudioOutputStream::HandleError(MMRESULT error) {
void PCMWaveOutAudioOutputStream::QueueNextPacket(WAVEHDR *buffer) {
// Call the source which will fill our buffer with pleasant sounds and
// return to us how many bytes were used.
+ // If we are down sampling to a smaller number of channels, we need to
+ // scale up the amount of pending bytes.
// TODO(fbarchard): Handle used 0 by queueing more.
- size_t used = callback_->OnMoreData(this, buffer->lpData, buffer_size_);
+ int scaled_pending_bytes = pending_bytes_ * channels_ / format_.nChannels;
+ size_t used = callback_->OnMoreData(this, buffer->lpData, buffer_size_,
+ scaled_pending_bytes);
if (used <= buffer_size_) {
buffer->dwBufferLength = used * format_.nChannels / channels_;
if (channels_ > 2 && format_.nChannels == 2) {
@@ -248,7 +254,6 @@ void PCMWaveOutAudioOutputStream::QueueNextPacket(WAVEHDR *buffer) {
format_.nChannels, format_.wBitsPerSample >> 3,
volume_);
}
-
} else {
HandleError(0);
return;
@@ -282,6 +287,11 @@ void PCMWaveOutAudioOutputStream::WaveCallback(HWAVEOUT hwo, UINT msg,
// Not sure if ever hit this but just in case.
return;
}
+
+ // Before we queue the next packet, we need to adjust the number of pending
+ // bytes since the last write to hardware.
+ obj->pending_bytes_ -= buffer->dwBufferLength;
+
obj->QueueNextPacket(buffer);
// Time to send the buffer to the audio driver. Since we are reusing
@@ -290,6 +300,8 @@ void PCMWaveOutAudioOutputStream::WaveCallback(HWAVEOUT hwo, UINT msg,
if (result != MMSYSERR_NOERROR)
obj->HandleError(result);
+ obj->pending_bytes_ += buffer->dwBufferLength;
+
} else if (msg == WOM_CLOSE) {
// We can be closed before calling Start, so it is possible to have a
// null callback at this point.
diff --git a/media/audio/win/waveout_output_win.h b/media/audio/win/waveout_output_win.h
index e072851..4f090ba 100644
--- a/media/audio/win/waveout_output_win.h
+++ b/media/audio/win/waveout_output_win.h
@@ -89,6 +89,9 @@ class PCMWaveOutAudioOutputStream : public AudioOutputStream {
// Channels from 0 to 6.
int channels_;
+ // Number of bytes yet to be played in the hardware buffer.
+ int pending_bytes_;
+
// The id assigned by the operating system to the selected wave output
// hardware device. Usually this is just -1 which means 'default device'.
UINT device_id_;
diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
index 6576679..cf31af7 100644
--- a/media/filters/audio_renderer_impl.cc
+++ b/media/filters/audio_renderer_impl.cc
@@ -13,7 +13,8 @@ static const size_t kSamplesPerBuffer = 8*1024;
AudioRendererImpl::AudioRendererImpl()
: AudioRendererBase(),
- stream_(NULL) {
+ stream_(NULL),
+ bytes_per_second_(0) {
}
AudioRendererImpl::~AudioRendererImpl() {
@@ -48,7 +49,7 @@ void AudioRendererImpl::SetVolume(float volume) {
}
size_t AudioRendererImpl::OnMoreData(AudioOutputStream* stream, void* dest_void,
- size_t len) {
+ size_t len, int pending_bytes) {
// TODO(scherkus): handle end of stream.
if (!stream_)
return 0;
@@ -56,7 +57,9 @@ size_t AudioRendererImpl::OnMoreData(AudioOutputStream* stream, void* dest_void,
// TODO(scherkus): Maybe change OnMoreData to pass in char/uint8 or similar.
// TODO(fbarchard): Waveout_output_win.h should handle zero length buffers
// without clicking.
- return FillBuffer(static_cast<uint8*>(dest_void), len, base::TimeDelta());
+ base::TimeDelta delay = base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond * pending_bytes / bytes_per_second_);
+ return FillBuffer(static_cast<uint8*>(dest_void), len, delay);
}
void AudioRendererImpl::OnClose(AudioOutputStream* stream) {
@@ -78,6 +81,8 @@ bool AudioRendererImpl::OnInitialize(const MediaFormat& media_format) {
return false;
}
+ bytes_per_second_ = sample_rate * channels * sample_bits / 8;
+
// Create our audio stream.
stream_ = AudioManager::GetAudioManager()->MakeAudioStream(
AudioManager::AUDIO_PCM_LINEAR, channels, sample_rate, sample_bits);
diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h
index 1a6c5a1..b15c83d 100644
--- a/media/filters/audio_renderer_impl.h
+++ b/media/filters/audio_renderer_impl.h
@@ -43,7 +43,8 @@ class AudioRendererImpl : public AudioRendererBase,
virtual void SetVolume(float volume);
// AudioSourceCallback implementation.
- virtual size_t OnMoreData(AudioOutputStream* stream, void* dest, size_t len);
+ virtual size_t OnMoreData(AudioOutputStream* stream, void* dest,
+ size_t len, int pending_bytes);
virtual void OnClose(AudioOutputStream* stream);
virtual void OnError(AudioOutputStream* stream, int code);
@@ -60,6 +61,7 @@ class AudioRendererImpl : public AudioRendererBase,
private:
// Audio output stream device.
AudioOutputStream* stream_;
+ int bytes_per_second_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl);
};