LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - pepper_emu_audio.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 147 4 2.7 %
Date: 2012-02-16 Functions: 0 0 -

       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 provides limited support for pepper audio emulation
       8                 : // NOTE: Though, it looks like that multiple audio streams are
       9                 : // supported, this is not the case at this point.
      10                 : 
      11                 : 
      12                 : #include <string.h>
      13                 : #include <string>
      14                 : 
      15                 : #if (NACL_LINUX)
      16                 : // for shmem
      17                 : #include "native_client/src/trusted/desc/linux/nacl_desc_sysv_shm.h"
      18                 : // for sync_sockets
      19                 : #include <sys/socket.h>
      20                 : #endif
      21                 : 
      22                 : #include "ppapi/c/pp_errors.h"
      23                 : #include "ppapi/c/pp_size.h"
      24                 : #include "ppapi/c/ppb_audio.h"
      25                 : #include "ppapi/c/ppb_audio_config.h"
      26                 : 
      27                 : #include "native_client/src/shared/imc/nacl_imc.h"
      28                 : #include "native_client/src/shared/platform/nacl_check.h"
      29                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      30                 : #include "native_client/src/trusted/desc/nacl_desc_sync_socket.h"
      31                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      32                 : 
      33                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      34                 : #include "native_client/src/trusted/sel_universal/parsing.h"
      35                 : #include "native_client/src/trusted/sel_universal/primitives.h"
      36                 : #include "native_client/src/trusted/sel_universal/pepper_emu.h"
      37                 : #include "native_client/src/trusted/sel_universal/pepper_emu_helper.h"
      38                 : #include "native_client/src/trusted/sel_universal/srpc_helper.h"
      39                 : 
      40                 : using nacl::DescWrapperFactory;
      41                 : using nacl::DescWrapper;
      42                 : 
      43                 : // ======================================================================
      44                 : namespace {
      45                 : 
      46                 : const int kBytesPerSample = 4;  // 16-bit stereo
      47                 : 
      48                 : const int kRecommendSampleFrameCount = 4 * 1024;
      49                 : const int kMaxAudioBufferSize = 64 * 1024;
      50                 : 
      51                 : IMultimedia* GlobalMultiMediaInterface = 0;
      52                 : 
      53                 : // ======================================================================
      54                 : // Note: Just a bunch of fairly unrelated global variables,
      55                 : // we expect them to be zero initialized.
      56                 : struct DataAudio {
      57                 :   int handle_config;
      58                 : 
      59                 :   nacl::DescWrapper* desc_shmem;
      60                 :   nacl::DescWrapper* desc_sync_in;
      61                 :   nacl::DescWrapper* desc_sync_out;
      62                 :   void* addr_audio;
      63                 : };
      64                 : 
      65                 : 
      66                 : struct DataAudioConfig {
      67                 :   int sample_frequency;
      68                 :   int sample_frame_count;
      69                 : };
      70                 : 
      71                 : // For now we handle only one resource each which is sufficient for SDL
      72              22 : Resource<DataAudio> GlobalAudioDataResources(1, "audio");
      73              22 : Resource<DataAudioConfig> GlobalAudioConfigDataResources(1, "audio_config");
      74                 : 
      75                 : // ======================================================================
      76               0 : void AudioCallBack(void* user_data, unsigned char* buffer, int length) {
      77               0 :   NaClLog(2, "AudioCallBack(%p, %p, %d)\n", user_data, buffer, length);
      78               0 :   DataAudio* data = reinterpret_cast<DataAudio*>(user_data);
      79                 :   // NOTE: we copy the previously filled buffer.
      80                 :   //       This introduces extra latency but simplifies the design
      81                 :   //       as we do not have to wait for the nexe to generate the data.
      82               0 :   memcpy(buffer, data->addr_audio, length);
      83               0 :   int value = 0;
      84               0 :   data->desc_sync_in->Write(&value, sizeof value);
      85               0 : }
      86                 : 
      87                 : // From the PPB_Audio API
      88                 : // PP_Resource Create(PP_Instance instance, PP_Resource config,
      89                 : //                    PPB_Audio_Callback audio_callback, void* user_data);
      90                 : // PPB_Audio_Create:ii:i
      91               0 : void PPB_Audio_Create(SRPC_PARAMS) {
      92               0 :   int instance = ins[0]->u.ival;
      93               0 :   int config_handle = ins[1]->u.ival;
      94               0 :   NaClLog(1, "PPB_Audio_Create(%d, %d)\n", instance, config_handle);
      95                 : 
      96               0 :   const int handle = GlobalAudioDataResources.Alloc();
      97                 :   // for now only support one audio resource
      98               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
      99               0 :   data->handle_config = config_handle;
     100                 :   DataAudioConfig* config_data =
     101               0 :     GlobalAudioConfigDataResources.GetDataForHandle(config_handle);
     102                 : 
     103               0 :   nacl::DescWrapperFactory factory;
     104                 : #if (NACL_WINDOWS || NACL_OSX)
     105               0 :   NaClLog(LOG_ERROR, "HandlerSyncSocketCreate NYI for windows/mac\n");
     106                 : #else
     107                 :   nacl::Handle handles[2] = {nacl::kInvalidHandle, nacl::kInvalidHandle};
     108                 :   if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) {
     109                 :     NaClLog(LOG_FATAL, "cannot create syn sockets\n");
     110                 :   }
     111                 :   data->desc_sync_in = factory.ImportSyncSocketHandle(handles[0]);
     112                 :   data->desc_sync_out = factory.ImportSyncSocketHandle(handles[1]);
     113                 : #endif
     114               0 :   data->desc_shmem = factory.MakeShm(kMaxAudioBufferSize);
     115                 :   size_t dummy_size;
     116                 : 
     117               0 :   if (data->desc_shmem->Map(&data->addr_audio, &dummy_size)) {
     118               0 :     NaClLog(LOG_FATAL, "cannot map audio shmem\n");
     119                 :   }
     120               0 :   NaClLog(LOG_INFO, "PPB_Audio_Create: buffer is %p\n", data->addr_audio);
     121                 : 
     122                 :   GlobalMultiMediaInterface->AudioInit16Bit(config_data->sample_frequency,
     123                 :                                             2,
     124                 :                                             config_data->sample_frame_count,
     125                 :                                             &AudioCallBack,
     126               0 :                                             data);
     127               0 :   outs[0]->u.ival = handle;
     128               0 :   NaClLog(1, "PPB_Audio_Create -> %d\n", handle);
     129               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     130               0 :   done->Run(done);
     131                 : 
     132                 :   UserEvent* event =
     133               0 :     MakeUserEvent(EVENT_TYPE_INIT_AUDIO, 0, handle, data, 0);
     134                 : 
     135               0 :   GlobalMultiMediaInterface->PushUserEvent(event);
     136               0 : }
     137                 : 
     138                 : // From the PPB_Audio API
     139                 : // PP_Bool IsAudio(PP_Resource resource)
     140                 : // PPB_Audio_IsAudio:i:i
     141               0 : void PPB_Audio_IsAudio(SRPC_PARAMS) {
     142               0 :   int handle = ins[0]->u.ival;
     143               0 :   NaClLog(1, "PPB_Audio_IsAudio(%d)\n", handle);
     144               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
     145                 :   // for now be strict to catch problems early
     146               0 :   CHECK(data != NULL);
     147               0 :   outs[0]->u.ival = 1;
     148               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     149               0 :   done->Run(done);
     150               0 : }
     151                 : 
     152                 : // From the PPB_Audio API
     153                 : // PP_Resource GetCurrentConfig(PP_Resource audio);
     154                 : // PPB_Audio_GetCurrentConfig:i:i
     155               0 : void PPB_Audio_GetCurrentConfig(SRPC_PARAMS) {
     156               0 :   int handle = ins[0]->u.ival;
     157               0 :   NaClLog(1, "PPB_Audio_GetCurrentConfig(%d)\n", handle);
     158               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
     159               0 :   outs[0]->u.ival = data->handle_config;
     160               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     161               0 :   done->Run(done);
     162               0 : }
     163                 : 
     164                 : // From the PPB_Audio API
     165                 : // PP_Bool StartPlayback(PP_Resource audio);
     166                 : // PPB_Audio_StopPlayback:i:i
     167               0 : void PPB_Audio_StopPlayback(SRPC_PARAMS) {
     168               0 :   int handle = ins[0]->u.ival;
     169               0 :   NaClLog(1, "PPB_Audio_StopPlayback(%d)\n", handle);
     170               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
     171               0 :   CHECK(data != NULL);
     172               0 :   GlobalMultiMediaInterface->AudioStop();
     173               0 :   outs[0]->u.ival = 1;
     174               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     175               0 :   done->Run(done);
     176               0 : }
     177                 : 
     178                 : // From the PPB_Audio API
     179                 : // PP_Bool StopPlayback(PP_Resource audio);
     180                 : // PPB_Audio_StartPlayback:i:i
     181               0 : void PPB_Audio_StartPlayback(SRPC_PARAMS) {
     182               0 :   int handle = ins[0]->u.ival;
     183               0 :   NaClLog(1, "PPB_Audio_StartPlayback(%d)\n", handle);
     184               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
     185               0 :   CHECK(data != NULL);
     186               0 :   GlobalMultiMediaInterface->AudioStart();
     187                 : 
     188               0 :   outs[0]->u.ival = 1;
     189               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     190               0 :   done->Run(done);
     191               0 : }
     192                 : 
     193                 : // From the PPB_AudioConfig API
     194                 : // PP_Resource CreateStereo16Bit(PP_Instance instance,
     195                 : //                               PP_AudioSampleRate sample_rate,
     196                 : //                               uint32_t sample_frame_count);
     197                 : // PPB_AudioConfig_CreateStereo16Bit:iii:i
     198               0 : void PPB_AudioConfig_CreateStereo16Bit(SRPC_PARAMS) {
     199               0 :   int instance = ins[0]->u.ival;
     200               0 :   int sample_frequency = ins[1]->u.ival;
     201               0 :   int sample_frame_count = ins[2]->u.ival;
     202                 :   NaClLog(1, "PPB_AudioConfig_CreateStereo16Bit(%d, %d, %d)\n",
     203               0 :           instance, sample_frequency, sample_frame_count);
     204                 : 
     205               0 :   const int handle = GlobalAudioConfigDataResources.Alloc();
     206                 :   DataAudioConfig* data =
     207               0 :     GlobalAudioConfigDataResources.GetDataForHandle(handle);
     208               0 :   data->sample_frequency = sample_frequency;
     209               0 :   data->sample_frame_count = sample_frame_count;
     210                 : 
     211               0 :   CHECK(sample_frame_count * kBytesPerSample < kMaxAudioBufferSize);
     212               0 :   outs[0]->u.ival = handle;
     213               0 :   NaClLog(1, "PPB_AudioConfig_CreateStereo16Bit -> %d\n", handle);
     214               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     215               0 :   done->Run(done);
     216               0 : }
     217                 : 
     218                 : // PPB_AudioConfig_IsAudioConfig:i:i
     219                 : // PP_Bool IsAudioConfig(PP_Resource resource);
     220               0 : void PPB_AudioConfig_IsAudioConfig(SRPC_PARAMS) {
     221               0 :   int handle = ins[0]->u.ival;
     222               0 :   NaClLog(1, "PPB_AudioConfig_IsAudioConfig(%d)\n", handle);
     223                 :   DataAudioConfig* data =
     224               0 :     GlobalAudioConfigDataResources.GetDataForHandle(handle);
     225                 :   // for now be strict to catch problems early
     226               0 :   CHECK(data != NULL);
     227               0 :   outs[0]->u.ival = 1;
     228               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     229               0 :   done->Run(done);
     230               0 : }
     231                 : 
     232                 : // PPB_AudioConfig_RecommendSampleFrameCount:ii:i
     233                 : // uint32_t RecommendSampleFrameCount(PP_AudioSampleRate sample_rate,
     234                 : //                                    uint32_t requested_sample_frame_count);
     235               0 : void PPB_AudioConfig_RecommendSampleFrameCount(SRPC_PARAMS) {
     236               0 :   int sample_frequency = ins[0]->u.ival;
     237               0 :   int sample_frame_count = ins[1]->u.ival;
     238                 :   NaClLog(LOG_INFO, "PPB_AudioConfig_RecommendSampleFrameCount(%d, %d)\n",
     239               0 :           sample_frequency, sample_frame_count);
     240                 :   // This is clearly imperfect.
     241                 :   // TODO(robertm): Consider using SDL's negotiation mechanism here
     242               0 :   outs[0]->u.ival = kRecommendSampleFrameCount;
     243               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     244               0 :   done->Run(done);
     245               0 : }
     246                 : 
     247                 : // PPB_AudioConfig_GetSampleRate:i:i
     248                 : // PP_AudioSampleRate GetSampleRate(PP_Resource config);
     249               0 : void PPB_AudioConfig_GetSampleRate(SRPC_PARAMS) {
     250               0 :   int handle = ins[0]->u.ival;
     251               0 :   NaClLog(1, "PPB_AudioConfig_GetSampleRate(%d)\n", handle);
     252                 :   DataAudioConfig* data =
     253               0 :     GlobalAudioConfigDataResources.GetDataForHandle(handle);
     254               0 :   outs[0]->u.ival = data->sample_frequency;
     255               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     256               0 :   done->Run(done);
     257               0 : }
     258                 : 
     259                 : // PPB_AudioConfig_GetSampleFrameCount:i:i
     260                 : // uint32_t GetSampleFrameCount(PP_Resource config);
     261               0 : void PPB_AudioConfig_GetSampleFrameCount(SRPC_PARAMS) {
     262               0 :   int handle = ins[0]->u.ival;
     263               0 :   NaClLog(1, "PPB_AudioConfig_GetSampleFrameCount(%d)\n", handle);
     264                 :   DataAudioConfig* data =
     265               0 :     GlobalAudioConfigDataResources.GetDataForHandle(handle);
     266               0 :   outs[0]->u.ival = data->sample_frame_count;
     267               0 :   rpc->result = NACL_SRPC_RESULT_OK;
     268               0 :   done->Run(done);
     269               0 : }
     270                 : 
     271                 : }  //  namespace
     272                 : 
     273                 : void InvokeAudioStreamCreatedCallback(NaClCommandLoop* ncl,
     274               0 :                                       const UserEvent *event) {
     275               0 :   const int handle = event->result;
     276               0 :   DataAudio* data = GlobalAudioDataResources.GetDataForHandle(handle);
     277                 :   DataAudioConfig* config =
     278               0 :     GlobalAudioConfigDataResources.GetDataForHandle(data->handle_config);
     279                 :   NaClSrpcArg  in[NACL_SRPC_MAX_ARGS];
     280                 :   NaClSrpcArg* ins[NACL_SRPC_MAX_ARGS + 1];
     281                 :   NaClSrpcArg  out[NACL_SRPC_MAX_ARGS];
     282                 :   NaClSrpcArg* outs[NACL_SRPC_MAX_ARGS + 1];
     283               0 :   BuildArgVec(outs, out, 0);
     284               0 :   BuildArgVec(ins, in, 4);
     285               0 :   ins[0]->tag = NACL_SRPC_ARG_TYPE_INT;
     286               0 :   ins[0]->u.ival = handle;
     287               0 :   ins[1]->tag = NACL_SRPC_ARG_TYPE_HANDLE;
     288               0 :   ins[1]->u.hval = data->desc_shmem->desc();
     289               0 :   ins[2]->tag = NACL_SRPC_ARG_TYPE_INT;
     290               0 :   ins[2]->u.ival = config->sample_frame_count * kBytesPerSample;
     291               0 :   ins[3]->tag = NACL_SRPC_ARG_TYPE_HANDLE;
     292               0 :   ins[3]->u.hval = data->desc_sync_out->desc();
     293               0 :   ncl->InvokeNexeRpc("PPP_Audio_StreamCreated:ihih:", ins, outs);
     294               0 : }
     295                 : 
     296                 : 
     297                 : #define TUPLE(a, b) #a #b, a
     298               0 : void PepperEmuInitAudio(NaClCommandLoop* ncl, IMultimedia* im) {
     299               0 :   GlobalMultiMediaInterface = im;
     300               0 :   NaClLog(LOG_INFO, "PepperEmuInitAudio\n");
     301                 : 
     302               0 :   ncl->AddUpcallRpc(TUPLE(PPB_Audio_Create, :ii:i));
     303               0 :   ncl->AddUpcallRpc(TUPLE(PPB_Audio_IsAudio, :i:i));
     304               0 :   ncl->AddUpcallRpc(TUPLE(PPB_Audio_GetCurrentConfig, :i:i));
     305               0 :   ncl->AddUpcallRpc(TUPLE(PPB_Audio_StopPlayback, :i:i));
     306               0 :   ncl->AddUpcallRpc(TUPLE(PPB_Audio_StartPlayback, :i:i));
     307                 : 
     308               0 :   ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_CreateStereo16Bit, :iii:i));
     309               0 :   ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_IsAudioConfig, :i:i));
     310               0 :   ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_RecommendSampleFrameCount, :ii:i));
     311               0 :   ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_GetSampleRate, :i:i));
     312               0 :   ncl->AddUpcallRpc(TUPLE(PPB_AudioConfig_GetSampleFrameCount, :i:i));
     313              22 : }

Generated by: LCOV version 1.7