15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppb_audio_shared.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/debug/trace_event.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ppapi/nacl_irt/public/irt_ppapi.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ppapi/shared_impl/ppb_audio_config_shared.h" 1258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "ppapi/shared_impl/proxy_lock.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool g_nacl_mode = false; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because this is static, the function pointers will be NULL initially. 190529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochPP_ThreadFunctions g_thread_functions; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AudioCallbackCombined::AudioCallbackCombined() 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : callback_1_0_(NULL), callback_(NULL) {} 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)AudioCallbackCombined::AudioCallbackCombined( 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PPB_Audio_Callback_1_0 callback_1_0) 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : callback_1_0_(callback_1_0), callback_(NULL) {} 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback) 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : callback_1_0_(NULL), callback_(callback) {} 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AudioCallbackCombined::~AudioCallbackCombined() {} 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool AudioCallbackCombined::IsValid() const { 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return callback_1_0_ || callback_; 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void AudioCallbackCombined::Run(void* sample_buffer, 3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) uint32_t buffer_size_in_bytes, 4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_TimeDelta latency, 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void* user_data) const { 4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (callback_) { 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callback_(sample_buffer, buffer_size_in_bytes, latency, user_data); 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else if (callback_1_0_) { 4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data); 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NOTREACHED(); 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Shared::PPB_Audio_Shared() 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : playing_(false), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_size_(0), 540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_thread_active_(false), 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_data_(NULL), 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) client_buffer_size_bytes_(0), 570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bytes_per_second_(0), 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) buffer_index_(0) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Shared::~PPB_Audio_Shared() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shut down the socket to escape any hanging |Receive|s. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_.get()) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->Shutdown(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopThread(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* user_data) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_data_ = user_data; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::SetStartPlaybackState() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!playing_); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_thread_.get()); 770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!nacl_thread_active_); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the socket doesn't exist, that means that the plugin has started before 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the browser has had a chance to create all the shared memory info and 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notify us. This is a common case. In this case, we just set the playing_ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flag and the playback will automatically start when that data is available 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in SetStreamInfo. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = true; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartThread(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::SetStopPlaybackState() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(playing_); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopThread(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::SetStreamInfo( 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PP_Instance instance, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle shared_memory_handle, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t shared_memory_size, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket::Handle socket_handle, 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PP_AudioSampleRate sample_rate, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_frame_count) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_.reset(new base::CancelableSyncSocket(socket_handle)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_size_ = shared_memory_size; 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_per_second_ = 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kAudioOutputChannels * (kBitsPerAudioOutputSample / 8) * sample_rate; 1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) buffer_index_ = 0; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!shared_memory_->Map(shared_memory_size_)) { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PpapiGlobals::Get()->LogWithSource( 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) instance, 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PP_LOGLEVEL_WARNING, 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "Failed to map shared memory for PPB_Audio_Shared."); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_ = media::AudioBus::WrapMemory( 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) kAudioOutputChannels, sample_frame_count, shared_memory_->memory()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup integer audio buffer for user audio data. 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() * 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kBitsPerAudioOutputSample / 8; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartThread(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::StartThread() { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't start the thread unless all our state is set up correctly. 12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!playing_ || !callback_.IsValid() || !socket_.get() || 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bytes_per_second_ == 0) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Clear contents of shm buffer before starting audio thread. This will 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prevent a burst of static if for some reason the audio thread doesn't 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start up quickly enough. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(shared_memory_->memory(), 0, shared_memory_size_); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(client_buffer_.get(), 0, client_buffer_size_bytes_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (g_nacl_mode) { 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Use NaCl's special API for IRT code that creates threads that call back 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // into user code. 1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!IsThreadFunctionReady()) 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!nacl_thread_active_); 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int result = 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_thread_functions.thread_create(&nacl_thread_id_, CallRun, this); 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(0, result); 1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_thread_active_ = true; 1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!audio_thread_.get()); 1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_thread_.reset( 1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new base::DelegateSimpleThread(this, "plugin_audio_thread")); 1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_thread_->Start(); 1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::StopThread() { 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // In general, the audio thread should not do Pepper calls, but it might 1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // anyway (for example, our Audio test does CallOnMainThread). If it did a 1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // pepper call which acquires the lock (most of them do), and we try to shut 1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // down the thread and Join it while holding the lock, we would deadlock. So 1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // we give up the lock here so that the thread at least _can_ make Pepper 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // calls without causing deadlock. 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (g_nacl_mode) { 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (nacl_thread_active_) { 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch int result = 1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CallWhileUnlocked(g_thread_functions.thread_join, nacl_thread_id_); 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK_EQ(0, result); 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch nacl_thread_active_ = false; 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (audio_thread_.get()) { 1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Unretained(audio_thread_.get()))); 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch audio_thread_.reset(); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// static 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbool PPB_Audio_Shared::IsThreadFunctionReady() { 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!g_nacl_mode) 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return true; 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return (g_thread_functions.thread_create != NULL && 1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_thread_functions.thread_join != NULL); 1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// static 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid PPB_Audio_Shared::SetNaClMode() { 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_nacl_mode = true; 1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::SetThreadFunctions( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct PP_ThreadFunctions* functions) { 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(g_nacl_mode); 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch g_thread_functions = *functions; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::CallRun(void* self) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio->Run(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Shared::Run() { 2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int pending_data = 0; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (sizeof(pending_data) == 2090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) socket_->Receive(&pending_data, sizeof(pending_data))) { 2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // |buffer_index_| must track the number of Receive() calls. See the Send() 2110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // call below for why this is important. 2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ++buffer_index_; 2130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (pending_data < 0) 2140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) { 21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) TRACE_EVENT0("audio", "PPB_Audio_Shared::FireRenderCallback"); 21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PP_TimeDelta latency = 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) static_cast<double>(pending_data) / bytes_per_second_; 22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) callback_.Run( 22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) client_buffer_.get(), client_buffer_size_bytes_, latency, user_data_); 22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Deinterleave the audio data into the shared memory as floats. 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus_->FromInterleaved(client_buffer_.get(), 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus_->frames(), 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kBitsPerAudioOutputSample / 8); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Let the other end know which buffer we just filled. The buffer index is 2300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // used to ensure the other end is getting the buffer it expects. For more 2310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). 2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); 2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (bytes_sent != sizeof(buffer_index_)) 2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ppapi 239