Index: media/audio/audio_input_device.cc |
=================================================================== |
--- media/audio/audio_input_device.cc (revision 186213) |
+++ media/audio/audio_input_device.cc (working copy) |
@@ -11,6 +11,14 @@ |
#include "media/audio/audio_manager_base.h" |
#include "media/base/audio_bus.h" |
+namespace { |
+// The number of shared memory buffers indicated to browser process in order |
+// to avoid data overwriting. This number can be any positive number, |
+// dependent how fast the renderer process can pick up captured data from |
+// shared memory. |
+int kRequestedSharedMemoryCount = 10; |
DaleCurtis
2013/03/06 01:12:51
Seems like a lot. How did you choose this number?
wjia(left Chromium)
2013/03/06 05:32:22
I have seen renderer process missed 5 to 6 buffers
|
+} |
+ |
namespace media { |
// Takes care of invoking the capture callback on the audio thread. |
@@ -20,7 +28,7 @@ |
: public AudioDeviceThread::Callback { |
public: |
AudioThreadCallback(const AudioParameters& audio_parameters, |
- base::SharedMemoryHandle memory, |
+ SharedMemoryHandleVector memory, |
int memory_length, |
CaptureCallback* capture_callback); |
virtual ~AudioThreadCallback(); |
@@ -28,7 +36,8 @@ |
virtual void MapSharedMemory() OVERRIDE; |
// Called whenever we receive notifications about pending data. |
- virtual void Process(int pending_data) OVERRIDE; |
+ // The |index| states which buffer is used. |
+ virtual void Process(int pending_data, int index) OVERRIDE; |
private: |
CaptureCallback* capture_callback_; |
@@ -43,10 +52,13 @@ |
callback_(NULL), |
event_handler_(NULL), |
ipc_(ipc), |
+ socket_handle_(base::SyncSocket::kInvalidHandle), |
+ received_shared_memory_count_(0), |
stream_id_(0), |
session_id_(0), |
pending_device_ready_(false), |
- agc_is_enabled_(false) { |
+ agc_is_enabled_(false), |
+ audio_thread_(true) { |
CHECK(ipc_); |
} |
@@ -102,22 +114,40 @@ |
} |
void AudioInputDevice::OnStreamCreated( |
- base::SharedMemoryHandle handle, |
base::SyncSocket::Handle socket_handle, |
- int length) { |
+ int total_handles) { |
DCHECK(message_loop()->BelongsToCurrentThread()); |
-#if defined(OS_WIN) |
- DCHECK(handle); |
- DCHECK(socket_handle); |
-#else |
- DCHECK_GE(handle.fd, 0); |
- DCHECK_GE(socket_handle, 0); |
-#endif |
+ DCHECK_NE(socket_handle, base::SyncSocket::kInvalidHandle); |
+ DVLOG(1) << "OnStreamCreated (stream_id=" << stream_id_ << ")"; |
+ |
+ // We should only get this callback if stream_id_ is valid. If it is not, |
+ // the IPC layer should have closed the socket handle for us and not invoked |
+ // the callback. The basic assertion is that when |
+ // stream_id_ is 0 the AudioInputDevice instance is not registered as a |
+ // delegate and hence it should not receive callbacks. |
+ DCHECK(stream_id_); |
+ DCHECK_GT(total_handles, 0); |
+ DCHECK_EQ(shared_memory_handles_.size(), 0u); |
+ |
+ base::AutoLock auto_lock(audio_thread_lock_); |
+ DCHECK(audio_thread_.IsStopped()); |
+ |
+ socket_handle_ = socket_handle; |
+ shared_memory_handles_.resize(total_handles, base::SharedMemory().handle()); |
+} |
+ |
+void AudioInputDevice::OnSharedMemoryCreated( |
+ base::SharedMemoryHandle handle, |
+ int length, |
+ int index) { |
+ DCHECK(message_loop()->BelongsToCurrentThread()); |
+ DCHECK_NE(socket_handle_, base::SyncSocket::kInvalidHandle); |
+ DCHECK(base::SharedMemory::IsHandleValid(handle)); |
DCHECK(length); |
DVLOG(1) << "OnStreamCreated (stream_id=" << stream_id_ << ")"; |
// We should only get this callback if stream_id_ is valid. If it is not, |
- // the IPC layer should have closed the shared memory and socket handles |
+ // the IPC layer should have closed the shared memory socket handle |
// for us and not invoked the callback. The basic assertion is that when |
// stream_id_ is 0 the AudioInputDevice instance is not registered as a |
// delegate and hence it should not receive callbacks. |
@@ -126,13 +156,22 @@ |
base::AutoLock auto_lock(audio_thread_lock_); |
DCHECK(audio_thread_.IsStopped()); |
- audio_callback_.reset( |
- new AudioInputDevice::AudioThreadCallback(audio_parameters_, handle, |
- length, callback_)); |
- audio_thread_.Start(audio_callback_.get(), socket_handle, "AudioInputDevice"); |
- MessageLoop::current()->PostTask(FROM_HERE, |
- base::Bind(&AudioInputDevice::StartOnIOThread, this)); |
+ int total_handles = static_cast<int>(shared_memory_handles_.size()); |
+ DCHECK_LT(index, total_handles); |
+ DCHECK(!base::SharedMemory::IsHandleValid(shared_memory_handles_[index])); |
+ shared_memory_handles_[index] = handle; |
+ received_shared_memory_count_++; |
+ if (received_shared_memory_count_ == total_handles) { |
+ audio_callback_.reset( |
+ new AudioInputDevice::AudioThreadCallback( |
+ audio_parameters_, shared_memory_handles_, length, callback_)); |
+ audio_thread_.Start(audio_callback_.get(), socket_handle_, |
+ "AudioInputDevice"); |
+ |
+ MessageLoop::current()->PostTask(FROM_HERE, |
+ base::Bind(&AudioInputDevice::StartOnIOThread, this)); |
+ } |
} |
void AudioInputDevice::OnVolume(double volume) { |
@@ -196,7 +235,7 @@ |
stream_id_ = 0; |
} else { |
ipc_->CreateStream(stream_id_, audio_parameters_, device_id, |
- agc_is_enabled_); |
+ agc_is_enabled_, kRequestedSharedMemoryCount); |
} |
pending_device_ready_ = false; |
@@ -228,7 +267,8 @@ |
// and create the stream when getting a OnDeviceReady() callback. |
if (!session_id_) { |
ipc_->CreateStream(stream_id_, audio_parameters_, |
- AudioManagerBase::kDefaultDeviceId, agc_is_enabled_); |
+ AudioManagerBase::kDefaultDeviceId, agc_is_enabled_, |
+ kRequestedSharedMemoryCount); |
} else { |
ipc_->StartDevice(stream_id_, session_id_); |
pending_device_ready_ = true; |
@@ -300,7 +340,7 @@ |
// AudioInputDevice::AudioThreadCallback |
AudioInputDevice::AudioThreadCallback::AudioThreadCallback( |
const AudioParameters& audio_parameters, |
- base::SharedMemoryHandle memory, |
+ SharedMemoryHandleVector memory, |
int memory_length, |
CaptureCallback* capture_callback) |
: AudioDeviceThread::Callback(audio_parameters, memory, memory_length), |
@@ -312,15 +352,18 @@ |
} |
void AudioInputDevice::AudioThreadCallback::MapSharedMemory() { |
- shared_memory_.Map(memory_length_); |
+ for (size_t id = 0; id < shared_memory_.size(); ++id) { |
+ shared_memory_[id]->Map(memory_length_); |
+ } |
} |
-void AudioInputDevice::AudioThreadCallback::Process(int pending_data) { |
+void AudioInputDevice::AudioThreadCallback::Process( |
+ int pending_data, int index) { |
// The shared memory represents parameters, size of the data buffer and the |
// actual data buffer containing audio data. Map the memory into this |
// structure and parse out parameters and the data area. |
AudioInputBuffer* buffer = |
- reinterpret_cast<AudioInputBuffer*>(shared_memory_.memory()); |
+ reinterpret_cast<AudioInputBuffer*>(shared_memory_[index]->memory()); |
DCHECK_EQ(buffer->params.size, |
memory_length_ - sizeof(AudioInputBufferParameters)); |
double volume = buffer->params.volume; |