Example #1
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 = handle->config.audio_enable ? (handle->audio.codec->frame_size * handle->params.channels * sizeof(int16_t)) : 0;
   void *audio_buf = audio_buf_size ? av_malloc(audio_buf_size) : NULL;

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

      if (handle->config.audio_enable)
      {
         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 = handle->audio.codec->frame_size;
            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.
   if (handle->config.audio_enable)
      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);
}
Example #2
0
static void ffemu_flush_audio(ffemu_t *handle, int16_t *audio_buf, size_t audio_buf_size)
{
   size_t avail = fifo_read_avail(handle->audio_fifo);
   if (avail)
   {
      fifo_read(handle->audio_fifo, audio_buf, avail);

      struct ffemu_audio_data aud = {0};
      aud.frames = avail / (sizeof(int16_t) * handle->params.channels);
      aud.data = audio_buf;

      ffemu_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;
   }
}
Example #3
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);
}