Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: webkit/glue/plugins/pepper_audio.cc

Issue 4985001: Initial audio implementation. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/pepper_audio.h ('k') | webkit/glue/plugins/pepper_font.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_audio.h" 5 #include "webkit/glue/plugins/pepper_audio.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "ppapi/c/dev/ppb_audio_dev.h" 8 #include "ppapi/c/dev/ppb_audio_dev.h"
9 #include "ppapi/c/dev/ppb_audio_trusted_dev.h" 9 #include "ppapi/c/dev/ppb_audio_trusted_dev.h"
10 #include "ppapi/c/pp_completion_callback.h" 10 #include "ppapi/c/pp_completion_callback.h"
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 user_callback, user_data)) 89 user_callback, user_data))
90 return 0; 90 return 0;
91 return audio->GetReference(); 91 return audio->GetReference();
92 } 92 }
93 93
94 PP_Bool IsAudio(PP_Resource resource) { 94 PP_Bool IsAudio(PP_Resource resource) {
95 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(resource); 95 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(resource);
96 return BoolToPPBool(!!audio); 96 return BoolToPPBool(!!audio);
97 } 97 }
98 98
99 PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { 99 PP_Resource GetCurrentConfig(PP_Resource audio_id) {
100 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); 100 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
101 return audio ? audio->GetCurrentConfiguration() : 0; 101 return audio ? audio->GetCurrentConfig() : 0;
102 } 102 }
103 103
104 PP_Bool StartPlayback(PP_Resource audio_id) { 104 PP_Bool StartPlayback(PP_Resource audio_id) {
105 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); 105 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
106 return audio ? BoolToPPBool(audio->StartPlayback()) : PP_FALSE; 106 return audio ? BoolToPPBool(audio->StartPlayback()) : PP_FALSE;
107 } 107 }
108 108
109 PP_Bool StopPlayback(PP_Resource audio_id) { 109 PP_Bool StopPlayback(PP_Resource audio_id) {
110 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); 110 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
111 return audio ? BoolToPPBool(audio->StopPlayback()) : PP_FALSE; 111 return audio ? BoolToPPBool(audio->StopPlayback()) : PP_FALSE;
112 } 112 }
113 113
114 const PPB_Audio_Dev ppb_audio = { 114 const PPB_Audio_Dev ppb_audio = {
115 &Create, 115 &Create,
116 &IsAudio, 116 &IsAudio,
117 &GetCurrentConfiguration, 117 &GetCurrentConfig,
118 &StartPlayback, 118 &StartPlayback,
119 &StopPlayback, 119 &StopPlayback,
120 }; 120 };
121 121
122 // PPB_AudioTrusted ------------------------------------------------------------ 122 // PPB_AudioTrusted ------------------------------------------------------------
123 123
124 PP_Resource CreateTrusted(PP_Instance instance_id) { 124 PP_Resource CreateTrusted(PP_Instance instance_id) {
125 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); 125 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
126 if (!instance) 126 if (!instance)
127 return 0; 127 return 0;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 194 }
195 195
196 AudioConfig* AudioConfig::AsAudioConfig() { 196 AudioConfig* AudioConfig::AsAudioConfig() {
197 return this; 197 return this;
198 } 198 }
199 199
200 // Audio ----------------------------------------------------------------------- 200 // Audio -----------------------------------------------------------------------
201 201
202 Audio::Audio(PluginModule* module, PP_Instance instance_id) 202 Audio::Audio(PluginModule* module, PP_Instance instance_id)
203 : Resource(module), 203 : Resource(module),
204 playing_(false),
205 pp_instance_(instance_id), 204 pp_instance_(instance_id),
206 audio_(NULL), 205 audio_(NULL),
207 socket_(NULL),
208 shared_memory_(NULL),
209 shared_memory_size_(0),
210 callback_(NULL),
211 user_data_(NULL),
212 create_callback_pending_(false) { 206 create_callback_pending_(false) {
213 create_callback_ = PP_MakeCompletionCallback(NULL, NULL); 207 create_callback_ = PP_MakeCompletionCallback(NULL, NULL);
214 } 208 }
215 209
216 Audio::~Audio() { 210 Audio::~Audio() {
217 // Calling ShutDown() makes sure StreamCreated cannot be called anymore. 211 // Calling ShutDown() makes sure StreamCreated cannot be called anymore.
218 audio_->ShutDown(); 212 audio_->ShutDown();
219 audio_ = NULL; 213 audio_ = NULL;
220 214
221 // Closing the socket causes the thread to exit - wait for it.
222 socket_->Close();
223 if (audio_thread_.get()) {
224 audio_thread_->Join();
225 audio_thread_.reset();
226 }
227
228 // If the completion callback hasn't fired yet, do so here 215 // If the completion callback hasn't fired yet, do so here
229 // with an error condition. 216 // with an error condition.
230 if (create_callback_pending_) { 217 if (create_callback_pending_) {
231 PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED); 218 PP_RunCompletionCallback(&create_callback_, PP_ERROR_ABORTED);
232 create_callback_pending_ = false; 219 create_callback_pending_ = false;
233 } 220 }
234 // Shared memory destructor will unmap the memory automatically.
235 } 221 }
236 222
237 const PPB_Audio_Dev* Audio::GetInterface() { 223 const PPB_Audio_Dev* Audio::GetInterface() {
238 return &ppb_audio; 224 return &ppb_audio;
239 } 225 }
240 226
241 const PPB_AudioTrusted_Dev* Audio::GetTrustedInterface() { 227 const PPB_AudioTrusted_Dev* Audio::GetTrustedInterface() {
242 return &ppb_audiotrusted; 228 return &ppb_audiotrusted;
243 } 229 }
244 230
245 Audio* Audio::AsAudio() { 231 Audio* Audio::AsAudio() {
246 return this; 232 return this;
247 } 233 }
248 234
249 bool Audio::Init(PluginDelegate* plugin_delegate, 235 bool Audio::Init(PluginDelegate* plugin_delegate,
250 PP_Resource config_id, 236 PP_Resource config_id,
251 PPB_Audio_Callback callback, void* user_data) { 237 PPB_Audio_Callback callback, void* user_data) {
252 CHECK(!audio_); 238 CHECK(!audio_);
253 config_ = Resource::GetAs<AudioConfig>(config_id); 239 config_ = Resource::GetAs<AudioConfig>(config_id);
254 if (!config_) 240 if (!config_)
255 return false; 241 return false;
256 callback_ = callback; 242 SetCallback(callback, user_data);
257 user_data_ = user_data;
258 243
259 // When the stream is created, we'll get called back on StreamCreated(). 244 // When the stream is created, we'll get called back on StreamCreated().
260 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(), 245 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(),
261 config_->sample_frame_count(), 246 config_->sample_frame_count(),
262 this); 247 this);
263 return audio_ != NULL; 248 return audio_ != NULL;
264 } 249 }
265 250
251 PP_Resource Audio::GetCurrentConfig() {
252 return config_->GetReference();
253 }
254
255 bool Audio::StartPlayback() {
256 if (playing())
257 return true;
258 SetStartPlaybackState();
259 return audio_->StartPlayback();
260 }
261
262 bool Audio::StopPlayback() {
263 if (!playing())
264 return true;
265 if (!audio_->StopPlayback())
266 return false;
267 SetStopPlaybackState();
268 return true;
269 }
270
266 int32_t Audio::Open(PluginDelegate* plugin_delegate, 271 int32_t Audio::Open(PluginDelegate* plugin_delegate,
267 PP_Resource config_id, 272 PP_Resource config_id,
268 PP_CompletionCallback create_callback) { 273 PP_CompletionCallback create_callback) {
269 DCHECK(!audio_); 274 DCHECK(!audio_);
270 config_ = Resource::GetAs<AudioConfig>(config_id); 275 config_ = Resource::GetAs<AudioConfig>(config_id);
271 if (!config_) 276 if (!config_)
272 return PP_ERROR_BADRESOURCE; 277 return PP_ERROR_BADRESOURCE;
273 278
274 // When the stream is created, we'll get called back on StreamCreated(). 279 // When the stream is created, we'll get called back on StreamCreated().
275 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(), 280 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(),
276 config_->sample_frame_count(), 281 config_->sample_frame_count(),
277 this); 282 this);
278 if (!audio_) 283 if (!audio_)
279 return PP_ERROR_FAILED; 284 return PP_ERROR_FAILED;
280 285
281 // At this point, we are guaranteeing ownership of the completion 286 // At this point, we are guaranteeing ownership of the completion
282 // callback. Audio promises to fire the completion callback 287 // callback. Audio promises to fire the completion callback
283 // once and only once. 288 // once and only once.
284 create_callback_ = create_callback; 289 create_callback_ = create_callback;
285 create_callback_pending_ = true; 290 create_callback_pending_ = true;
286 return PP_ERROR_WOULDBLOCK; 291 return PP_ERROR_WOULDBLOCK;
287 } 292 }
288 293
289 int32_t Audio::GetSyncSocket(int* sync_socket) { 294 int32_t Audio::GetSyncSocket(int* sync_socket) {
290 if (socket_ != NULL) { 295 if (socket_for_create_callback_.get()) {
291 #if defined(OS_POSIX) 296 #if defined(OS_POSIX)
292 *sync_socket = socket_->handle(); 297 *sync_socket = socket_for_create_callback_->handle();
293 #elif defined(OS_WIN) 298 #elif defined(OS_WIN)
294 *sync_socket = reinterpret_cast<int>(socket_->handle()); 299 *sync_socket = reinterpret_cast<int>(socket_for_create_callback_->handle());
295 #else 300 #else
296 #error "Platform not supported." 301 #error "Platform not supported."
297 #endif 302 #endif
298 return PP_OK; 303 return PP_OK;
299 } 304 }
300 return PP_ERROR_FAILED; 305 return PP_ERROR_FAILED;
301 } 306 }
302 307
303 int32_t Audio::GetSharedMemory(int* shm_handle, uint32_t* shm_size) { 308 int32_t Audio::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
304 if (shared_memory_ != NULL) { 309 if (shared_memory_for_create_callback_.get()) {
305 #if defined(OS_POSIX) 310 #if defined(OS_POSIX)
306 *shm_handle = shared_memory_->handle().fd; 311 *shm_handle = shared_memory_for_create_callback_->handle().fd;
307 #elif defined(OS_WIN) 312 #elif defined(OS_WIN)
308 *shm_handle = reinterpret_cast<int>(shared_memory_->handle()); 313 *shm_handle = reinterpret_cast<int>(
314 shared_memory_handle_for_create_callback_->handle());
309 #else 315 #else
310 #error "Platform not supported." 316 #error "Platform not supported."
311 #endif 317 #endif
312 *shm_size = shared_memory_size_; 318 *shm_size = shared_memory_size_for_create_callback_;
313 return PP_OK; 319 return PP_OK;
314 } 320 }
315 return PP_ERROR_FAILED; 321 return PP_ERROR_FAILED;
316 } 322 }
317 323
318 bool Audio::StartPlayback() {
319 if (playing_)
320 return true;
321
322 CHECK(!audio_thread_.get());
323 if (callback_ && socket_.get()) {
324 audio_thread_.reset(new base::DelegateSimpleThread(this,
325 "plugin_audio_thread"));
326 audio_thread_->Start();
327 }
328 playing_ = true;
329 return audio_->StartPlayback();
330 }
331
332 bool Audio::StopPlayback() {
333 if (!playing_)
334 return true;
335
336 if (!audio_->StopPlayback())
337 return false;
338
339 if (audio_thread_.get()) {
340 audio_thread_->Join();
341 audio_thread_.reset();
342 }
343 playing_ = false;
344 return true;
345 }
346
347 void Audio::StreamCreated(base::SharedMemoryHandle shared_memory_handle, 324 void Audio::StreamCreated(base::SharedMemoryHandle shared_memory_handle,
348 size_t shared_memory_size, 325 size_t shared_memory_size,
349 base::SyncSocket::Handle socket_handle) { 326 base::SyncSocket::Handle socket_handle) {
350 socket_.reset(new base::SyncSocket(socket_handle)); 327 if (create_callback_pending_) {
351 shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); 328 // Trusted side of proxy can specify a callback to recieve handles. In
352 shared_memory_size_ = shared_memory_size; 329 // this case we don't need to map any data or start the thread since it
330 // will be handled by the proxy.
331 shared_memory_for_create_callback_.reset(
332 new base::SharedMemory(shared_memory_handle, false));
333 shared_memory_size_for_create_callback_ = shared_memory_size;
334 socket_for_create_callback_.reset(new base::SyncSocket(socket_handle));
353 335
354 // Trusted side of proxy can specify a callback to recieve handles.
355 if (create_callback_pending_) {
356 PP_RunCompletionCallback(&create_callback_, 0); 336 PP_RunCompletionCallback(&create_callback_, 0);
357 create_callback_pending_ = false; 337 create_callback_pending_ = false;
358 }
359 338
360 // Trusted, non-proxy audio will invoke buffer filling callback on a 339 // Close the handles now that this process is done with them.
361 // dedicated thread, see Audio::Run() below. 340 shared_memory_for_create_callback_.reset();
362 if (callback_) { 341 shared_memory_size_for_create_callback_ = 0;
363 shared_memory_->Map(shared_memory_size_); 342 socket_for_create_callback_.reset();
364 343 } else {
365 // In common case StartPlayback() was called before StreamCreated(). 344 SetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle);
366 if (playing_) {
367 audio_thread_.reset(new base::DelegateSimpleThread(this,
368 "plugin_audio_thread"));
369 audio_thread_->Start();
370 }
371 }
372 }
373
374 void Audio::Run() {
375 int pending_data;
376 void* buffer = shared_memory_->memory();
377 size_t buffer_size_in_bytes = config_->BufferSize();
378
379 while (sizeof(pending_data) ==
380 socket_->Receive(&pending_data, sizeof(pending_data)) &&
381 pending_data >= 0) {
382 // Exit the thread on pause.
383 if (pending_data < 0)
384 return;
385 callback_(buffer, buffer_size_in_bytes, user_data_);
386 } 345 }
387 } 346 }
388 347
389 } // namespace pepper 348 } // namespace pepper
OLDNEW
« no previous file with comments | « webkit/glue/plugins/pepper_audio.h ('k') | webkit/glue/plugins/pepper_font.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698