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

Side by Side Diff: src/trusted/sel_universal/multimedia_handler.cc

Issue 7046064: Some small refactoring and renaming of sel_universel pepper emulation components. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 6 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 /*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 // This file exports a single function used to setup the
8 // multimedia sub-system for use with sel_universal
9 // It was inpspired by src/trusted/plugin/srpc/multimedia_socket.cc
10 // On the untrusted side it interface with: src/untrusted/av/nacl_av.c
11 //
12 // NOTE: this is experimentation and testing. We are not concerned
13 // about descriptor and memory leaks
14
15 #include <string.h>
16 #include <fstream>
17 #include <queue>
18 #include <string>
19
20 #if (NACL_LINUX)
21 // for shmem
22 #include <sys/ipc.h>
23 #include <sys/shm.h>
24 #include "native_client/src/trusted/desc/linux/nacl_desc_sysv_shm.h"
25 // for sync_sockets
26 #include <sys/socket.h>
27 #endif
28
29
30 #include "ppapi/c/pp_errors.h"
31 #include "ppapi/c/pp_input_event.h"
32 #include "ppapi/c/pp_size.h"
33 #include "ppapi/c/ppb_audio.h"
34 #include "ppapi/c/ppb_audio_config.h"
35 #include "ppapi/c/ppb_image_data.h"
36
37 #include "native_client/src/shared/imc/nacl_imc.h"
38 #include "native_client/src/shared/platform/nacl_check.h"
39 #include "native_client/src/shared/srpc/nacl_srpc.h"
40 #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
41 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
42
43 #include "native_client/src/trusted/sel_universal/rpc_universal.h"
44 #include "native_client/src/trusted/sel_universal/multimedia.h"
45 #include "native_client/src/trusted/sel_universal/parsing.h"
46 #include "native_client/src/trusted/sel_universal/pepper_emu.h"
47 #include "native_client/src/trusted/sel_universal/srpc_helper.h"
48
49 using nacl::DescWrapperFactory;
50 using nacl::DescWrapper;
51
52 // ======================================================================
53 const int kInvalidInstance = 0;
54 const int kInvalidHandle = 0;
55 const int kFirstImageDataHandle = 100;
56 const int kFirstGraphicsHandle = 200;
57 const int kFirstAudioHandle = 300;
58 const int kFirstAudioConfigHandle = 400;
59 const int kBytesPerSample = 4; // 16-bit stereo
60
61 const int kRecommendSampleFrameCount = 2048;
62 const int kMaxAudioBufferSize = 0x10000;
63 const int kBytesPerPixel = 4;
64
65 // ======================================================================
66
67 // Note: Just a bunch of fairly unrelated global variables,
68 // we expect them to be zero initialized.
69 static struct {
70 int instance;
71
72 // video stuff
73 int screen_width;
74 int screen_height;
75
76 int handle_graphics;
77 int handle_image_data;
78 int image_data_size;
79
80 nacl::DescWrapper* desc_video_shmem;
81 void* addr_video;
82
83 // audio stuff
84 int handle_audio;
85 int handle_audio_config;
86
87 int sample_frequency;
88 int sample_frame_count;
89
90 nacl::DescWrapper* desc_audio_shmem;
91 nacl::DescWrapper* desc_audio_sync_in;
92 nacl::DescWrapper* desc_audio_sync_out;
93 void* addr_audio;
94
95 // for event loggging and replay
96 std::ofstream event_logger_stream;
97 std::ifstream event_replay_stream;
98 std::queue<PP_InputEvent> events_ready_to_go;
99 PP_InputEvent next_sync_event;
100
101 IMultimedia* sdl_engine;
102 std::string title;
103 } Global;
104
105 // ======================================================================
106 static void AudioCallBack(void* data, unsigned char* buffer, int length) {
107 NaClLog(2, "AudioCallBack(%p, %p, %d)\n", data, buffer, length);
108 UNREFERENCED_PARAMETER(data);
109 CHECK(length == Global.sample_frame_count * kBytesPerSample);
110 // NOTE: we copy the previously filled buffer.
111 // This introduces extra latency but simplifies the design
112 // as we do not have to wait for the nexe to generate the data.
113 memcpy(buffer, Global.addr_audio, length);
114
115 // ping sync socket
116 int value = 0;
117 Global.desc_audio_sync_in->Write(&value, sizeof value);
118 }
119
120 // From the ImageData API
121 // PP_Resource Create(PP_Instance instance,
122 // PP_ImageDataFormat format,
123 // const struct PP_Size* size,
124 // PP_Bool init_to_zero);
125 // PPB_ImageData_Create:iiCi:i
126 //
127 // TODO(robertm) this function can currently be called only once
128 // and the dimension must match the global values
129 // and the format is fixed.
130 static void PPB_ImageData_Create(SRPC_PARAMS) {
131 const int instance = ins[0]->u.ival;
132 const int format = ins[1]->u.ival;
133 CHECK(ins[2]->u.count == sizeof(PP_Size));
134 PP_Size* img_size = (PP_Size*) ins[2]->arrays.carr;
135 NaClLog(1, "PPB_ImageData_Create(%d, %d, %d, %d)\n",
136 instance, format, img_size->width, img_size->height);
137
138 CHECK(Global.handle_image_data == kInvalidHandle);
139 Global.handle_image_data = kFirstImageDataHandle;
140 CHECK(Global.instance != kInvalidInstance);
141 CHECK(instance == Global.instance);
142 CHECK(format == PP_IMAGEDATAFORMAT_BGRA_PREMUL);
143
144 CHECK(Global.screen_width == img_size->width);
145 CHECK(Global.screen_height == img_size->height);
146 Global.image_data_size = kBytesPerPixel * img_size->width * img_size->height;
147
148 nacl::DescWrapperFactory factory;
149 Global.desc_video_shmem = factory.MakeShm(Global.image_data_size);
150 size_t dummy_size;
151
152 if (Global.desc_video_shmem->Map(&Global.addr_video, &dummy_size)) {
153 NaClLog(LOG_FATAL, "cannot map video shmem\n");
154 }
155
156 if (ins[3]->u.ival) {
157 memset(Global.addr_video, 0, Global.image_data_size);
158 }
159
160 outs[0]->u.ival = Global.handle_image_data;
161 rpc->result = NACL_SRPC_RESULT_OK;
162 done->Run(done);
163 }
164
165 // From the ImageData API
166 // PP_Bool Describe(PP_Resource image_data,
167 // struct PP_ImageDataDesc* desc);
168 // PPB_ImageData_Describe:i:Chii
169 static void PPB_ImageData_Describe(SRPC_PARAMS) {
170 int handle = ins[0]->u.ival;
171 NaClLog(1, "PPB_ImageData_Describe(%d)\n", handle);
172 CHECK(handle == Global.handle_image_data);
173
174 PP_ImageDataDesc d;
175 d.format = PP_IMAGEDATAFORMAT_BGRA_PREMUL;
176 d.size.width = Global.screen_width;
177 d.size.height = Global.screen_height;
178 // we handle only rgba data -> each pixel is 4 bytes.
179 d.stride = Global.screen_width * kBytesPerPixel;
180 outs[0]->u.count = sizeof(d);
181 outs[0]->arrays.carr = reinterpret_cast<char*>(calloc(1, sizeof(d)));
182 memcpy(outs[0]->arrays.carr, &d, sizeof(d));
183
184 outs[1]->u.hval = Global.desc_video_shmem->desc();
185 outs[2]->u.ival = Global.image_data_size;
186 outs[3]->u.ival = 1;
187 rpc->result = NACL_SRPC_RESULT_OK;
188 done->Run(done);
189 }
190
191 // From the Graphics2D API
192 // PP_Resource Create(PP_Instance instance,
193 // const struct PP_Size* size,
194 // PP_Bool is_always_opaque);
195 // PPB_Graphics2D_Create:iCi:i
196 //
197 // TODO(robertm) This function can currently be called only once
198 // The size must be the same as the one provided via
199 // HandlerSDLInitialize()
200 static void PPB_Graphics2D_Create(SRPC_PARAMS) {
201 int instance = ins[0]->u.ival;
202 NaClLog(1, "PPB_Graphics2D_Create(%d)\n", instance);
203 CHECK(Global.handle_graphics == kInvalidHandle);
204 Global.handle_graphics = kFirstGraphicsHandle;
205 CHECK(instance == Global.instance);
206 PP_Size* img_size = reinterpret_cast<PP_Size*>(ins[1]->arrays.carr);
207 CHECK(Global.screen_width == img_size->width);
208 CHECK(Global.screen_height == img_size->height);
209 // TODO(robertm): is_always_opaque is currently ignored
210 outs[0]->u.ival = Global.handle_graphics;
211 rpc->result = NACL_SRPC_RESULT_OK;
212 done->Run(done);
213 }
214
215 // PP_Bool BindGraphics(PP_Instance instance, PP_Resource device);
216 // PPB_Instance_BindGraphics:ii:i
217 static void PPB_Instance_BindGraphics(SRPC_PARAMS) {
218 int instance = ins[0]->u.ival;
219 int handle = ins[1]->u.ival;
220 NaClLog(1, "PPB_Instance_BindGraphics(%d, %d)\n",
221 instance, handle);
222 CHECK(instance == Global.instance);
223 CHECK(handle == Global.handle_graphics);
224 outs[0]->u.ival = 1;
225 rpc->result = NACL_SRPC_RESULT_OK;
226 done->Run(done);
227 }
228
229 // From the Graphics2D API
230 // void ReplaceContents(PP_Resource graphics_2d,
231 // PP_Resource image_data);
232 // PPB_Graphics2D_ReplaceContents:ii:
233 //
234 // NOTE: this is completely ignored and we postpone all action to "Flush"
235 static void PPB_Graphics2D_ReplaceContents(SRPC_PARAMS) {
236 int handle_graphics = ins[0]->u.ival;
237 int handle_image_data = ins[1]->u.ival;
238 UNREFERENCED_PARAMETER(outs);
239 NaClLog(1, "PPB_Graphics2D_ReplaceContents(%d, %d)\n",
240 handle_graphics, handle_image_data);
241 CHECK(handle_graphics == Global.handle_graphics);
242 CHECK(handle_image_data == Global.handle_image_data);
243
244 // For now assume this will be immediately followed by a Flush
245 rpc->result = NACL_SRPC_RESULT_OK;
246 done->Run(done);
247 }
248
249 // From the Graphics2D API
250 // void PaintImageData(PP_Resource graphics_2d,
251 // PP_Resource image_data,
252 // const struct PP_Point* top_left,
253 // const struct PP_Rect* src_rect);
254 // PPB_Graphics2D_PaintImageData:iiCC:
255 //
256 // NOTE: this is completely ignored and we postpone all action to "Flush"
257 // Furhermore we assume that entire image is painted
258 static void PPB_Graphics2D_PaintImageData(SRPC_PARAMS) {
259 int handle_graphics = ins[0]->u.ival;
260 int handle_image_data = ins[1]->u.ival;
261 UNREFERENCED_PARAMETER(outs);
262 NaClLog(1, "PPB_Graphics2D_PaintImageData(%d, %d)\n",
263 handle_graphics, handle_image_data);
264 CHECK(handle_graphics == Global.handle_graphics);
265 CHECK(handle_image_data == Global.handle_image_data);
266
267 // For now assume this will be immediately followed by a Flush
268 rpc->result = NACL_SRPC_RESULT_OK;
269 done->Run(done);
270 }
271
272 // From the Graphics2D API
273 // int32_t Flush(PP_Resource graphics_2d,
274 // struct PP_CompletionCallback callback);
275 // PPB_Graphics2D_Flush:ii:i
276 static void PPB_Graphics2D_Flush(SRPC_PARAMS) {
277 int handle = ins[0]->u.ival;
278 int callback_id = ins[1]->u.ival;
279 NaClLog(1, "PPB_Graphics2D_Flush(%d, %d)\n", handle, callback_id);
280 CHECK(handle == Global.handle_graphics);
281 outs[0]->u.ival = -1;
282 rpc->result = NACL_SRPC_RESULT_OK;
283 done->Run(done);
284
285 Global.sdl_engine->VideoUpdate(Global.addr_video);
286 NaClLog(1, "pushing user event for callback (%d)\n", callback_id);
287 Global.sdl_engine->PushUserEvent(0, MY_EVENT_FLUSH_CALL_BACK, callback_id, 0);
288 }
289
290 // From the PPB_Audio API
291 // PP_Resource Create(PP_Instance instance, PP_Resource config,
292 // PPB_Audio_Callback audio_callback, void* user_data);
293 // PPB_Audio_Create:ii:i
294 static void PPB_Audio_Create(SRPC_PARAMS) {
295 int instance = ins[0]->u.ival;
296 int handle = ins[1]->u.ival;
297 NaClLog(1, "PPB_Audio_Create(%d, %d)\n", instance, handle);
298 CHECK(instance == Global.instance);
299 CHECK(handle == Global.handle_audio_config);
300
301 nacl::DescWrapperFactory factory;
302 #if (NACL_WINDOWS || NACL_OSX)
303 NaClLog(LOG_ERROR, "HandlerSyncSocketCreate NYI for windows/mac\n");
304 #else
305 nacl::Handle handles[2] = {nacl::kInvalidHandle, nacl::kInvalidHandle};
306 if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
307 NaClLog(LOG_FATAL, "cannot create syn sockets\n");
308 }
309 Global.desc_audio_sync_in = factory.ImportSyncSocketHandle(handles[0]);
310 Global.desc_audio_sync_out = factory.ImportSyncSocketHandle(handles[1]);
311 #endif
312 Global.desc_audio_shmem = factory.MakeShm(kMaxAudioBufferSize);
313 size_t dummy_size;
314
315 if (Global.desc_audio_shmem->Map(&Global.addr_audio, &dummy_size)) {
316 NaClLog(LOG_FATAL, "cannot map audio shmem\n");
317 }
318 NaClLog(LOG_INFO, "PPB_Audio_Create: buffer is %p\n", Global.addr_audio);
319
320 Global.sdl_engine->AudioInit16Bit(Global.sample_frequency,
321 2,
322 Global.sample_frame_count,
323 &AudioCallBack);
324
325 CHECK(Global.handle_audio == kInvalidHandle);
326 Global.handle_audio = kFirstAudioHandle;
327 outs[0]->u.ival = Global.handle_audio;
328 rpc->result = NACL_SRPC_RESULT_OK;
329 done->Run(done);
330
331 Global.sdl_engine->PushUserEvent(0, MY_EVENT_INIT_AUDIO, 0, 0);
332 }
333
334 // From the PPB_Audio API
335 // PP_Bool IsAudio(PP_Resource resource)
336 // PPB_Audio_IsAudio:i:i
337 static void PPB_Audio_IsAudio(SRPC_PARAMS) {
338 int handle = ins[0]->u.ival;
339 NaClLog(1, "PPB_Audio_IsAudio(%d)\n", handle);
340 CHECK(handle == Global.handle_audio);
341
342 outs[0]->u.ival = 1;
343 rpc->result = NACL_SRPC_RESULT_OK;
344 done->Run(done);
345 }
346
347 // From the PPB_Audio API
348 // PP_Resource GetCurrentConfig(PP_Resource audio);
349 // PPB_Audio_GetCurrentConfig:i:i
350 static void PPB_Audio_GetCurrentConfig(SRPC_PARAMS) {
351 int handle = ins[0]->u.ival;
352 NaClLog(1, "PPB_Audio_GetCurrentConfig(%d)\n", handle);
353 CHECK(handle == Global.handle_audio);
354 CHECK(Global.handle_audio_config != kInvalidHandle);
355
356 outs[0]->u.ival = Global.handle_audio_config;
357 rpc->result = NACL_SRPC_RESULT_OK;
358 done->Run(done);
359 }
360
361 // From the PPB_Audio API
362 // PP_Bool StartPlayback(PP_Resource audio);
363 // PPB_Audio_StopPlayback:i:i
364 static void PPB_Audio_StopPlayback(SRPC_PARAMS) {
365 int handle = ins[0]->u.ival;
366 NaClLog(1, "PPB_Audio_StopPlayback(%d)\n", handle);
367 CHECK(handle == Global.handle_audio);
368 Global.sdl_engine->AudioStop();
369
370 outs[0]->u.ival = 1;
371 rpc->result = NACL_SRPC_RESULT_OK;
372 done->Run(done);
373 }
374
375 // From the PPB_Audio API
376 // PP_Bool StopPlayback(PP_Resource audio);
377 // PPB_Audio_StartPlayback:i:i
378 static void PPB_Audio_StartPlayback(SRPC_PARAMS) {
379 int handle = ins[0]->u.ival;
380 NaClLog(1, "PPB_Audio_StartPlayback(%d)\n", handle);
381 CHECK(handle == Global.handle_audio);
382 Global.sdl_engine->AudioStart();
383
384 outs[0]->u.ival = 1;
385 rpc->result = NACL_SRPC_RESULT_OK;
386 done->Run(done);
387 }
388
389 // From the PPB_AudioConfig API
390 // PP_Resource CreateStereo16Bit(PP_Instance instance,
391 // PP_AudioSampleRate sample_rate,
392 // uint32_t sample_frame_count);
393 // PPB_AudioConfig_CreateStereo16Bit:iii:i
394 static void PPB_AudioConfig_CreateStereo16Bit(SRPC_PARAMS) {
395 int instance = ins[0]->u.ival;
396 Global.sample_frequency = ins[1]->u.ival;
397 Global.sample_frame_count = ins[2]->u.ival;
398 NaClLog(1, "PPB_AudioConfig_CreateStereo16Bit(%d, %d, %d)\n",
399 instance, Global.sample_frequency, Global.sample_frame_count);
400 CHECK(instance == Global.instance);
401 CHECK(Global.sample_frame_count * kBytesPerSample < kMaxAudioBufferSize);
402 CHECK(Global.handle_audio_config == kInvalidHandle);
403 Global.handle_audio_config = kFirstAudioConfigHandle;
404 outs[0]->u.ival = Global.handle_audio_config;
405
406 rpc->result = NACL_SRPC_RESULT_OK;
407 done->Run(done);
408 }
409
410 // PPB_AudioConfig_IsAudioConfig:i:i
411 // PP_Bool IsAudioConfig(PP_Resource resource);
412 static void PPB_AudioConfig_IsAudioConfig(SRPC_PARAMS) {
413 int handle = ins[0]->u.ival;
414 NaClLog(1, "PPB_AudioConfig_IsAudioConfig(%d)\n", handle);
415 outs[0]->u.ival = (handle == Global.handle_audio_config);
416 rpc->result = NACL_SRPC_RESULT_OK;
417 done->Run(done);
418 }
419
420 // PPB_AudioConfig_RecommendSampleFrameCount:ii:i
421 // uint32_t RecommendSampleFrameCount(PP_AudioSampleRate sample_rate,
422 // uint32_t requested_sample_frame_count);
423 static void PPB_AudioConfig_RecommendSampleFrameCount(SRPC_PARAMS) {
424 int sample_frequency = ins[0]->u.ival;
425 int sample_frame_count = ins[1]->u.ival;
426 NaClLog(LOG_INFO, "PPB_AudioConfig_RecommendSampleFrameCount(%d, %d)\n",
427 sample_frequency, sample_frame_count);
428 // This is clearly imperfect.
429 // TODO(robertm): Consider using SDL's negotiation mechanism here
430 outs[0]->u.ival = kRecommendSampleFrameCount;
431 rpc->result = NACL_SRPC_RESULT_OK;
432 done->Run(done);
433 }
434
435 // PPB_AudioConfig_GetSampleRate:i:i
436 // PP_AudioSampleRate GetSampleRate(PP_Resource config);
437 static void PPB_AudioConfig_GetSampleRate(SRPC_PARAMS) {
438 int handle = ins[0]->u.ival;
439 NaClLog(1, "PPB_AudioConfig_GetSampleRate(%d)\n", handle);
440 CHECK(handle == Global.handle_audio_config);
441
442 outs[0]->u.ival = Global.sample_frequency;
443 rpc->result = NACL_SRPC_RESULT_OK;
444 done->Run(done);
445 }
446
447 // PPB_AudioConfig_GetSampleFrameCount:i:i
448 // uint32_t GetSampleFrameCount(PP_Resource config);
449 static void PPB_AudioConfig_GetSampleFrameCount(SRPC_PARAMS) {
450 int handle = ins[0]->u.ival;
451 NaClLog(1, "PPB_AudioConfig_GetSampleFrameCount(%d)\n", handle);
452 CHECK(handle == Global.handle_audio_config);
453
454 outs[0]->u.ival = Global.sample_frame_count;
455 rpc->result = NACL_SRPC_RESULT_OK;
456 done->Run(done);
457 }
458
459
460 // TODO(robertm): rename this to HandlerPepperEmuInitialize
461 #define TUPLE(a, b) #a #b, a
462 bool HandlerSDLInitialize(NaClCommandLoop* ncl, const vector<string>& args) {
463 NaClLog(LOG_INFO, "HandlerSDLInitialize\n");
464 if (args.size() < 5) {
465 NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
466 return false;
467 }
468
469 UNREFERENCED_PARAMETER(ncl);
470 // TODO(robertm): factor the audio video rpcs into a different file
471 // and initialize them via say PepperEmuInitAV()
472 ncl->AddUpcallRpc(TUPLE(PPB_Audio_Create, :ii:i));
473 ncl->AddUpcallRpc(TUPLE(PPB_Audio_IsAudio, :i:i));
474 ncl->AddUpcallRpc(TUPLE(PPB_Audio_GetCurrentConfig, :i:i));
475 ncl->AddUpcallRpc(TUPLE(PPB_Audio_StopPlayback, :i:i));
476 ncl->AddUpcallRpc(TUPLE(PPB_Audio_StartPlayback, :i:i));
477
478 ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_CreateStereo16Bit, :iii:i));
479 ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_IsAudioConfig, :i:i));
480 ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_RecommendSampleFrameCount, :ii:i));
481 ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_GetSampleRate, :i:i));
482 ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_GetSampleFrameCount, :i:i));
483
484 ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_Create, :iCi:i));
485 ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_ReplaceContents, :ii:));
486 ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_PaintImageData, :iiCC:));
487 ncl->AddUpcallRpc(TUPLE(PPB_Graphics2D_Flush, :ii:i));
488
489 ncl->AddUpcallRpc(TUPLE(PPB_ImageData_Describe, :i:Chii));
490 ncl->AddUpcallRpc(TUPLE(PPB_ImageData_Create, :iiCi:i));
491
492 ncl->AddUpcallRpc(TUPLE(PPB_Instance_BindGraphics, :ii:i));
493
494
495 Global.instance = ExtractInt32(args[1]);
496 Global.screen_width = ExtractInt32(args[2]);
497 Global.screen_height = ExtractInt32(args[3]);
498 Global.title = args[4];
499
500 // NOTE: we decide at linktime which incarnation to use here
501 Global.sdl_engine = MakeMultimediaSDL(Global.screen_width,
502 Global.screen_height,
503 Global.title.c_str());
504 PepperEmuInitCore(ncl, Global.sdl_engine);
505 PepperEmuInitFileIO(ncl, Global.sdl_engine);
506 PepperEmuInitPostMessage(ncl, Global.sdl_engine);
507 return true;
508 }
509
510
511 bool GetNextEvent(PP_InputEvent* event) {
512 if (Global.event_replay_stream.is_open()) {
513 if (Global.events_ready_to_go.size() > 0) {
514 // empty queue while we have ready to events
515 *event = Global.events_ready_to_go.front();
516 Global.events_ready_to_go.pop();
517 return true;
518 } else if (!IsInvalidEvent(&Global.next_sync_event)) {
519 // wait for the matching sync event
520 Global.sdl_engine->EventGet(event);
521
522 if (IsTerminationEvent(event)) return true;
523
524 // drop all regular events on the floor;
525 if (!IsUserEvent(event)) return false;
526
527 // NOTE: we only replay the recorded input events.
528 // Recorded UserEvents are used for synchronization with the
529 // actual UserEvents that the system generates.
530 // TODO(robertm): We may need to refine this because, in theory,
531 // there is no guaranteed time ordering on the UserEvents.
532 // One solution would be to only use the screen refresh
533 // UserEvents (MY_EVENT_FLUSH_CALL_BACK) as sync events and
534 // ignore all others.
535 // We can delay this work until we see the check below firing.
536 CHECK(GetCodeFromUserEvent(event) ==
537 GetCodeFromUserEvent(&Global.next_sync_event));
538 // sync event has been "consumed"
539 MakeInvalidEvent(&Global.next_sync_event);
540 return true;
541 } else {
542 // refill queue
543 if (Global.event_replay_stream.eof()) {
544 NaClLog(LOG_INFO, "replay events depleted\n");
545 MakeTerminationEvent(event);
546 Global.events_ready_to_go.push(*event);
547 return false;
548 }
549 while (true) {
550 Global.event_replay_stream.read(
551 reinterpret_cast<char*>(event), sizeof(*event));
552 if (Global.event_replay_stream.fail()) return false;
553 CHECK(!IsInvalidEvent(event));
554 if (IsUserEvent(event)) {
555 Global.next_sync_event = *event;
556 return false;
557 } else {
558 Global.events_ready_to_go.push(*event);
559 }
560 }
561 }
562 } else {
563 #if defined(USE_POLLING)
564 Global.sdl_engine->EventPoll(event);
565 if (IsInvalidEvent(&event)) return false;
566 #else
567 Global.sdl_engine->EventGet(event);
568 #endif
569 return true;
570 }
571 }
572
573 // uncomment the line below if you want to use a non-blocking
574 // event processing loop.
575 // This can be sometime useful for debugging but is wasting cycles
576 // #define USE_POLLING
577
578 bool HandlerSDLEventLoop(NaClCommandLoop* ncl, const vector<string>& args) {
579 NaClLog(LOG_INFO, "HandlerSDLEventLoop\n");
580 UNREFERENCED_PARAMETER(args);
581 UNREFERENCED_PARAMETER(ncl);
582 PP_InputEvent event;
583 while (true) {
584 NaClLog(1, "event wait\n");
585 if (!GetNextEvent(&event)) {
586 continue;
587 }
588
589 NaClSrpcArg in[NACL_SRPC_MAX_ARGS];
590 NaClSrpcArg* ins[NACL_SRPC_MAX_ARGS + 1];
591 NaClSrpcArg out[NACL_SRPC_MAX_ARGS];
592 NaClSrpcArg* outs[NACL_SRPC_MAX_ARGS + 1];
593 int dummy_exception[2] = {0, 0};
594
595 if (Global.event_logger_stream.is_open() && !IsInvalidEvent(&event)) {
596 Global.event_logger_stream.write(reinterpret_cast<char*>(&event),
597 sizeof(event));
598 }
599
600 if (IsTerminationEvent(&event)) {
601 NaClLog(LOG_INFO, "Got termination event\n");
602 break;
603 } else if (IsUserEvent(&event)) {
604 // A user event is a non-standard event
605 NaClLog(2, "Got user event with code %d\n",
606 GetCodeFromUserEvent(&event));
607
608 switch (GetCodeFromUserEvent(&event)) {
609 // This event gets created as a result of PPB_Core_CallOnMainThread(
610 case MY_EVENT_TIMER_CALL_BACK:
611 // FALL THROUGH
612 // This event gets created so that we can invoke
613 // RunCompletionCallback after PPB_Graphics2D_Flush
614 case MY_EVENT_FLUSH_CALL_BACK: {
615 int callback = GetData1FromUserEvent(&event);
616 int result = GetData2FromUserEvent(&event);
617 NaClLog(2, "Completion callback(%d, %d)\n", callback, result);
618 BuildArgVec(ins, in, 3);
619
620 ins[0]->tag = NACL_SRPC_ARG_TYPE_INT;
621 ins[0]->u.ival = callback;
622 ins[1]->tag = NACL_SRPC_ARG_TYPE_INT;
623 ins[1]->u.ival = result;
624 ins[2]->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
625 ins[2]->u.count = sizeof(dummy_exception);
626 ins[2]->arrays.carr = reinterpret_cast<char*>(dummy_exception);
627 BuildArgVec(outs, out, 0);
628 ncl->InvokeNexeRpc("RunCompletionCallback:iiC:", ins, outs);
629 break;
630 }
631 // This event gets created so that we can invoke
632 // PPP_Audio_StreamCreated after PPB_Audio_Create
633 case MY_EVENT_INIT_AUDIO:
634 NaClLog(1, "audio init callback\n");
635 BuildArgVec(ins, in, 4);
636 ins[0]->tag = NACL_SRPC_ARG_TYPE_INT;
637 ins[0]->u.ival = Global.handle_audio;
638 ins[1]->tag = NACL_SRPC_ARG_TYPE_HANDLE;
639 ins[1]->u.hval = Global.desc_audio_shmem->desc();
640 ins[2]->tag = NACL_SRPC_ARG_TYPE_INT;
641 ins[2]->u.ival = Global.sample_frame_count * kBytesPerSample;
642 ins[3]->tag = NACL_SRPC_ARG_TYPE_HANDLE;
643 ins[3]->u.hval = Global.desc_audio_sync_out->desc();
644
645 BuildArgVec(outs, out, 0);
646 sleep(1);
647 ncl->InvokeNexeRpc("PPP_Audio_StreamCreated:ihih:", ins, outs);
648 break;
649
650 default:
651 NaClLog(LOG_FATAL, "unknown event type %d\n",
652 GetData1FromUserEvent(&event));
653 break;
654 }
655 } else {
656 NaClLog(1, "Got input event with type %d\n", event.type);
657 BuildArgVec(ins, in, 2);
658 ins[0]->tag = NACL_SRPC_ARG_TYPE_INT;
659 ins[0]->u.ival = Global.instance;
660 ins[1]->tag = NACL_SRPC_ARG_TYPE_CHAR_ARRAY;
661 ins[1]->u.count = sizeof(event);
662 ins[1]->arrays.carr = reinterpret_cast<char*>(&event);
663
664 BuildArgVec(outs, out, 1);
665 outs[0]->tag = NACL_SRPC_ARG_TYPE_INT;
666 ncl->InvokeNexeRpc("PPP_Instance_HandleInputEvent:iC:i", ins, outs);
667 }
668 }
669 NaClLog(LOG_INFO, "Exiting event loop\n");
670 return true;
671 }
672
673
674 void RecordPPAPIEvents(std::string filename) {
675 NaClLog(LOG_INFO, "recoding events to %s\n", filename.c_str());
676 Global.event_logger_stream.open(
677 filename.c_str(), std::ios::out | std::ios::trunc | std::ios::binary);
678 if (!Global.event_logger_stream.is_open()) {
679 NaClLog(LOG_FATAL, "Cannot open %s\n", filename.c_str());
680 }
681 }
682
683
684 void ReplayPPAPIEvents(std::string filename) {
685 NaClLog(LOG_INFO, "replaying events from %s\n", filename.c_str());
686 MakeInvalidEvent(&Global.next_sync_event);
687 Global.event_replay_stream.open(filename.c_str(),
688 std::ios::in | std::ios::binary);
689 if (!Global.event_replay_stream.is_open()) {
690 NaClLog(LOG_FATAL, "Cannot open %s\n", filename.c_str());
691 }
692 }
OLDNEW
« no previous file with comments | « src/trusted/sel_universal/multimedia_handler.h ('k') | src/trusted/sel_universal/multimedia_sdl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698