| Index: ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc | 
| diff --git a/ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc b/ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc | 
| index 18558e6370a576a8848024d31cb1264e2047642f..6a4cfd9d7bfbe0de3a887a7f808eea3e29997e4e 100644 | 
| --- a/ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc | 
| +++ b/ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc | 
| @@ -30,6 +30,10 @@ size_t ceil64k(size_t n) { | 
| return (n + 0xFFFF) & (~0xFFFF); | 
| } | 
|  | 
| +// Hard coded values from PepperPlatformAudioOutputImpl. | 
| +// TODO(???): PPAPI shouldn't hard code these values for all clients. | 
| +enum { kChannels = 2, kBytesPerSample = 2 }; | 
| + | 
| }  // namespace | 
|  | 
| PluginAudio::PluginAudio() : | 
| @@ -42,7 +46,8 @@ PluginAudio::PluginAudio() : | 
| thread_id_(), | 
| thread_active_(false), | 
| user_callback_(NULL), | 
| -    user_data_(NULL) { | 
| +    user_data_(NULL), | 
| +    audio_buffer_size_(0) { | 
| DebugPrintf("PluginAudio::PluginAudio\n"); | 
| } | 
|  | 
| @@ -53,10 +58,13 @@ PluginAudio::~PluginAudio() { | 
| GetInterface()->StopPlayback(resource_); | 
| // Unmap the shared memory buffer, if present. | 
| if (shm_buffer_) { | 
| +    audio_bus_.reset(); | 
| +    audio_buffer_.reset(); | 
| munmap(shm_buffer_, | 
| ceil64k(media::TotalSharedMemorySizeInBytes(shm_size_))); | 
| shm_buffer_ = NULL; | 
| shm_size_ = 0; | 
| +    audio_buffer_size_ = 0; | 
| } | 
| // Close the handles. | 
| if (shm_ != -1) { | 
| @@ -87,9 +95,15 @@ void PluginAudio::AudioThread(void* self) { | 
| if ((sizeof(sync_value) != r) || (-1 == sync_value)) | 
| break; | 
| // Invoke user callback, get next buffer of audio data. | 
| -    audio->user_callback_(audio->shm_buffer_, | 
| -                          audio->shm_size_, | 
| +    audio->user_callback_(audio->audio_buffer_.get(), | 
| +                          audio->audio_buffer_size_, | 
| audio->user_data_); | 
| + | 
| +    // Deinterleave the audio data into the shared memory as float. | 
| +    audio->audio_bus_->FromInterleaved( | 
| +        audio->audio_buffer_.get(), audio->audio_bus_->frames(), | 
| +        kBytesPerSample); | 
| + | 
| // Signal audio backend by writing buffer length at end of buffer. | 
| // (Note: NaCl applications will always write the entire buffer.) | 
| media::SetActualDataSizeInBytes(audio->shm_buffer_, | 
| @@ -112,6 +126,14 @@ void PluginAudio::StreamCreated(NaClSrpcImcDescType socket, | 
| shm, | 
| 0); | 
| if (MAP_FAILED != shm_buffer_) { | 
| +    // Deduce the frame count from the size using hard coded channel count. | 
| +    audio_bus_ = media::AudioBus::WrapMemory( | 
| +        kChannels, shm_size_ / (sizeof(float) * kChannels), shm_buffer_); | 
| +    // Setup integer audio buffer for user audio data. | 
| +    audio_buffer_size_ = | 
| +        audio_bus_->frames() * audio_bus_->channels() * kBytesPerSample; | 
| +    audio_buffer_.reset(new uint8_t[audio_buffer_size_]); | 
| + | 
| if (state() == AUDIO_PENDING) { | 
| StartAudioThread(); | 
| } else { | 
| @@ -126,6 +148,7 @@ bool PluginAudio::StartAudioThread() { | 
| // clear contents of shm buffer before spinning up audio thread | 
| DebugPrintf("PluginAudio::StartAudioThread\n"); | 
| memset(shm_buffer_, 0, shm_size_); | 
| +  memset(audio_buffer_.get(), 0, audio_buffer_size_); | 
| const struct PP_ThreadFunctions* thread_funcs = GetThreadCreator(); | 
| if (NULL == thread_funcs->thread_create || | 
| NULL == thread_funcs->thread_join) { | 
|  |