1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ppapi/shared_impl/ppb_audio_shared.h" 6 7 #include "base/logging.h" 8 #include "ppapi/shared_impl/ppapi_globals.h" 9 #include "ppapi/shared_impl/ppb_audio_config_shared.h" 10 #include "ppapi/shared_impl/proxy_lock.h" 11 12 namespace ppapi { 13 14 #if defined(OS_NACL) 15 namespace { 16 // Because this is static, the function pointers will be NULL initially. 17 PP_ThreadFunctions thread_functions; 18 } 19 #endif // defined(OS_NACL) 20 21 AudioCallbackCombined::AudioCallbackCombined() : callback_1_0_(NULL), 22 callback_(NULL) { 23 } 24 25 AudioCallbackCombined::AudioCallbackCombined( 26 PPB_Audio_Callback_1_0 callback_1_0) 27 : callback_1_0_(callback_1_0), 28 callback_(NULL) { 29 } 30 31 AudioCallbackCombined::AudioCallbackCombined(PPB_Audio_Callback callback) 32 : callback_1_0_(NULL), 33 callback_(callback) { 34 } 35 36 AudioCallbackCombined::~AudioCallbackCombined() { 37 } 38 39 bool AudioCallbackCombined::IsValid() const { 40 return callback_1_0_ || callback_; 41 } 42 43 void AudioCallbackCombined::Run(void* sample_buffer, 44 uint32_t buffer_size_in_bytes, 45 PP_TimeDelta latency, 46 void* user_data) const { 47 if (callback_) { 48 callback_(sample_buffer, buffer_size_in_bytes, latency, user_data); 49 } else if (callback_1_0_) { 50 callback_1_0_(sample_buffer, buffer_size_in_bytes, user_data); 51 } else { 52 NOTREACHED(); 53 } 54 } 55 56 PPB_Audio_Shared::PPB_Audio_Shared() 57 : playing_(false), 58 shared_memory_size_(0), 59 #if defined(OS_NACL) 60 thread_id_(0), 61 thread_active_(false), 62 #endif 63 user_data_(NULL), 64 client_buffer_size_bytes_(0), 65 bytes_per_second_(0), 66 buffer_index_(0) { 67 } 68 69 PPB_Audio_Shared::~PPB_Audio_Shared() { 70 // Shut down the socket to escape any hanging |Receive|s. 71 if (socket_.get()) 72 socket_->Shutdown(); 73 StopThread(); 74 } 75 76 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, 77 void* user_data) { 78 callback_ = callback; 79 user_data_ = user_data; 80 } 81 82 void PPB_Audio_Shared::SetStartPlaybackState() { 83 DCHECK(!playing_); 84 #if !defined(OS_NACL) 85 DCHECK(!audio_thread_.get()); 86 #else 87 DCHECK(!thread_active_); 88 #endif 89 // If the socket doesn't exist, that means that the plugin has started before 90 // the browser has had a chance to create all the shared memory info and 91 // notify us. This is a common case. In this case, we just set the playing_ 92 // flag and the playback will automatically start when that data is available 93 // in SetStreamInfo. 94 playing_ = true; 95 StartThread(); 96 } 97 98 void PPB_Audio_Shared::SetStopPlaybackState() { 99 DCHECK(playing_); 100 StopThread(); 101 playing_ = false; 102 } 103 104 void PPB_Audio_Shared::SetStreamInfo( 105 PP_Instance instance, 106 base::SharedMemoryHandle shared_memory_handle, 107 size_t shared_memory_size, 108 base::SyncSocket::Handle socket_handle, 109 PP_AudioSampleRate sample_rate, 110 int sample_frame_count) { 111 socket_.reset(new base::CancelableSyncSocket(socket_handle)); 112 shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); 113 shared_memory_size_ = shared_memory_size; 114 bytes_per_second_ = kAudioOutputChannels * (kBitsPerAudioOutputSample / 8) * 115 sample_rate; 116 buffer_index_ = 0; 117 118 if (!shared_memory_->Map(shared_memory_size_)) { 119 PpapiGlobals::Get()->LogWithSource( 120 instance, 121 PP_LOGLEVEL_WARNING, 122 std::string(), 123 "Failed to map shared memory for PPB_Audio_Shared."); 124 } else { 125 audio_bus_ = media::AudioBus::WrapMemory( 126 kAudioOutputChannels, sample_frame_count, shared_memory_->memory()); 127 // Setup integer audio buffer for user audio data. 128 client_buffer_size_bytes_ = 129 audio_bus_->frames() * audio_bus_->channels() * 130 kBitsPerAudioOutputSample / 8; 131 client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); 132 } 133 134 StartThread(); 135 } 136 137 void PPB_Audio_Shared::StartThread() { 138 // Don't start the thread unless all our state is set up correctly. 139 if (!playing_ || !callback_.IsValid() || !socket_.get() || 140 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || 141 bytes_per_second_ == 0) 142 return; 143 // Clear contents of shm buffer before starting audio thread. This will 144 // prevent a burst of static if for some reason the audio thread doesn't 145 // start up quickly enough. 146 memset(shared_memory_->memory(), 0, shared_memory_size_); 147 memset(client_buffer_.get(), 0, client_buffer_size_bytes_); 148 #if !defined(OS_NACL) 149 DCHECK(!audio_thread_.get()); 150 audio_thread_.reset(new base::DelegateSimpleThread( 151 this, "plugin_audio_thread")); 152 audio_thread_->Start(); 153 #else 154 // Use NaCl's special API for IRT code that creates threads that call back 155 // into user code. 156 if (NULL == thread_functions.thread_create || 157 NULL == thread_functions.thread_join) 158 return; 159 160 int result = thread_functions.thread_create(&thread_id_, CallRun, this); 161 DCHECK_EQ(result, 0); 162 thread_active_ = true; 163 #endif 164 } 165 166 void PPB_Audio_Shared::StopThread() { 167 #if !defined(OS_NACL) 168 if (audio_thread_.get()) { 169 // In general, the audio thread should not do Pepper calls, but it might 170 // anyway (for example, our Audio test does CallOnMainThread). If it did 171 // a pepper call which acquires the lock (most of them do), and we try to 172 // shut down the thread and Join it while holding the lock, we would 173 // deadlock. So we give up the lock here so that the thread at least _can_ 174 // make Pepper calls without causing deadlock. 175 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, 176 base::Unretained(audio_thread_.get()))); 177 audio_thread_.reset(); 178 } 179 #else 180 if (thread_active_) { 181 // See comment above about why we unlock here. 182 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); 183 DCHECK_EQ(0, result); 184 thread_active_ = false; 185 } 186 #endif 187 } 188 189 #if defined(OS_NACL) 190 // static 191 void PPB_Audio_Shared::SetThreadFunctions( 192 const struct PP_ThreadFunctions* functions) { 193 DCHECK(thread_functions.thread_create == NULL); 194 DCHECK(thread_functions.thread_join == NULL); 195 thread_functions = *functions; 196 } 197 198 // static 199 void PPB_Audio_Shared::CallRun(void* self) { 200 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); 201 audio->Run(); 202 } 203 #endif 204 205 void PPB_Audio_Shared::Run() { 206 int pending_data = 0; 207 while (sizeof(pending_data) == 208 socket_->Receive(&pending_data, sizeof(pending_data))) { 209 // |buffer_index_| must track the number of Receive() calls. See the Send() 210 // call below for why this is important. 211 ++buffer_index_; 212 if (pending_data < 0) 213 break; 214 215 PP_TimeDelta latency = 216 static_cast<double>(pending_data) / bytes_per_second_; 217 callback_.Run(client_buffer_.get(), client_buffer_size_bytes_, latency, 218 user_data_); 219 220 // Deinterleave the audio data into the shared memory as floats. 221 audio_bus_->FromInterleaved( 222 client_buffer_.get(), audio_bus_->frames(), 223 kBitsPerAudioOutputSample / 8); 224 225 // Let the other end know which buffer we just filled. The buffer index is 226 // used to ensure the other end is getting the buffer it expects. For more 227 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). 228 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); 229 if (bytes_sent != sizeof(buffer_index_)) 230 break; 231 } 232 } 233 234 } // namespace ppapi 235