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