Esempio n. 1
0
static void adapter_thread(void *data)
{
   uint8_t send_command_buf[4096];
   struct libusb_adapter *adapter = (struct libusb_adapter*)data;
   libusb_hid_t *hid              = adapter ? adapter->hid : NULL;

   if (!adapter)
      return;

   while (!adapter->quitting)
   {
      size_t send_command_size;
      int tmp;
      int report_number;
      int size = 0;

      slock_lock(adapter->send_control_lock);
      if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size))
      {
         fifo_read(adapter->send_control_buffer, &send_command_size, sizeof(send_command_size));
         if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size))
         {
            fifo_read(adapter->send_control_buffer, send_command_buf, send_command_size);
            libusb_interrupt_transfer(adapter->handle, adapter->endpoint_out, send_command_buf, send_command_size, &tmp, 1000);
         }
      }
      slock_unlock(adapter->send_control_lock);

      libusb_interrupt_transfer(adapter->handle, adapter->endpoint_in, &adapter->data[1], adapter->endpoint_in_max_size, &size, 1000);

      if (adapter && hid && hid->slots && size)
         pad_connection_packet(&hid->slots[adapter->slot], adapter->slot,
               adapter->data, size+1);
   }
}
Esempio n. 2
0
static void ffmpeg_flush_buffers(ffmpeg_t *handle)
{
   bool did_work;
   void *video_buf = av_malloc(2 * handle->params.fb_width * 
         handle->params.fb_height * handle->video.pix_size);
   size_t audio_buf_size = handle->config.audio_enable ? 
      (handle->audio.codec->frame_size * 
       handle->params.channels * sizeof(int16_t)) : 0;
   void *audio_buf = NULL;

   if (audio_buf_size)
      audio_buf = av_malloc(audio_buf_size);
   /* Try pushing data in an interleaving pattern to 
    * ease the work of the muxer a bit. */

   do
   {
      struct ffemu_video_data attr_buf;

      did_work = false;

      if (handle->config.audio_enable)
      {
         if (fifo_read_avail(handle->audio_fifo) >= audio_buf_size)
         {
            struct ffemu_audio_data aud = {0};

            fifo_read(handle->audio_fifo, audio_buf, audio_buf_size);

            aud.frames = handle->audio.codec->frame_size;
            aud.data = audio_buf;

            ffmpeg_push_audio_thread(handle, &aud, true);
            did_work = true;
         }
      }

      if (fifo_read_avail(handle->attr_fifo) >= sizeof(attr_buf))
      {
         fifo_read(handle->attr_fifo, &attr_buf, sizeof(attr_buf));
         fifo_read(handle->video_fifo, video_buf, 
               attr_buf.height * attr_buf.pitch);
         attr_buf.data = video_buf;
         ffmpeg_push_video_thread(handle, &attr_buf);

         did_work = true;
      }
   } while (did_work);

   /* Flush out last audio. */
   if (handle->config.audio_enable)
      ffmpeg_flush_audio(handle, audio_buf, audio_buf_size);

   /* Flush out last video. */
   ffmpeg_flush_video(handle);

   av_free(video_buf);
   av_free(audio_buf);
}
Esempio n. 3
0
static void ffmpeg_flush_audio(ffmpeg_t *handle, void *audio_buf,
      size_t audio_buf_size)
{
   size_t avail = fifo_read_avail(handle->audio_fifo);

   if (avail)
   {
      struct ffemu_audio_data aud = {0};

      fifo_read(handle->audio_fifo, audio_buf, avail);

      aud.frames = avail / (sizeof(int16_t) * handle->params.channels);
      aud.data = audio_buf;

      ffmpeg_push_audio_thread(handle, &aud, false);
   }

   for (;;)
   {
      AVPacket pkt;
      if (!encode_audio(handle, &pkt, true) || !pkt.size ||
            av_interleaved_write_frame(handle->muxer.ctx, &pkt) < 0)
         break;
   }
}
Esempio n. 4
0
static uint32_t resampler_cb(void *userdata, float **data)
{
   audioport_t *port = userdata;
   uint32_t has_read = 0;

   if (port->sample_cb)
      has_read = port->sample_cb(port->re_pull_buffer, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t), port->userdata);
   else
   {
      has_read = CELL_AUDIO_BLOCK_SAMPLES * port->channels;
      sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT);
      uint32_t avail = fifo_read_avail(port->buffer);
      if (avail < CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t))
         has_read = avail / sizeof(int16_t);

      fifo_read(port->buffer, port->re_pull_buffer, has_read * sizeof(int16_t));
      sys_lwmutex_unlock(&port->lock);
      sys_lwcond_signal(&port->cond);
   }

   if (has_read < CELL_AUDIO_BLOCK_SAMPLES * port->channels * 2)
      memset(port->re_pull_buffer + has_read, 0, (CELL_AUDIO_BLOCK_SAMPLES * port->channels - has_read) * sizeof(int16_t));

   audio_convert_s16_to_float_altivec(port->re_buffer, port->re_pull_buffer, CELL_AUDIO_BLOCK_SAMPLES * port->channels);

   *data = port->re_buffer;
   return CELL_AUDIO_BLOCK_SAMPLES;
}
Esempio n. 5
0
static void pull_event_loop(audioport_t *port, sys_event_queue_t id)
{
   sys_event_t event;

   int16_t *in_buf = memalign(128, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t));
   float *conv_buf = memalign(128, CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(float));
   while (!port->quit_thread)
   {
      uint32_t has_read = 0;
      if (port->sample_cb)
         has_read = port->sample_cb(in_buf, CELL_AUDIO_BLOCK_SAMPLES * port->channels, port->userdata);
      else
      {
         has_read = CELL_AUDIO_BLOCK_SAMPLES * port->channels;
         sys_lwmutex_lock(&port->lock, SYS_NO_TIMEOUT);
         uint32_t avail = fifo_read_avail(port->buffer);
         if (avail < CELL_AUDIO_BLOCK_SAMPLES * port->channels * sizeof(int16_t))
            has_read = avail / sizeof(int16_t);

         fifo_read(port->buffer, in_buf, has_read * sizeof(int16_t));
         sys_lwmutex_unlock(&port->lock);
      }

      if (has_read < CELL_AUDIO_BLOCK_SAMPLES * port->channels)
         memset(in_buf + has_read, 0, (CELL_AUDIO_BLOCK_SAMPLES * port->channels - has_read) * sizeof(int16_t));

      resampler_int16_t_to_float(conv_buf, in_buf, CELL_AUDIO_BLOCK_SAMPLES * port->channels);
      sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT);
      cellAudioAddData(port->audio_port, conv_buf, CELL_AUDIO_BLOCK_SAMPLES, 1.0);

      pthread_cond_signal(&port->cond);
   }
   free(conv_buf);
}
Esempio n. 6
0
static void event_loop(uint64_t data)
#endif
{
   float out_tmp[CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS]
      __attribute__((aligned(16)));
   sys_event_queue_t id;
   sys_ipc_key_t key;
   sys_event_t event;
   ps3_audio_t *aud = data;

   cellAudioCreateNotifyEventQueue(&id, &key);
   cellAudioSetNotifyEventQueue(key);

   while (!aud->quit_thread)
   {
      sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT);

      sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT);
      if (fifo_read_avail(aud->buffer) >= sizeof(out_tmp))
         fifo_read(aud->buffer, out_tmp, sizeof(out_tmp));
      else
         memset(out_tmp, 0, sizeof(out_tmp));
      sys_lwmutex_unlock(&aud->lock);
      sys_lwcond_signal(&aud->cond);

      cellAudioAddData(aud->audio_port, out_tmp,
            CELL_AUDIO_BLOCK_SAMPLES, 1.0);
   }

   cellAudioRemoveNotifyEventQueue(key);
   sys_ppu_thread_exit(0);
}
Esempio n. 7
0
static OSStatus audio_write_cb(void *userdata, AudioUnitRenderActionFlags *action_flags,
      const AudioTimeStamp *time_stamp, UInt32 bus_number,
      UInt32 number_frames, AudioBufferList *io_data)
{
   coreaudio_t *dev = (coreaudio_t*)userdata;
   (void)time_stamp;
   (void)bus_number;
   (void)number_frames;

   if (!io_data)
      return noErr;
   if (io_data->mNumberBuffers != 1)
      return noErr;

   unsigned write_avail = io_data->mBuffers[0].mDataByteSize;
   void *outbuf = io_data->mBuffers[0].mData;

   pthread_mutex_lock(&dev->lock);
   if (fifo_read_avail(dev->buffer) < write_avail)
   {
      *action_flags = kAudioUnitRenderAction_OutputIsSilence;
      memset(outbuf, 0, write_avail); // Seems to be needed.
      pthread_mutex_unlock(&dev->lock);
      pthread_cond_signal(&dev->cond); // Technically possible to deadlock without.
      return noErr;
   }

   fifo_read(dev->buffer, outbuf, write_avail);
   pthread_mutex_unlock(&dev->lock);
   pthread_cond_signal(&dev->cond);
   return noErr;
}
Esempio n. 8
0
static void ffemu_flush_buffers(ffemu_t *handle)
{
   void *video_buf = av_malloc(2 * handle->params.fb_width * handle->params.fb_height * handle->video.pix_size);
   size_t audio_buf_size = 512 * handle->params.channels * sizeof(int16_t);
   int16_t *audio_buf = (int16_t*)av_malloc(audio_buf_size);

   // Try pushing data in an interleaving pattern to ease the work of the muxer a bit.
   bool did_work;
   do
   {
      did_work = false;

      if (fifo_read_avail(handle->audio_fifo) >= audio_buf_size)
      {
         fifo_read(handle->audio_fifo, audio_buf, audio_buf_size);

         struct ffemu_audio_data aud = {0};
         aud.frames = 512;
         aud.data = audio_buf;

         ffemu_push_audio_thread(handle, &aud, true);
         did_work = true;
      }

      struct ffemu_video_data attr_buf;
      if (fifo_read_avail(handle->attr_fifo) >= sizeof(attr_buf))
      {
         fifo_read(handle->attr_fifo, &attr_buf, sizeof(attr_buf));
         fifo_read(handle->video_fifo, video_buf, attr_buf.height * attr_buf.pitch);
         attr_buf.data = video_buf;
         ffemu_push_video_thread(handle, &attr_buf);

         did_work = true;
      }
   } while (did_work);

   // Flush out last audio.
   ffemu_flush_audio(handle, audio_buf, audio_buf_size);

   // Flush out last video.
   ffemu_flush_video(handle);

   av_free(video_buf);
   av_free(audio_buf);
}
Esempio n. 9
0
static void adapter_thread(void *data)
{
   uint8_t __attribute__((aligned(32))) send_command_buf[4096];
   struct wiiusb_adapter *adapter = (struct wiiusb_adapter*)data;
   wiiusb_hid_t *hid = adapter ? adapter->hid : NULL;

   if (!adapter)
      return;

   while (!adapter->quitting)
   {
      size_t send_command_size;
      int tmp;
      int report_number;
      int size = 0;

      (void)tmp;
      (void)report_number;

      slock_lock(adapter->send_control_lock);

      if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size))
      {
         fifo_read(adapter->send_control_buffer, &send_command_size, sizeof(send_command_size));
         if (fifo_read_avail(adapter->send_control_buffer) >= sizeof(send_command_size))
         {
            fifo_read(adapter->send_control_buffer, send_command_buf, send_command_size);
            USB_WriteIntrMsg(adapter->handle, adapter->endpoint_out, send_command_size, send_command_buf);
         }
      }
      slock_unlock(adapter->send_control_lock);

      size = USB_ReadIntrMsg(adapter->handle, adapter->endpoint_in, adapter->endpoint_in_max_size, &adapter->data[0]);
      /* RARCH_LOG("%p USB_ReadIntrMsg(%i, %i, %i, %p): %i\n", &adapter->data[0],
         adapter->handle, adapter->endpoint_in, adapter->endpoint_in_max_size, &adapter->data[0],
         size); */

      //RARCH_LOG("%03i %03i %03i %03i\n", adapter->data[0], adapter->data[1], adapter->data[2], adapter->data[3], adapter->data[4]);
      //memmove(&adapter->data[1], &adapter->data[0], 2048);

      if (adapter && hid && hid->slots && size)
         pad_connection_packet(&hid->slots[adapter->slot], adapter->slot,
               adapter->data - 1, size+1);
   }
}
Esempio n. 10
0
static void alsa_worker_thread(void *data)
{
   alsa_thread_t *alsa = (alsa_thread_t*)data;
   uint8_t        *buf = (uint8_t *)calloc(1, alsa->period_size);

   if (!buf)
   {
      RARCH_ERR("failed to allocate audio buffer");
      goto end;
   }

   while (!alsa->thread_dead)
   {
      size_t avail;
      size_t fifo_size;
      snd_pcm_sframes_t frames;
      slock_lock(alsa->fifo_lock);
      avail = fifo_read_avail(alsa->buffer);
      fifo_size = MIN(alsa->period_size, avail);
      fifo_read(alsa->buffer, buf, fifo_size);
      scond_signal(alsa->cond);
      slock_unlock(alsa->fifo_lock);

      /* If underrun, fill rest with silence. */
      memset(buf + fifo_size, 0, alsa->period_size - fifo_size);

      frames = snd_pcm_writei(alsa->pcm, buf, alsa->period_frames);

      if (frames == -EPIPE || frames == -EINTR || 
            frames == -ESTRPIPE)
      {
         if (snd_pcm_recover(alsa->pcm, frames, 1) < 0)
         {
            RARCH_ERR("[ALSA]: (#2) Failed to recover from error (%s)\n",
                  snd_strerror(frames));
            break;
         }

         continue;
      }
      else if (frames < 0)
      {
         RARCH_ERR("[ALSA]: Unknown error occurred (%s).\n",
               snd_strerror(frames));
         break;
      }
   }

end:
   slock_lock(alsa->cond_lock);
   alsa->thread_dead = true;
   scond_signal(alsa->cond);
   slock_unlock(alsa->cond_lock);
   free(buf);
}
Esempio n. 11
0
static ssize_t audio_cb(void *data, size_t bytes, void *userdata)
{
   rsd_t *rsd = (rsd_t*)userdata;

   size_t avail = fifo_read_avail(rsd->buffer);
   size_t write_size = bytes > avail ? avail : bytes;
   fifo_read(rsd->buffer, data, write_size);
   scond_signal(rsd->cond);

   return write_size;
}
Esempio n. 12
0
static void sdl_audio_cb(void *data, Uint8 *stream, int len)
{
   sdl_audio_t *sdl = (sdl_audio_t*)data;

   size_t avail = fifo_read_avail(sdl->buffer);
   size_t write_size = len > (int)avail ? avail : len;
   fifo_read(sdl->buffer, stream, write_size);
   scond_signal(sdl->cond);

   // If underrun, fill rest with silence.
   memset(stream + write_size, 0, len - write_size);
}
Esempio n. 13
0
static void ffemu_thread(void *data)
{
   ffemu_t *ff = (ffemu_t*)data;

   // For some reason, FFmpeg has a tendency to crash if we don't overallocate a bit. :s
   void *video_buf = av_malloc(2 * ff->params.fb_width * ff->params.fb_height * ff->video.pix_size);
   assert(video_buf);

   size_t audio_buf_size = 512 * ff->params.channels * sizeof(int16_t);
   int16_t *audio_buf = (int16_t*)av_malloc(audio_buf_size);
   assert(audio_buf);

   while (ff->alive)
   {
      struct ffemu_video_data attr_buf;

      bool avail_video = false;
      bool avail_audio = false;

      slock_lock(ff->lock);
      if (fifo_read_avail(ff->attr_fifo) >= sizeof(attr_buf))
         avail_video = true;

      if (fifo_read_avail(ff->audio_fifo) >= audio_buf_size)
         avail_audio = true;
      slock_unlock(ff->lock);

      if (!avail_video && !avail_audio)
      {
         slock_lock(ff->cond_lock);
         if (ff->can_sleep)
         {
            ff->can_sleep = false;
            scond_wait(ff->cond, ff->cond_lock);
            ff->can_sleep = true;
         }
         else
            scond_signal(ff->cond);

         slock_unlock(ff->cond_lock);
      }

      if (avail_video)
      {
         slock_lock(ff->lock);
         fifo_read(ff->attr_fifo, &attr_buf, sizeof(attr_buf));
         fifo_read(ff->video_fifo, video_buf, attr_buf.height * attr_buf.pitch);
         slock_unlock(ff->lock);
         scond_signal(ff->cond);

         attr_buf.data = video_buf;
         ffemu_push_video_thread(ff, &attr_buf);
      }

      if (avail_audio)
      {
         slock_lock(ff->lock);
         fifo_read(ff->audio_fifo, audio_buf, audio_buf_size);
         slock_unlock(ff->lock);
         scond_signal(ff->cond);

         struct ffemu_audio_data aud = {0};
         aud.frames = 512;
         aud.data = audio_buf;

         ffemu_push_audio_thread(ff, &aud, true);
      }
   }

   av_free(video_buf);
   av_free(audio_buf);
}
Esempio n. 14
0
static void dsound_thread(void *data)
{
   DWORD write_ptr;
   dsound_t *ds = (dsound_t*)data;

   SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

   get_positions(ds, NULL, &write_ptr);
   write_ptr = (write_ptr + ds->buffer_size / 2) % ds->buffer_size;

   while (ds->thread_alive)
   {
      struct audio_lock region;
      DWORD read_ptr, avail, fifo_avail;
      get_positions(ds, &read_ptr, NULL);
      
      avail = write_avail(read_ptr, write_ptr, ds->buffer_size);

      EnterCriticalSection(&ds->crit);
      fifo_avail = fifo_read_avail(ds->buffer);
      LeaveCriticalSection(&ds->crit);

      if (avail < CHUNK_SIZE || ((fifo_avail < CHUNK_SIZE) && (avail < ds->buffer_size / 2)))
      {
         /* No space to write, or we don't have data in our fifo, 
          * but we can wait some time before it underruns ... */


         /* We could opt for using the notification interface,
          * but it is not guaranteed to work, so use high 
          * priority sleeping patterns.
          */
         retro_sleep(1);
         continue;
      }

      if (!grab_region(ds, write_ptr, &region))
      {
         ds->thread_alive = false;
         SetEvent(ds->event);
         break;
      }

      if (fifo_avail < CHUNK_SIZE)
      {
         /* Got space to write, but nothing in FIFO (underrun), 
          * fill block with silence. */

         memset(region.chunk1, 0, region.size1);
         memset(region.chunk2, 0, region.size2);

         release_region(ds, &region);
         write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size;
      }
      else 
      {
         /* All is good. Pull from it and notify FIFO. */

         EnterCriticalSection(&ds->crit);
         if (region.chunk1)
            fifo_read(ds->buffer, region.chunk1, region.size1);
         if (region.chunk2)
            fifo_read(ds->buffer, region.chunk2, region.size2);
         LeaveCriticalSection(&ds->crit);

         release_region(ds, &region);
         write_ptr = (write_ptr + region.size1 + region.size2) % ds->buffer_size;

         SetEvent(ds->event);
      }
   }

   ExitThread(0);
}
Esempio n. 15
0
static void ffmpeg_thread(void *data)
{
   size_t audio_buf_size;
   void *audio_buf = NULL;
   ffmpeg_t *ff    = (ffmpeg_t*)data;
   /* For some reason, FFmpeg has a tendency to crash 
    * if we don't overallocate a bit. */
   void *video_buf = av_malloc(2 * ff->params.fb_width *
         ff->params.fb_height * ff->video.pix_size);

   retro_assert(video_buf);

   audio_buf_size = ff->config.audio_enable ? 
      (ff->audio.codec->frame_size * ff->params.channels * sizeof(int16_t)) : 0;
   audio_buf      = audio_buf_size ? av_malloc(audio_buf_size) : NULL;

   while (ff->alive)
   {
      struct ffemu_video_data attr_buf;

      bool avail_video = false;
      bool avail_audio = false;

      slock_lock(ff->lock);
      if (fifo_read_avail(ff->attr_fifo) >= sizeof(attr_buf))
         avail_video = true;

      if (ff->config.audio_enable)
         if (fifo_read_avail(ff->audio_fifo) >= audio_buf_size)
            avail_audio = true;
      slock_unlock(ff->lock);

      if (!avail_video && !avail_audio)
      {
         slock_lock(ff->cond_lock);
         if (ff->can_sleep)
         {
            ff->can_sleep = false;
            scond_wait(ff->cond, ff->cond_lock);
            ff->can_sleep = true;
         }
         else
            scond_signal(ff->cond);

         slock_unlock(ff->cond_lock);
      }

      if (avail_video && video_buf)
      {
         slock_lock(ff->lock);
         fifo_read(ff->attr_fifo, &attr_buf, sizeof(attr_buf));
         fifo_read(ff->video_fifo, video_buf,
               attr_buf.height * attr_buf.pitch);
         slock_unlock(ff->lock);
         scond_signal(ff->cond);

         attr_buf.data = video_buf;
         ffmpeg_push_video_thread(ff, &attr_buf);
      }

      if (avail_audio && audio_buf)
      {
         struct ffemu_audio_data aud = {0};

         slock_lock(ff->lock);
         fifo_read(ff->audio_fifo, audio_buf, audio_buf_size);
         slock_unlock(ff->lock);
         scond_signal(ff->cond);

         aud.frames = ff->audio.codec->frame_size;
         aud.data = audio_buf;

         ffmpeg_push_audio_thread(ff, &aud, true);
      }
   }

   av_free(video_buf);
   av_free(audio_buf);
}