diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-24 22:30:07 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-24 22:30:07 +0000 |
commit | 9d3381548a57745b672e65fa4b487c61b0b7bf39 (patch) | |
tree | d12a7e03ca70bbce7a3a372e5969719e496e0193 | |
parent | 4748f54e887fc85f009e8d1df2288f7f3f984d0e (diff) | |
download | chromium_src-9d3381548a57745b672e65fa4b487c61b0b7bf39.zip chromium_src-9d3381548a57745b672e65fa4b487c61b0b7bf39.tar.gz chromium_src-9d3381548a57745b672e65fa4b487c61b0b7bf39.tar.bz2 |
Provide unplayed bytes ALSA implementation of audio
BUG=19921
TEST=play an video track on linux, AV should be in sync.
Use snd_pcm_delay() to provide the number of unplayed bytes in linux's
audio implementation. This information will correct the sync problem
for linux.
Review URL: http://codereview.chromium.org/173288
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24163 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/audio/linux/alsa_output.cc | 22 | ||||
-rw-r--r-- | media/audio/linux/alsa_output_unittest.cc | 8 | ||||
-rw-r--r-- | media/audio/linux/alsa_wrapper.cc | 4 | ||||
-rw-r--r-- | media/audio/linux/alsa_wrapper.h | 1 |
4 files changed, 32 insertions, 3 deletions
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc index 8a59e33..96a2e4b 100644 --- a/media/audio/linux/alsa_output.cc +++ b/media/audio/linux/alsa_output.cc @@ -389,10 +389,28 @@ void AlsaPcmOutputStream::BufferPacket(Packet* packet) { // Request more data if we don't have any cached. if (packet->used >= packet->size) { + // Before making a request to source for data. We need to determine the + // delay (in bytes) for the requested data to be played. + snd_pcm_sframes_t delay; + int error = wrapper_->PcmDelay(playback_handle_, &delay); + if (error < 0) { + error = wrapper_->PcmRecover(playback_handle_, + error, + kPcmRecoverIsSilent); + if (error < 0) { + LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error); + } + + // TODO(hclam): If we cannot query the delay, we may want to stop + // the playback and report an error. + delay = 0; + } else { + delay *= bytes_per_frame_; + } + packet->used = 0; - // TODO(hclam): Provide pending bytes. packet->size = shared_data_.OnMoreData(this, packet->buffer.get(), - packet->capacity, 0); + packet->capacity, delay); CHECK(packet->size <= packet->capacity) << "Data source overran buffer."; // This should not happen, but incase it does, drop any trailing bytes diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc index d736d93..d13da89 100644 --- a/media/audio/linux/alsa_output_unittest.cc +++ b/media/audio/linux/alsa_output_unittest.cc @@ -24,6 +24,7 @@ class MockAlsaWrapper : public AlsaWrapper { MOCK_METHOD1(PcmClose, int(snd_pcm_t* handle)); MOCK_METHOD1(PcmPrepare, int(snd_pcm_t* handle)); MOCK_METHOD1(PcmDrop, int(snd_pcm_t* handle)); + MOCK_METHOD2(PcmDelay, int(snd_pcm_t* handle, snd_pcm_sframes_t* delay)); MOCK_METHOD3(PcmWritei, snd_pcm_sframes_t(snd_pcm_t* handle, const void* buffer, snd_pcm_uframes_t size)); @@ -272,6 +273,9 @@ TEST_F(AlsaPcmOutputStreamTest, StartStop) { // Expect the pre-roll. MockAudioSourceCallback mock_callback; + EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(kFakeHandle, _)) + .Times(2) + .WillRepeatedly(DoAll(SetArgumentPointee<1>(0), Return(0))); EXPECT_CALL(mock_callback, OnMoreData(test_stream_.get(), _, kTestPacketSize, 0)) .Times(2) @@ -361,9 +365,11 @@ TEST_F(AlsaPcmOutputStreamTest, BufferPacket) { // Return a partially filled packet. MockAudioSourceCallback mock_callback; + EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _)) + .WillOnce(DoAll(SetArgumentPointee<1>(1), Return(0))); EXPECT_CALL(mock_callback, OnMoreData(test_stream_.get(), packet_.buffer.get(), - packet_.capacity, 0)) + packet_.capacity, kTestBytesPerFrame)) .WillOnce(Return(10)); test_stream_->shared_data_.set_source_callback(&mock_callback); diff --git a/media/audio/linux/alsa_wrapper.cc b/media/audio/linux/alsa_wrapper.cc index 9557cac..8463686 100644 --- a/media/audio/linux/alsa_wrapper.cc +++ b/media/audio/linux/alsa_wrapper.cc @@ -29,6 +29,10 @@ int AlsaWrapper::PcmDrop(snd_pcm_t* handle) { return snd_pcm_drop(handle); } +int AlsaWrapper::PcmDelay(snd_pcm_t* handle, snd_pcm_sframes_t* delay) { + return snd_pcm_delay(handle, delay); +} + snd_pcm_sframes_t AlsaWrapper::PcmWritei(snd_pcm_t* handle, const void* buffer, snd_pcm_uframes_t size) { diff --git a/media/audio/linux/alsa_wrapper.h b/media/audio/linux/alsa_wrapper.h index a3dafbb..d7686dd 100644 --- a/media/audio/linux/alsa_wrapper.h +++ b/media/audio/linux/alsa_wrapper.h @@ -20,6 +20,7 @@ class AlsaWrapper { virtual int PcmClose(snd_pcm_t* handle); virtual int PcmPrepare(snd_pcm_t* handle); virtual int PcmDrop(snd_pcm_t* handle); + virtual int PcmDelay(snd_pcm_t* handle, snd_pcm_sframes_t* delay); virtual snd_pcm_sframes_t PcmWritei(snd_pcm_t* handle, const void* buffer, snd_pcm_uframes_t size); |