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

Side by Side Diff: ppapi/native_client/src/shared/ppapi_proxy/plugin_ppb_audio.cc

Issue 7740013: Cloning a bunch of stuff from the native_client repository at r6528 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 4 months 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
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Native Client 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 "native_client/src/shared/ppapi_proxy/plugin_ppb_audio.h"
6
7 #include <pthread.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/errno.h>
11 #include <sys/mman.h>
12 #include "native_client/src/include/nacl_scoped_ptr.h"
13 #include "native_client/src/include/portability.h"
14 #include "native_client/src/shared/ppapi_proxy/plugin_globals.h"
15 #include "native_client/src/shared/ppapi_proxy/plugin_resource.h"
16 #include "native_client/src/shared/ppapi_proxy/utility.h"
17 #include "native_client/src/shared/srpc/nacl_srpc.h"
18 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h"
19 #include "ppapi/c/ppb_audio.h"
20 #include "ppapi/c/ppb_audio_config.h"
21 #include "ppapi/cpp/module_impl.h"
22 #include "srpcgen/ppb_rpc.h"
23 #include "srpcgen/ppp_rpc.h"
24
25 namespace ppapi_proxy {
26 namespace {
27
28 // round size up to next 64k
29 size_t ceil64k(size_t n) {
30 return (n + 0xFFFF) & (~0xFFFF);
31 }
32
33 } // namespace
34
35 PluginAudio::PluginAudio() :
36 resource_(kInvalidResourceId),
37 socket_(-1),
38 shm_(-1),
39 shm_size_(0),
40 shm_buffer_(NULL),
41 state_(AUDIO_INCOMPLETE),
42 thread_id_(),
43 thread_active_(false),
44 user_callback_(NULL),
45 user_data_(NULL) {
46 DebugPrintf("PluginAudio::PluginAudio\n");
47 }
48
49 PluginAudio::~PluginAudio() {
50 DebugPrintf("PluginAudio::~PluginAudio\n");
51 // Ensure audio thread is not active.
52 if (resource_ != kInvalidResourceId)
53 GetInterface()->StopPlayback(resource_);
54 // Unmap the shared memory buffer, if present.
55 if (shm_buffer_) {
56 munmap(shm_buffer_, ceil64k(shm_size_));
57 shm_buffer_ = NULL;
58 shm_size_ = 0;
59 }
60 // Close the handles.
61 if (shm_ != -1) {
62 close(shm_);
63 shm_ = -1;
64 }
65 if (socket_ != -1) {
66 close(socket_);
67 socket_ = -1;
68 }
69 }
70
71 bool PluginAudio::InitFromBrowserResource(PP_Resource resource) {
72 DebugPrintf("PluginAudio::InitFromBrowserResource: resource=%"NACL_PRIu32"\n",
73 resource);
74 resource_ = resource;
75 return true;
76 }
77
78 void PluginAudio::AudioThread(void* self) {
79 PluginAudio* audio = static_cast<PluginAudio*>(self);
80 DebugPrintf("PluginAudio::AudioThread: self=%p\n", self);
81 while (true) {
82 int32_t sync_value;
83 // block on socket read
84 ssize_t r = read(audio->socket_, &sync_value, sizeof(sync_value));
85 // StopPlayback() will send a value of -1 over the sync_socket
86 if ((sizeof(sync_value) != r) || (-1 == sync_value))
87 break;
88 // invoke user callback, get next buffer of audio data
89 audio->user_callback_(audio->shm_buffer_,
90 audio->shm_size_,
91 audio->user_data_);
92 }
93 }
94
95 void PluginAudio::StreamCreated(NaClSrpcImcDescType socket,
96 NaClSrpcImcDescType shm, size_t shm_size) {
97 DebugPrintf("PluginAudio::StreamCreated: shm=%"NACL_PRIu32""
98 " shm_size=%"NACL_PRIuS"\n", shm, shm_size);
99 socket_ = socket;
100 shm_ = shm;
101 shm_size_ = shm_size;
102 shm_buffer_ = mmap(NULL,
103 ceil64k(shm_size),
104 PROT_READ | PROT_WRITE,
105 MAP_SHARED,
106 shm,
107 0);
108 if (MAP_FAILED != shm_buffer_) {
109 if (state() == AUDIO_PENDING) {
110 StartAudioThread();
111 } else {
112 set_state(AUDIO_READY);
113 }
114 } else {
115 shm_buffer_ = NULL;
116 }
117 }
118
119 bool PluginAudio::StartAudioThread() {
120 // clear contents of shm buffer before spinning up audio thread
121 DebugPrintf("PluginAudio::StartAudioThread\n");
122 memset(shm_buffer_, 0, shm_size_);
123 const struct PP_ThreadFunctions* thread_funcs = GetThreadCreator();
124 if (NULL == thread_funcs->thread_create ||
125 NULL == thread_funcs->thread_join) {
126 return false;
127 }
128 int ret = thread_funcs->thread_create(&thread_id_, AudioThread, this);
129 if (0 == ret) {
130 thread_active_ = true;
131 set_state(AUDIO_PLAYING);
132 return true;
133 }
134 return false;
135 }
136
137 bool PluginAudio::StopAudioThread() {
138 DebugPrintf("PluginAudio::StopAudioThread\n");
139 if (thread_active_) {
140 int ret = GetThreadCreator()->thread_join(thread_id_);
141 if (0 == ret) {
142 thread_active_ = false;
143 set_state(AUDIO_READY);
144 return true;
145 }
146 }
147 return false;
148 }
149
150 // Start of untrusted PPB_Audio functions
151 namespace {
152
153 PP_Resource Create(PP_Instance instance,
154 PP_Resource config,
155 PPB_Audio_Callback user_callback,
156 void* user_data) {
157 DebugPrintf("PPB_Audio::Create: instance=%"NACL_PRIu32" config=%"NACL_PRIu32
158 " user_callback=%p user_data=%p\n",
159 instance, config, user_callback, user_data);
160 PP_Resource audio_resource;
161 // Proxy to browser Create, get audio PP_Resource
162 NaClSrpcError srpc_result = PpbAudioRpcClient::PPB_Audio_Create(
163 GetMainSrpcChannel(),
164 instance,
165 config,
166 &audio_resource);
167 DebugPrintf("PPB_Audio::Create: %s\n", NaClSrpcErrorString(srpc_result));
168 if (NACL_SRPC_RESULT_OK != srpc_result) {
169 return kInvalidResourceId;
170 }
171 if (kInvalidResourceId == audio_resource) {
172 return kInvalidResourceId;
173 }
174 scoped_refptr<PluginAudio> audio =
175 PluginResource::AdoptAs<PluginAudio>(audio_resource);
176 if (audio.get()) {
177 audio->set_callback(user_callback, user_data);
178 return audio_resource;
179 }
180 return kInvalidResourceId;
181 }
182
183 PP_Bool IsAudio(PP_Resource resource) {
184 int32_t success;
185 DebugPrintf("PPB_Audio::IsAudio: resource=%"NACL_PRIu32"\n", resource);
186 NaClSrpcError srpc_result =
187 PpbAudioRpcClient::PPB_Audio_IsAudio(
188 GetMainSrpcChannel(),
189 resource,
190 &success);
191 DebugPrintf("PPB_Audio::IsAudio: %s\n", NaClSrpcErrorString(srpc_result));
192 if (NACL_SRPC_RESULT_OK != srpc_result) {
193 return PP_FALSE;
194 }
195 return PP_FromBool(success);
196 }
197
198 PP_Resource GetCurrentConfig(PP_Resource audio) {
199 DebugPrintf("PPB_Audio::GetCurrentConfig: audio=%"NACL_PRIu32"\n", audio);
200 PP_Resource config_resource;
201 NaClSrpcError srpc_result =
202 PpbAudioRpcClient::PPB_Audio_GetCurrentConfig(
203 GetMainSrpcChannel(),
204 audio,
205 &config_resource);
206 DebugPrintf("PPB_Audio::GetCurrentConfig: %s\n",
207 NaClSrpcErrorString(srpc_result));
208 if (NACL_SRPC_RESULT_OK != srpc_result) {
209 return kInvalidResourceId;
210 }
211 return config_resource;
212 }
213
214 PP_Bool StartPlayback(PP_Resource audio_resource) {
215 DebugPrintf("PPB_Audio::StartPlayback: audio_resource=%"NACL_PRIu32"\n",
216 audio_resource);
217 scoped_refptr<PluginAudio> audio =
218 PluginResource::GetAs<PluginAudio>(audio_resource);
219 if (NULL == audio.get()) {
220 return PP_FALSE;
221 }
222 if (audio->state() == AUDIO_INCOMPLETE) {
223 audio->set_state(AUDIO_PENDING);
224 }
225 if (audio->state() == AUDIO_READY) {
226 if (!audio->StartAudioThread()) {
227 return PP_FALSE;
228 }
229 }
230 int32_t success;
231 NaClSrpcError srpc_result =
232 PpbAudioRpcClient::PPB_Audio_StartPlayback(
233 GetMainSrpcChannel(),
234 audio_resource,
235 &success);
236 DebugPrintf("PPB_Audio::StartPlayback: %s\n",
237 NaClSrpcErrorString(srpc_result));
238 if (NACL_SRPC_RESULT_OK != srpc_result || !success) {
239 return PP_FALSE;
240 }
241 return PP_TRUE;
242 }
243
244 PP_Bool StopPlayback(PP_Resource audio_resource) {
245 DebugPrintf("PPB_Audio::StopPlayback: audio_resource=%"NACL_PRIu32"\n",
246 audio_resource);
247 scoped_refptr<PluginAudio> audio =
248 PluginResource::GetAs<PluginAudio>(audio_resource);
249 if (NULL == audio.get()) {
250 return PP_FALSE;
251 }
252 if (audio->state() == AUDIO_PENDING) {
253 // audio is pending to start, but StreamCreated() hasn't occurred yet...
254 audio->set_state(AUDIO_INCOMPLETE);
255 }
256 // RPC to trusted side
257 int32_t success;
258 NaClSrpcError srpc_result =
259 PpbAudioRpcClient::PPB_Audio_StopPlayback(
260 GetMainSrpcChannel(),
261 audio_resource,
262 &success);
263 DebugPrintf("PPB_Audio::StopPlayback: %s\n",
264 NaClSrpcErrorString(srpc_result));
265 if (NACL_SRPC_RESULT_OK != srpc_result) {
266 return PP_FALSE;
267 }
268 if (audio->state() != AUDIO_PLAYING) {
269 return PP_FromBool(success);
270 }
271 // stop and join the audio thread
272 return PP_FromBool(audio->StopAudioThread());
273 }
274 } // namespace
275
276 const PPB_Audio* PluginAudio::GetInterface() {
277 DebugPrintf("PluginAudio::GetInterface\n");
278 static const PPB_Audio audio_interface = {
279 Create,
280 IsAudio,
281 GetCurrentConfig,
282 StartPlayback,
283 StopPlayback,
284 };
285 return &audio_interface;
286 }
287 } // namespace ppapi_proxy
288
289 using ppapi_proxy::DebugPrintf;
290
291 // PppAudioRpcServer::PPP_Audio_StreamCreated() must be in global
292 // namespace. This function receives handles for the socket and shared
293 // memory, provided by the trusted audio implementation.
294 void PppAudioRpcServer::PPP_Audio_StreamCreated(
295 NaClSrpcRpc* rpc,
296 NaClSrpcClosure* done,
297 PP_Resource audio_resource,
298 NaClSrpcImcDescType shm,
299 int32_t shm_size,
300 NaClSrpcImcDescType sync_socket) {
301 NaClSrpcClosureRunner runner(done);
302 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
303 DebugPrintf("PPP_Audio::StreamCreated: audio_resource=%"NACL_PRIu32
304 " shm=%"NACL_PRIx32" shm_size=%"NACL_PRIuS
305 " sync_socket=%"NACL_PRIx32"\n",
306 audio_resource, shm, shm_size, sync_socket);
307 scoped_refptr<ppapi_proxy::PluginAudio> audio =
308 ppapi_proxy::PluginResource::
309 GetAs<ppapi_proxy::PluginAudio>(audio_resource);
310 if (NULL == audio.get()) {
311 // Ignore if no audio_resource -> audio_instance mapping exists,
312 // the app may have shutdown audio before StreamCreated() invoked.
313 rpc->result = NACL_SRPC_RESULT_OK;
314 return;
315 }
316 audio->StreamCreated(sync_socket, shm, shm_size);
317 rpc->result = NACL_SRPC_RESULT_OK;
318 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698