Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/shared_impl/ppb_audio_shared.h" | 5 #include "ppapi/shared_impl/ppb_audio_shared.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "ppapi/shared_impl/ppapi_globals.h" | 8 #include "ppapi/shared_impl/ppapi_globals.h" |
| 9 #include "ppapi/shared_impl/ppb_audio_config_shared.h" | 9 #include "ppapi/shared_impl/ppb_audio_config_shared.h" |
| 10 #include "ppapi/shared_impl/proxy_lock.h" | 10 #include "ppapi/shared_impl/proxy_lock.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 socket_->Shutdown(); | 66 socket_->Shutdown(); |
| 67 StopThread(); | 67 StopThread(); |
| 68 } | 68 } |
| 69 | 69 |
| 70 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, | 70 void PPB_Audio_Shared::SetCallback(const AudioCallbackCombined& callback, |
| 71 void* user_data) { | 71 void* user_data) { |
| 72 callback_ = callback; | 72 callback_ = callback; |
| 73 user_data_ = user_data; | 73 user_data_ = user_data; |
| 74 } | 74 } |
| 75 | 75 |
| 76 void PPB_Audio_Shared::SetStartPlaybackState() { | 76 bool PPB_Audio_Shared::SetStartPlaybackState() { |
| 77 DCHECK(!playing_); | 77 DCHECK(!playing_); |
| 78 #if !defined(OS_NACL) | 78 #if !defined(OS_NACL) |
| 79 DCHECK(!audio_thread_.get()); | 79 DCHECK(!audio_thread_.get()); |
| 80 #else | 80 #else |
| 81 DCHECK(!thread_active_); | 81 DCHECK(!thread_active_); |
| 82 #endif | 82 #endif |
| 83 // If the socket doesn't exist, that means that the plugin has started before | 83 // If the socket doesn't exist, that means that the plugin has started before |
| 84 // the browser has had a chance to create all the shared memory info and | 84 // the browser has had a chance to create all the shared memory info and |
| 85 // notify us. This is a common case. In this case, we just set the playing_ | 85 // notify us. This is a common case. In this case, we just set the playing_ |
| 86 // flag and the playback will automatically start when that data is available | 86 // flag and the playback will automatically start when that data is available |
| 87 // in SetStreamInfo. | 87 // in SetStreamInfo. |
| 88 // If StartThread() returns false, it means no thread creator is set yet. | |
| 89 // In such a case, we do not set playing state, because even if SetStreamInfo | |
| 90 // is invoked later, we cannot create a thread. | |
| 91 // Note that StartThread returns true even if socket doesn't exist as it is | |
|
bbudge
2014/04/18 13:34:40
I think this last sentence just repeats the commen
hidehiko
2014/04/18 18:16:30
Acknowledged.
| |
| 92 // common situation as descibed above. | |
| 88 playing_ = true; | 93 playing_ = true; |
| 89 StartThread(); | 94 if (!StartThread()) |
| 95 playing_ = false; | |
| 96 return playing_; | |
| 90 } | 97 } |
| 91 | 98 |
| 92 void PPB_Audio_Shared::SetStopPlaybackState() { | 99 void PPB_Audio_Shared::SetStopPlaybackState() { |
| 93 DCHECK(playing_); | 100 DCHECK(playing_); |
| 94 StopThread(); | 101 StopThread(); |
| 95 playing_ = false; | 102 playing_ = false; |
| 96 } | 103 } |
| 97 | 104 |
| 98 void PPB_Audio_Shared::SetStreamInfo( | 105 void PPB_Audio_Shared::SetStreamInfo( |
| 99 PP_Instance instance, | 106 PP_Instance instance, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 120 kAudioOutputChannels, sample_frame_count, shared_memory_->memory()); | 127 kAudioOutputChannels, sample_frame_count, shared_memory_->memory()); |
| 121 // Setup integer audio buffer for user audio data. | 128 // Setup integer audio buffer for user audio data. |
| 122 client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() * | 129 client_buffer_size_bytes_ = audio_bus_->frames() * audio_bus_->channels() * |
| 123 kBitsPerAudioOutputSample / 8; | 130 kBitsPerAudioOutputSample / 8; |
| 124 client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); | 131 client_buffer_.reset(new uint8_t[client_buffer_size_bytes_]); |
| 125 } | 132 } |
| 126 | 133 |
| 127 StartThread(); | 134 StartThread(); |
| 128 } | 135 } |
| 129 | 136 |
| 130 void PPB_Audio_Shared::StartThread() { | 137 bool PPB_Audio_Shared::StartThread() { |
| 138 #if defined(OS_NACL) | |
| 139 // Use NaCl's special API for IRT code that creates threads that call back | |
| 140 // into user code. | |
| 141 if (NULL == thread_functions.thread_create || | |
| 142 NULL == thread_functions.thread_join) | |
| 143 return false; | |
| 144 #endif | |
| 145 | |
| 131 // Don't start the thread unless all our state is set up correctly. | 146 // Don't start the thread unless all our state is set up correctly. |
| 132 if (!playing_ || !callback_.IsValid() || !socket_.get() || | 147 if (!playing_ || !callback_.IsValid() || !socket_.get() || |
| 133 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || | 148 !shared_memory_->memory() || !audio_bus_.get() || !client_buffer_.get() || |
| 134 bytes_per_second_ == 0) | 149 bytes_per_second_ == 0) |
| 135 return; | 150 return true; |
| 151 | |
| 136 // Clear contents of shm buffer before starting audio thread. This will | 152 // Clear contents of shm buffer before starting audio thread. This will |
| 137 // prevent a burst of static if for some reason the audio thread doesn't | 153 // prevent a burst of static if for some reason the audio thread doesn't |
| 138 // start up quickly enough. | 154 // start up quickly enough. |
| 139 memset(shared_memory_->memory(), 0, shared_memory_size_); | 155 memset(shared_memory_->memory(), 0, shared_memory_size_); |
| 140 memset(client_buffer_.get(), 0, client_buffer_size_bytes_); | 156 memset(client_buffer_.get(), 0, client_buffer_size_bytes_); |
| 141 #if !defined(OS_NACL) | 157 #if !defined(OS_NACL) |
| 142 DCHECK(!audio_thread_.get()); | 158 DCHECK(!audio_thread_.get()); |
| 143 audio_thread_.reset( | 159 audio_thread_.reset( |
| 144 new base::DelegateSimpleThread(this, "plugin_audio_thread")); | 160 new base::DelegateSimpleThread(this, "plugin_audio_thread")); |
| 145 audio_thread_->Start(); | 161 audio_thread_->Start(); |
| 146 #else | 162 #else |
| 147 // Use NaCl's special API for IRT code that creates threads that call back | 163 DCHECK(!thread_active_); |
| 148 // into user code. | |
| 149 if (NULL == thread_functions.thread_create || | |
| 150 NULL == thread_functions.thread_join) | |
| 151 return; | |
| 152 | |
| 153 int result = thread_functions.thread_create(&thread_id_, CallRun, this); | 164 int result = thread_functions.thread_create(&thread_id_, CallRun, this); |
| 154 DCHECK_EQ(result, 0); | 165 DCHECK_EQ(result, 0); |
| 155 thread_active_ = true; | 166 thread_active_ = true; |
| 156 #endif | 167 #endif |
| 168 return true; | |
| 157 } | 169 } |
| 158 | 170 |
| 159 void PPB_Audio_Shared::StopThread() { | 171 void PPB_Audio_Shared::StopThread() { |
| 160 #if !defined(OS_NACL) | 172 #if !defined(OS_NACL) |
| 161 if (audio_thread_.get()) { | 173 if (audio_thread_.get()) { |
| 162 // In general, the audio thread should not do Pepper calls, but it might | 174 // In general, the audio thread should not do Pepper calls, but it might |
| 163 // anyway (for example, our Audio test does CallOnMainThread). If it did | 175 // anyway (for example, our Audio test does CallOnMainThread). If it did |
| 164 // a pepper call which acquires the lock (most of them do), and we try to | 176 // a pepper call which acquires the lock (most of them do), and we try to |
| 165 // shut down the thread and Join it while holding the lock, we would | 177 // shut down the thread and Join it while holding the lock, we would |
| 166 // deadlock. So we give up the lock here so that the thread at least _can_ | 178 // deadlock. So we give up the lock here so that the thread at least _can_ |
| 167 // make Pepper calls without causing deadlock. | 179 // make Pepper calls without causing deadlock. |
| 168 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, | 180 CallWhileUnlocked(base::Bind(&base::DelegateSimpleThread::Join, |
| 169 base::Unretained(audio_thread_.get()))); | 181 base::Unretained(audio_thread_.get()))); |
| 170 audio_thread_.reset(); | 182 audio_thread_.reset(); |
| 171 } | 183 } |
| 172 #else | 184 #else |
| 173 if (thread_active_) { | 185 if (thread_active_) { |
| 174 // See comment above about why we unlock here. | 186 // See comment above about why we unlock here. |
| 175 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); | 187 int result = CallWhileUnlocked(thread_functions.thread_join, thread_id_); |
| 176 DCHECK_EQ(0, result); | 188 DCHECK_EQ(0, result); |
| 177 thread_active_ = false; | 189 thread_active_ = false; |
| 178 } | 190 } |
| 179 #endif | 191 #endif |
| 180 } | 192 } |
| 181 | 193 |
| 182 #if defined(OS_NACL) | 194 #if defined(OS_NACL) |
| 183 // static | 195 // static |
| 184 void PPB_Audio_Shared::SetThreadFunctions( | 196 void PPB_Audio_Shared::SetThreadFunctions( |
| 185 const struct PP_ThreadFunctions* functions) { | 197 const struct PP_ThreadFunctions* functions) { |
| 186 DCHECK(thread_functions.thread_create == NULL); | |
| 187 DCHECK(thread_functions.thread_join == NULL); | |
| 188 thread_functions = *functions; | 198 thread_functions = *functions; |
| 189 } | 199 } |
| 190 | 200 |
| 191 // static | 201 // static |
| 192 void PPB_Audio_Shared::CallRun(void* self) { | 202 void PPB_Audio_Shared::CallRun(void* self) { |
| 193 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); | 203 PPB_Audio_Shared* audio = static_cast<PPB_Audio_Shared*>(self); |
| 194 audio->Run(); | 204 audio->Run(); |
| 195 } | 205 } |
| 196 #endif | 206 #endif |
| 197 | 207 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 218 // Let the other end know which buffer we just filled. The buffer index is | 228 // Let the other end know which buffer we just filled. The buffer index is |
| 219 // used to ensure the other end is getting the buffer it expects. For more | 229 // used to ensure the other end is getting the buffer it expects. For more |
| 220 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). | 230 // details on how this works see AudioSyncReader::WaitUntilDataIsReady(). |
| 221 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); | 231 size_t bytes_sent = socket_->Send(&buffer_index_, sizeof(buffer_index_)); |
| 222 if (bytes_sent != sizeof(buffer_index_)) | 232 if (bytes_sent != sizeof(buffer_index_)) |
| 223 break; | 233 break; |
| 224 } | 234 } |
| 225 } | 235 } |
| 226 | 236 |
| 227 } // namespace ppapi | 237 } // namespace ppapi |
| OLD | NEW |