Index: ppapi/proxy/audio_input_resource.cc |
diff --git a/ppapi/proxy/audio_input_resource.cc b/ppapi/proxy/audio_input_resource.cc |
index 0ae1831afa8cf9c66409cde60cce814683696ce5..7f1f81983e6ae77d4f5acd52ae537ab67204ea01 100644 |
--- a/ppapi/proxy/audio_input_resource.cc |
+++ b/ppapi/proxy/audio_input_resource.cc |
@@ -8,6 +8,7 @@ |
#include "base/logging.h" |
#include "ipc/ipc_platform_file.h" |
#include "media/audio/audio_parameters.h" |
+#include "media/base/audio_bus.h" |
#include "ppapi/c/pp_errors.h" |
#include "ppapi/proxy/ppapi_messages.h" |
#include "ppapi/proxy/resource_message_params.h" |
@@ -22,9 +23,8 @@ |
namespace ppapi { |
namespace proxy { |
-AudioInputResource::AudioInputResource( |
- Connection connection, |
- PP_Instance instance) |
+AudioInputResource::AudioInputResource(Connection connection, |
+ PP_Instance instance) |
: PluginResource(connection, instance), |
open_state_(BEFORE_OPEN), |
capturing_(false), |
@@ -33,7 +33,9 @@ AudioInputResource::AudioInputResource( |
audio_input_callback_(NULL), |
user_data_(NULL), |
enumeration_helper_(this), |
- bytes_per_second_(0) { |
+ bytes_per_second_(0), |
+ sample_frame_count_(0), |
+ client_buffer_size_bytes_(0) { |
SendCreate(RENDERER, PpapiHostMsg_AudioInput_Create()); |
} |
@@ -181,14 +183,33 @@ void AudioInputResource::SetStreamInfo( |
socket_.reset(new base::CancelableSyncSocket(socket_handle)); |
shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); |
shared_memory_size_ = shared_memory_size; |
+ DCHECK(!shared_memory_->memory()); |
- if (!shared_memory_->Map(shared_memory_size_)) { |
- PpapiGlobals::Get()->LogWithSource( |
- pp_instance(), |
- PP_LOGLEVEL_WARNING, |
- std::string(), |
- "Failed to map shared memory for PPB_AudioInput_Shared."); |
- } |
+ // If we fail to map the shared memory into the caller's address space we |
+ // might as well fail here since nothing will work if this is the case. |
+ CHECK(shared_memory_->Map(shared_memory_size_)); |
+ |
+ // Create a new audio bus and wrap the audio data section in shared memory. |
+ media::AudioInputBuffer* buffer = |
+ static_cast<media::AudioInputBuffer*>(shared_memory_->memory()); |
+ audio_bus_ = media::AudioBus::WrapMemory( |
+ kAudioInputChannels, sample_frame_count_, buffer->audio); |
+ |
+ // Ensure that the size of the created audio bus matches the allocated |
+ // size in shared memory. |
+ // Example: DCHECK_EQ(8208 - 16, 8192) for |sample_frame_count_| = 2048. |
+ const uint32_t audio_bus_size_bytes = media::AudioBus::CalculateMemorySize( |
+ audio_bus_->channels(), audio_bus_->frames()); |
+ DCHECK_EQ(shared_memory_size_ - sizeof(media::AudioInputBufferParameters), |
+ audio_bus_size_bytes); |
+ |
+ // Create an extra integer audio buffer for user audio data callbacks. |
+ // Data in shared memory will be copied to this buffer, after interleaving |
+ // and truncation, before each input callback to match the format expected |
+ // by the client. |
+ client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() * |
+ kBitsPerAudioInputSample / 8; |
+ client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); |
// There is a pending capture request before SetStreamInfo(). |
if (capturing_) { |
@@ -202,7 +223,8 @@ void AudioInputResource::SetStreamInfo( |
void AudioInputResource::StartThread() { |
// Don't start the thread unless all our state is set up correctly. |
if ((!audio_input_callback_0_3_ && !audio_input_callback_) || |
- !socket_.get() || !capturing_ || !shared_memory_->memory()) { |
+ !socket_.get() || !capturing_ || !shared_memory_->memory() || |
+ !audio_bus_.get() || !client_buffer_.get()) { |
return; |
} |
DCHECK(!audio_input_thread_.get()); |
@@ -223,28 +245,42 @@ void AudioInputResource::StopThread() { |
void AudioInputResource::Run() { |
// The shared memory represents AudioInputBufferParameters and the actual data |
- // buffer. |
+ // buffer stored as an audio bus. |
media::AudioInputBuffer* buffer = |
static_cast<media::AudioInputBuffer*>(shared_memory_->memory()); |
- uint32_t data_buffer_size = |
+ const uint32_t audio_bus_size_bytes = |
shared_memory_size_ - sizeof(media::AudioInputBufferParameters); |
- int pending_data; |
- while (sizeof(pending_data) == socket_->Receive(&pending_data, |
- sizeof(pending_data)) && |
- pending_data >= 0) { |
+ while (true) { |
+ int pending_data = 0; |
+ size_t bytes_read = socket_->Receive(&pending_data, sizeof(pending_data)); |
+ if (bytes_read != sizeof(pending_data)) { |
+ DCHECK_EQ(bytes_read, 0U); |
+ break; |
+ } |
+ if (pending_data < 0) |
+ break; |
+ |
+ // Convert an AudioBus from deinterleaved float to interleaved integer data. |
+ // Store the result in a preallocated |client_buffer_|. |
+ audio_bus_->ToInterleaved(audio_bus_->frames(), |
+ kBitsPerAudioInputSample / 8, |
+ client_buffer_.get()); |
+ |
// While closing the stream, we may receive buffers whose size is different |
// from |data_buffer_size|. |
- CHECK_LE(buffer->params.size, data_buffer_size); |
+ CHECK_LE(buffer->params.size, audio_bus_size_bytes); |
if (buffer->params.size > 0) { |
if (audio_input_callback_) { |
PP_TimeDelta latency = |
static_cast<double>(pending_data) / bytes_per_second_; |
- audio_input_callback_(&buffer->audio[0], buffer->params.size, latency, |
+ audio_input_callback_(client_buffer_.get(), |
+ client_buffer_size_bytes_, |
+ latency, |
user_data_); |
} else { |
- audio_input_callback_0_3_(&buffer->audio[0], buffer->params.size, |
- user_data_); |
+ audio_input_callback_0_3_( |
+ client_buffer_.get(), client_buffer_size_bytes_, user_data_); |
} |
} |
} |
@@ -287,6 +323,7 @@ int32_t AudioInputResource::CommonOpen( |
open_callback_ = callback; |
bytes_per_second_ = kAudioInputChannels * (kBitsPerAudioInputSample / 8) * |
enter_config.object()->GetSampleRate(); |
+ sample_frame_count_ = enter_config.object()->GetSampleFrameCount(); |
PpapiHostMsg_AudioInput_Open msg( |
device_id, enter_config.object()->GetSampleRate(), |