diff options
-rw-r--r-- | media/audio/audio_input_controller.cc | 4 | ||||
-rw-r--r-- | media/audio/audio_input_controller.h | 5 | ||||
-rw-r--r-- | media/audio/audio_input_unittest.cc | 6 | ||||
-rw-r--r-- | media/audio/audio_io.h | 2 | ||||
-rw-r--r-- | media/audio/fake_audio_input_stream.cc | 2 | ||||
-rw-r--r-- | media/audio/linux/alsa_input.cc | 21 | ||||
-rw-r--r-- | media/audio/linux/alsa_input.h | 3 | ||||
-rw-r--r-- | media/audio/mac/audio_input_mac.cc | 3 | ||||
-rw-r--r-- | media/audio/win/wavein_input_win.cc | 3 |
9 files changed, 38 insertions, 11 deletions
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc index b370612..1e264e6 100644 --- a/media/audio/audio_input_controller.cc +++ b/media/audio/audio_input_controller.cc @@ -183,7 +183,7 @@ void AudioInputController::DoResetNoDataTimer() { } void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, - uint32 size) { + uint32 size, uint32 hardware_delay_bytes) { { base::AutoLock auto_lock(lock_); if (state_ != kRecording) @@ -196,7 +196,7 @@ void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, // Use SyncSocket if we are in a low-latency mode. if (LowLatencyMode()) { sync_writer_->Write(data, size); - sync_writer_->UpdateRecordedBytes(size); + sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); return; } diff --git a/media/audio/audio_input_controller.h b/media/audio/audio_input_controller.h index dd29001..fdc29cf 100644 --- a/media/audio/audio_input_controller.h +++ b/media/audio/audio_input_controller.h @@ -58,7 +58,7 @@ class MEDIA_EXPORT AudioInputController virtual ~SyncWriter() {} // Notify the synchronous writer about the number of bytes in the - // AudioInputController which has been recorded. + // soundcard which has been recorded. virtual void UpdateRecordedBytes(uint32 bytes) = 0; // Write certain amount of data from |data|. This method returns @@ -117,7 +117,8 @@ class MEDIA_EXPORT AudioInputController /////////////////////////////////////////////////////////////////////////// // AudioInputCallback methods. - virtual void OnData(AudioInputStream* stream, const uint8* src, uint32 size); + virtual void OnData(AudioInputStream* stream, const uint8* src, uint32 size, + uint32 hardware_delay_bytes); virtual void OnClose(AudioInputStream* stream); virtual void OnError(AudioInputStream* stream, int code); diff --git a/media/audio/audio_input_unittest.cc b/media/audio/audio_input_unittest.cc index f62de94..914aa4c3 100644 --- a/media/audio/audio_input_unittest.cc +++ b/media/audio/audio_input_unittest.cc @@ -25,7 +25,7 @@ class TestInputCallback : public AudioInputStream::AudioInputCallback { max_data_bytes_(max_data_bytes) { } virtual void OnData(AudioInputStream* stream, const uint8* data, - uint32 size) { + uint32 size, uint32 hardware_delay_bytes) { ++callback_count_; // Read the first byte to make sure memory is good. if (size) { @@ -75,9 +75,9 @@ class TestInputCallbackBlocking : public TestInputCallback { block_for_ms_(block_for_ms) { } virtual void OnData(AudioInputStream* stream, const uint8* data, - uint32 size) { + uint32 size, uint32 hardware_delay_bytes) { // Call the base, which increments the callback_count_. - TestInputCallback::OnData(stream, data, size); + TestInputCallback::OnData(stream, data, size, hardware_delay_bytes); if (callback_count() > block_after_callback_) base::PlatformThread::Sleep(block_for_ms_); } diff --git a/media/audio/audio_io.h b/media/audio/audio_io.h index 74b5c47..2550873 100644 --- a/media/audio/audio_io.h +++ b/media/audio/audio_io.h @@ -112,7 +112,7 @@ class AudioInputStream { // available. This is called from a special audio thread and the // implementation should return as soon as possible. virtual void OnData(AudioInputStream* stream, const uint8* src, - uint32 size) = 0; + uint32 size, uint32 hardware_delay_bytes) = 0; // The stream is done with this callback, the last call received by this // audio sink. diff --git a/media/audio/fake_audio_input_stream.cc b/media/audio/fake_audio_input_stream.cc index b84db92..8ed02de 100644 --- a/media/audio/fake_audio_input_stream.cc +++ b/media/audio/fake_audio_input_stream.cc @@ -48,7 +48,7 @@ void FakeAudioInputStream::Start(AudioInputCallback* callback) { void FakeAudioInputStream::DoCallback() { DCHECK(callback_); - callback_->OnData(this, buffer_.get(), buffer_size_); + callback_->OnData(this, buffer_.get(), buffer_size_, buffer_size_); Time now = Time::Now(); int64 next_callback_ms = (last_callback_time_ + diff --git a/media/audio/linux/alsa_input.cc b/media/audio/linux/alsa_input.cc index 9864fb9..8aad65a 100644 --- a/media/audio/linux/alsa_input.cc +++ b/media/audio/linux/alsa_input.cc @@ -133,6 +133,21 @@ bool AlsaPcmInputStream::Recover(int original_error) { return true; } +snd_pcm_sframes_t AlsaPcmInputStream::GetCurrentDelay() { + snd_pcm_sframes_t delay = -1; + + int error = wrapper_->PcmDelay(device_handle_, &delay); + if (error < 0) + Recover(error); + + // snd_pcm_delay() may not work in the beginning of the stream. In this case + // return delay of data we know currently is in the ALSA's buffer. + if (delay < 0) + delay = wrapper_->PcmAvailUpdate(device_handle_); + + return delay; +} + void AlsaPcmInputStream::ReadAudio() { DCHECK(callback_); @@ -160,11 +175,15 @@ void AlsaPcmInputStream::ReadAudio() { int num_packets = frames / params_.samples_per_packet; int num_packets_read = num_packets; + int bytes_per_frame = params_.channels * params_.bits_per_sample / 8; + uint32 hardware_delay_bytes = + static_cast<uint32>(GetCurrentDelay() * bytes_per_frame); while (num_packets--) { int frames_read = wrapper_->PcmReadi(device_handle_, audio_packet_.get(), params_.samples_per_packet); if (frames_read == params_.samples_per_packet) { - callback_->OnData(this, audio_packet_.get(), bytes_per_packet_); + callback_->OnData(this, audio_packet_.get(), bytes_per_packet_, + hardware_delay_bytes); } else { LOG(WARNING) << "PcmReadi returning less than expected frames: " << frames_read << " vs. " << params_.samples_per_packet diff --git a/media/audio/linux/alsa_input.h b/media/audio/linux/alsa_input.h index e97737f..3e5209a 100644 --- a/media/audio/linux/alsa_input.h +++ b/media/audio/linux/alsa_input.h @@ -50,6 +50,9 @@ class AlsaPcmInputStream : public AudioInputStream { // Recovers from any device errors if possible. bool Recover(int error); + // Utility function for talking with the ALSA API. + snd_pcm_sframes_t GetCurrentDelay(); + std::string device_name_; AudioParameters params_; int bytes_per_packet_; diff --git a/media/audio/mac/audio_input_mac.cc b/media/audio/mac/audio_input_mac.cc index 3efe86c..e96277f 100644 --- a/media/audio/mac/audio_input_mac.cc +++ b/media/audio/mac/audio_input_mac.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -159,6 +159,7 @@ void PCMQueueInAudioInputStream::HandleInputBuffer( if (audio_buffer->mAudioDataByteSize) callback_->OnData(this, reinterpret_cast<const uint8*>(audio_buffer->mAudioData), + audio_buffer->mAudioDataByteSize, audio_buffer->mAudioDataByteSize); // Recycle the buffer. OSStatus err = QueueNextBuffer(audio_buffer); diff --git a/media/audio/win/wavein_input_win.cc b/media/audio/win/wavein_input_win.cc index a1f6a83..b994a29 100644 --- a/media/audio/win/wavein_input_win.cc +++ b/media/audio/win/wavein_input_win.cc @@ -190,8 +190,11 @@ void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, if (msg == WIM_DATA) { // WIM_DONE indicates that the driver is done with our buffer. We pass it // to the callback and check if we need to stop playing. + // It should be OK to assume the data in the buffer is what has been + // recorded in the soundcard. WAVEHDR* buffer = reinterpret_cast<WAVEHDR*>(param1); obj->callback_->OnData(obj, reinterpret_cast<const uint8*>(buffer->lpData), + buffer->dwBytesRecorded, buffer->dwBytesRecorded); if (obj->state_ == kStateStopping) { |