diff libao2/ao_jack.c @ 28882:15f93fd5cd48

Reuse libavutil fifo code instead of reimplementing it over and over.
author reimar
date Mon, 09 Mar 2009 18:21:47 +0000
parents 9a5b8c2ed6de
children f951680cfea2
line wrap: on
line diff
--- a/libao2/ao_jack.c	Mon Mar 09 17:25:43 2009 +0000
+++ b/libao2/ao_jack.c	Mon Mar 09 18:21:47 2009 +0000
@@ -36,7 +36,7 @@
 #include "osdep/timer.h"
 #include "subopt-helper.h"
 
-#include "libvo/fastmemcpy.h"
+#include "libavutil/fifo.h"
 
 #include <jack/jack.h>
 
@@ -68,47 +68,10 @@
 #define CHUNK_SIZE (16 * 1024)
 //! number of "virtual" chunks the buffer consists of
 #define NUM_CHUNKS 8
-// This type of ring buffer may never fill up completely, at least
-// one byte must always be unused.
-// For performance reasons (alignment etc.) one whole chunk always stays
-// empty, not only one byte.
-#define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE)
+#define BUFFSIZE (NUM_CHUNKS * CHUNK_SIZE)
 
 //! buffer for audio data
-static unsigned char *buffer = NULL;
-
-//! buffer read position, may only be modified by playback thread or while it is stopped
-static volatile int read_pos;
-//! buffer write position, may only be modified by MPlayer's thread
-static volatile int write_pos;
-
-/**
- * \brief get the number of free bytes in the buffer
- * \return number of free bytes in buffer
- * 
- * may only be called by MPlayer's thread
- * return value may change between immediately following two calls,
- * and the real number of free bytes might be larger!
- */
-static int buf_free(void) {
-  int free = read_pos - write_pos - CHUNK_SIZE;
-  if (free < 0) free += BUFFSIZE;
-  return free;
-}
-
-/**
- * \brief get amount of data available in the buffer
- * \return number of bytes available in buffer
- *
- * may only be called by the playback thread
- * return value may change between immediately following two calls,
- * and the real number of buffered bytes might be larger!
- */
-static int buf_used(void) {
-  int used = write_pos - read_pos;
-  if (used < 0) used += BUFFSIZE;
-  return used;
-}
+static AVFifoBuffer *buffer;
 
 /**
  * \brief insert len bytes into buffer
@@ -119,22 +82,34 @@
  * If there is not enough room, the buffer is filled up
  */
 static int write_buffer(unsigned char* data, int len) {
-  int first_len = BUFFSIZE - write_pos;
-  int free = buf_free();
+  int free = BUFFSIZE - av_fifo_size(buffer);
   if (len > free) len = free;
-  if (first_len > len) first_len = len;
-  // till end of buffer
-  fast_memcpy (&buffer[write_pos], data, first_len);
-  if (len > first_len) { // we have to wrap around
-    // remaining part from beginning of buffer
-    fast_memcpy (buffer, &data[first_len], len - first_len);
-  }
-  write_pos = (write_pos + len) % BUFFSIZE;
-  return len;
+  return av_fifo_generic_write(buffer, data, len, NULL);
 }
 
 static void silence(float **bufs, int cnt, int num_bufs);
 
+struct deinterleave {
+  float **bufs;
+  int num_bufs;
+  int cur_buf;
+  int pos;
+};
+
+static void deinterleave(void *info, void *src, int len) {
+  struct deinterleave *di = info;
+  float *s = src;
+  int i;
+  len /= sizeof(float);
+  for (i = 0; i < len; i++) {
+    di->bufs[di->cur_buf++][di->pos] = s[i];
+    if (di->cur_buf >= di->num_bufs) {
+      di->cur_buf = 0;
+      di->pos++;
+    }
+  }
+}
+
 /**
  * \brief read data from buffer and splitting it into channels
  * \param bufs num_bufs float buffers, each will contain the data of one channel
@@ -149,18 +124,13 @@
  * with silence.
  */
 static int read_buffer(float **bufs, int cnt, int num_bufs) {
-  int buffered = buf_used();
-  int i, j;
+  struct deinterleave di = {bufs, num_bufs, 0, 0};
+  int buffered = av_fifo_size(buffer);
   if (cnt * sizeof(float) * num_bufs > buffered) {
     silence(bufs, cnt, num_bufs);
     cnt = buffered / sizeof(float) / num_bufs;
   }
-  for (i = 0; i < cnt; i++) {
-    for (j = 0; j < num_bufs; j++) {
-      bufs[j][i] = *(float *)&buffer[read_pos];
-      read_pos = (read_pos + sizeof(float)) % BUFFSIZE;
-    }
-  }
+  av_fifo_generic_read(buffer, &di, cnt * num_bufs * sizeof(float), deinterleave);
   return cnt;
 }
 
@@ -268,7 +238,7 @@
     mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] cannot open server\n");
     goto err_out;
   }
-  reset();
+  buffer = av_fifo_alloc(BUFFSIZE);
   jack_set_process_callback(client, outputaudio, 0);
 
   // list matching ports
@@ -308,7 +278,6 @@
   jack_latency = (float)(jack_port_get_total_latency(client, ports[0]) +
                          jack_get_buffer_size(client)) / (float)rate;
   callback_interval = 0;
-  buffer = malloc(BUFFSIZE);
 
   ao_data.channels = channels;
   ao_data.samplerate = rate;
@@ -327,7 +296,7 @@
   free(client_name);
   if (client)
     jack_client_close(client);
-  free(buffer);
+  av_fifo_free(buffer);
   buffer = NULL;
   return 0;
 }
@@ -340,7 +309,7 @@
   reset();
   usec_sleep(100 * 1000);
   jack_client_close(client);
-  free(buffer);
+  av_fifo_free(buffer);
   buffer = NULL;
 }
 
@@ -349,8 +318,7 @@
  */
 static void reset(void) {
   paused = 1;
-  read_pos = 0;
-  write_pos = 0;
+  av_fifo_reset(buffer);
   paused = 0;
 }
 
@@ -369,7 +337,7 @@
 }
 
 static int get_space(void) {
-  return buf_free();
+  return BUFFSIZE - av_fifo_size(buffer);
 }
 
 /**
@@ -383,7 +351,7 @@
 }
 
 static float get_delay(void) {
-  int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less
+  int buffered = av_fifo_size(buffer); // could be less
   float in_jack = jack_latency;
   if (estimate && callback_interval > 0) {
     float elapsed = (float)GetTimer() / 1000000.0 - callback_time;