| 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 "native_client/src/shared/ppapi_proxy/plugin_ppb_audio.h" | 5 #include "native_client/src/shared/ppapi_proxy/plugin_ppb_audio.h" |
| 6 | 6 |
| 7 #include <pthread.h> | 7 #include <pthread.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <sys/errno.h> | 10 #include <sys/errno.h> |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "srpcgen/ppp_rpc.h" | 23 #include "srpcgen/ppp_rpc.h" |
| 24 | 24 |
| 25 namespace ppapi_proxy { | 25 namespace ppapi_proxy { |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // Round size up to next 64k; required for NaCl's version of mmap(). | 28 // Round size up to next 64k; required for NaCl's version of mmap(). |
| 29 size_t ceil64k(size_t n) { | 29 size_t ceil64k(size_t n) { |
| 30 return (n + 0xFFFF) & (~0xFFFF); | 30 return (n + 0xFFFF) & (~0xFFFF); |
| 31 } | 31 } |
| 32 | 32 |
| 33 // Hard coded values from PepperPlatformAudioOutputImpl. |
| 34 // TODO(???): PPAPI shouldn't hard code these values for all clients. |
| 35 enum { kChannels = 2, kBytesPerSample = 2 }; |
| 36 |
| 33 } // namespace | 37 } // namespace |
| 34 | 38 |
| 35 PluginAudio::PluginAudio() : | 39 PluginAudio::PluginAudio() : |
| 36 resource_(kInvalidResourceId), | 40 resource_(kInvalidResourceId), |
| 37 socket_(-1), | 41 socket_(-1), |
| 38 shm_(-1), | 42 shm_(-1), |
| 39 shm_size_(0), | 43 shm_size_(0), |
| 40 shm_buffer_(NULL), | 44 shm_buffer_(NULL), |
| 41 state_(AUDIO_INCOMPLETE), | 45 state_(AUDIO_INCOMPLETE), |
| 42 thread_id_(), | 46 thread_id_(), |
| 43 thread_active_(false), | 47 thread_active_(false), |
| 44 user_callback_(NULL), | 48 user_callback_(NULL), |
| 45 user_data_(NULL) { | 49 user_data_(NULL), |
| 50 audio_buffer_size_(0) { |
| 46 DebugPrintf("PluginAudio::PluginAudio\n"); | 51 DebugPrintf("PluginAudio::PluginAudio\n"); |
| 47 } | 52 } |
| 48 | 53 |
| 49 PluginAudio::~PluginAudio() { | 54 PluginAudio::~PluginAudio() { |
| 50 DebugPrintf("PluginAudio::~PluginAudio\n"); | 55 DebugPrintf("PluginAudio::~PluginAudio\n"); |
| 51 // Ensure audio thread is not active. | 56 // Ensure audio thread is not active. |
| 52 if (resource_ != kInvalidResourceId) | 57 if (resource_ != kInvalidResourceId) |
| 53 GetInterface()->StopPlayback(resource_); | 58 GetInterface()->StopPlayback(resource_); |
| 54 // Unmap the shared memory buffer, if present. | 59 // Unmap the shared memory buffer, if present. |
| 55 if (shm_buffer_) { | 60 if (shm_buffer_) { |
| 61 audio_bus_.reset(); |
| 62 audio_buffer_.reset(); |
| 56 munmap(shm_buffer_, | 63 munmap(shm_buffer_, |
| 57 ceil64k(media::TotalSharedMemorySizeInBytes(shm_size_))); | 64 ceil64k(media::TotalSharedMemorySizeInBytes(shm_size_))); |
| 58 shm_buffer_ = NULL; | 65 shm_buffer_ = NULL; |
| 59 shm_size_ = 0; | 66 shm_size_ = 0; |
| 67 audio_buffer_size_ = 0; |
| 60 } | 68 } |
| 61 // Close the handles. | 69 // Close the handles. |
| 62 if (shm_ != -1) { | 70 if (shm_ != -1) { |
| 63 close(shm_); | 71 close(shm_); |
| 64 shm_ = -1; | 72 shm_ = -1; |
| 65 } | 73 } |
| 66 if (socket_ != -1) { | 74 if (socket_ != -1) { |
| 67 close(socket_); | 75 close(socket_); |
| 68 socket_ = -1; | 76 socket_ = -1; |
| 69 } | 77 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 80 PluginAudio* audio = static_cast<PluginAudio*>(self); | 88 PluginAudio* audio = static_cast<PluginAudio*>(self); |
| 81 DebugPrintf("PluginAudio::AudioThread: self=%p\n", self); | 89 DebugPrintf("PluginAudio::AudioThread: self=%p\n", self); |
| 82 while (true) { | 90 while (true) { |
| 83 int32_t sync_value; | 91 int32_t sync_value; |
| 84 // Block on socket read. | 92 // Block on socket read. |
| 85 ssize_t r = read(audio->socket_, &sync_value, sizeof(sync_value)); | 93 ssize_t r = read(audio->socket_, &sync_value, sizeof(sync_value)); |
| 86 // StopPlayback() will send a value of -1 over the sync_socket. | 94 // StopPlayback() will send a value of -1 over the sync_socket. |
| 87 if ((sizeof(sync_value) != r) || (-1 == sync_value)) | 95 if ((sizeof(sync_value) != r) || (-1 == sync_value)) |
| 88 break; | 96 break; |
| 89 // Invoke user callback, get next buffer of audio data. | 97 // Invoke user callback, get next buffer of audio data. |
| 90 audio->user_callback_(audio->shm_buffer_, | 98 audio->user_callback_(audio->audio_buffer_.get(), |
| 91 audio->shm_size_, | 99 audio->audio_buffer_size_, |
| 92 audio->user_data_); | 100 audio->user_data_); |
| 101 |
| 102 // Deinterleave the audio data into the shared memory as float. |
| 103 audio->audio_bus_->FromInterleaved( |
| 104 audio->audio_buffer_.get(), audio->audio_bus_->frames(), |
| 105 kBytesPerSample); |
| 106 |
| 93 // Signal audio backend by writing buffer length at end of buffer. | 107 // Signal audio backend by writing buffer length at end of buffer. |
| 94 // (Note: NaCl applications will always write the entire buffer.) | 108 // (Note: NaCl applications will always write the entire buffer.) |
| 95 media::SetActualDataSizeInBytes(audio->shm_buffer_, | 109 media::SetActualDataSizeInBytes(audio->shm_buffer_, |
| 96 audio->shm_size_, | 110 audio->shm_size_, |
| 97 audio->shm_size_); | 111 audio->shm_size_); |
| 98 } | 112 } |
| 99 } | 113 } |
| 100 | 114 |
| 101 void PluginAudio::StreamCreated(NaClSrpcImcDescType socket, | 115 void PluginAudio::StreamCreated(NaClSrpcImcDescType socket, |
| 102 NaClSrpcImcDescType shm, size_t shm_size) { | 116 NaClSrpcImcDescType shm, size_t shm_size) { |
| 103 DebugPrintf("PluginAudio::StreamCreated: shm=%"NACL_PRIu32"" | 117 DebugPrintf("PluginAudio::StreamCreated: shm=%"NACL_PRIu32"" |
| 104 " shm_size=%"NACL_PRIuS"\n", shm, shm_size); | 118 " shm_size=%"NACL_PRIuS"\n", shm, shm_size); |
| 105 socket_ = socket; | 119 socket_ = socket; |
| 106 shm_ = shm; | 120 shm_ = shm; |
| 107 shm_size_ = shm_size; | 121 shm_size_ = shm_size; |
| 108 shm_buffer_ = mmap(NULL, | 122 shm_buffer_ = mmap(NULL, |
| 109 ceil64k(media::TotalSharedMemorySizeInBytes(shm_size)), | 123 ceil64k(media::TotalSharedMemorySizeInBytes(shm_size)), |
| 110 PROT_READ | PROT_WRITE, | 124 PROT_READ | PROT_WRITE, |
| 111 MAP_SHARED, | 125 MAP_SHARED, |
| 112 shm, | 126 shm, |
| 113 0); | 127 0); |
| 114 if (MAP_FAILED != shm_buffer_) { | 128 if (MAP_FAILED != shm_buffer_) { |
| 129 // Deduce the frame count from the size using hard coded channel count. |
| 130 audio_bus_ = media::AudioBus::WrapMemory( |
| 131 kChannels, shm_size_ / (sizeof(float) * kChannels), shm_buffer_); |
| 132 // Setup integer audio buffer for user audio data. |
| 133 audio_buffer_size_ = |
| 134 audio_bus_->frames() * audio_bus_->channels() * kBytesPerSample; |
| 135 audio_buffer_.reset(new uint8_t[audio_buffer_size_]); |
| 136 |
| 115 if (state() == AUDIO_PENDING) { | 137 if (state() == AUDIO_PENDING) { |
| 116 StartAudioThread(); | 138 StartAudioThread(); |
| 117 } else { | 139 } else { |
| 118 set_state(AUDIO_READY); | 140 set_state(AUDIO_READY); |
| 119 } | 141 } |
| 120 } else { | 142 } else { |
| 121 shm_buffer_ = NULL; | 143 shm_buffer_ = NULL; |
| 122 } | 144 } |
| 123 } | 145 } |
| 124 | 146 |
| 125 bool PluginAudio::StartAudioThread() { | 147 bool PluginAudio::StartAudioThread() { |
| 126 // clear contents of shm buffer before spinning up audio thread | 148 // clear contents of shm buffer before spinning up audio thread |
| 127 DebugPrintf("PluginAudio::StartAudioThread\n"); | 149 DebugPrintf("PluginAudio::StartAudioThread\n"); |
| 128 memset(shm_buffer_, 0, shm_size_); | 150 memset(shm_buffer_, 0, shm_size_); |
| 151 memset(audio_buffer_.get(), 0, audio_buffer_size_); |
| 129 const struct PP_ThreadFunctions* thread_funcs = GetThreadCreator(); | 152 const struct PP_ThreadFunctions* thread_funcs = GetThreadCreator(); |
| 130 if (NULL == thread_funcs->thread_create || | 153 if (NULL == thread_funcs->thread_create || |
| 131 NULL == thread_funcs->thread_join) { | 154 NULL == thread_funcs->thread_join) { |
| 132 return false; | 155 return false; |
| 133 } | 156 } |
| 134 int ret = thread_funcs->thread_create(&thread_id_, AudioThread, this); | 157 int ret = thread_funcs->thread_create(&thread_id_, AudioThread, this); |
| 135 if (0 == ret) { | 158 if (0 == ret) { |
| 136 thread_active_ = true; | 159 thread_active_ = true; |
| 137 set_state(AUDIO_PLAYING); | 160 set_state(AUDIO_PLAYING); |
| 138 return true; | 161 return true; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 GetAs<ppapi_proxy::PluginAudio>(audio_resource); | 341 GetAs<ppapi_proxy::PluginAudio>(audio_resource); |
| 319 if (NULL == audio.get()) { | 342 if (NULL == audio.get()) { |
| 320 // Ignore if no audio_resource -> audio_instance mapping exists, | 343 // Ignore if no audio_resource -> audio_instance mapping exists, |
| 321 // the app may have shutdown audio before StreamCreated() invoked. | 344 // the app may have shutdown audio before StreamCreated() invoked. |
| 322 rpc->result = NACL_SRPC_RESULT_OK; | 345 rpc->result = NACL_SRPC_RESULT_OK; |
| 323 return; | 346 return; |
| 324 } | 347 } |
| 325 audio->StreamCreated(sync_socket, shm, shm_size); | 348 audio->StreamCreated(sync_socket, shm, shm_size); |
| 326 rpc->result = NACL_SRPC_RESULT_OK; | 349 rpc->result = NACL_SRPC_RESULT_OK; |
| 327 } | 350 } |
| OLD | NEW |