Mercurial > mplayer.hg
changeset 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 | 340e60d5b46b |
children | c3f295ceae51 |
files | libao2/ao_jack.c libao2/ao_sdl.c |
diffstat | 2 files changed, 54 insertions(+), 131 deletions(-) [+] |
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;
--- a/libao2/ao_sdl.c Mon Mar 09 17:25:43 2009 +0000 +++ b/libao2/ao_sdl.c Mon Mar 09 18:21:47 2009 +0000 @@ -3,8 +3,6 @@ * * Copyleft 2001 by Felix Bünemann (atmosfear@users.sf.net) * - * Thanks to Arpi for nice ringbuffer-code! - * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify @@ -36,7 +34,7 @@ #include <SDL.h> #include "osdep/timer.h" -#include "libvo/fastmemcpy.h" +#include "libavutil/fifo.h" static const ao_info_t info = { @@ -60,76 +58,34 @@ #define CHUNK_SIZE 4096 #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) -static unsigned char *buffer; +static AVFifoBuffer *buffer; -// may only be modified by SDL's playback thread or while it is stopped -static volatile int read_pos; -// may only be modified by mplayer's thread -static volatile int write_pos; #ifdef USE_SDL_INTERNAL_MIXER static unsigned char volume=SDL_MIX_MAXVOLUME; #endif -// 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; -} - -// may only be called by SDL's 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 int write_buffer(unsigned char* data,int len){ + int free = BUFFSIZE - av_fifo_size(buffer); + if (len > free) len = free; + return av_fifo_generic_write(buffer, data, len, NULL); } -static int write_buffer(unsigned char* data,int len){ - int first_len = BUFFSIZE - write_pos; - int free = buf_free(); - 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; +#ifdef USE_SDL_INTERNAL_MIXER +static void mix_audio(void *dst, void *src, int len) { + SDL_MixAudio(dst, src, len, volume); } +#endif static int read_buffer(unsigned char* data,int len){ - int first_len = BUFFSIZE - read_pos; - int buffered = buf_used(); + int buffered = av_fifo_size(buffer); if (len > buffered) len = buffered; - if (first_len > len) first_len = len; - // till end of buffer #ifdef USE_SDL_INTERNAL_MIXER - SDL_MixAudio (data, &buffer[read_pos], first_len, volume); + return av_fifo_generic_read(buffer, data, len, mix_audio); #else - fast_memcpy (data, &buffer[read_pos], first_len); + return av_fifo_generic_read(buffer, data, len, NULL); #endif - if (len > first_len) { // we have to wrap around - // remaining part from beginning of buffer -#ifdef USE_SDL_INTERNAL_MIXER - SDL_MixAudio (&data[first_len], buffer, len - first_len, volume); -#else - fast_memcpy (&data[first_len], buffer, len - first_len); -#endif - } - read_pos = (read_pos + len) % BUFFSIZE; - return len; } // end ring buffer stuff @@ -175,7 +131,7 @@ SDL_AudioSpec aspec, obtained; /* Allocate ring-buffer memory */ - buffer = (unsigned char *) malloc(BUFFSIZE); + buffer = av_fifo_alloc(BUFFSIZE); mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_SDL_INFO, rate, (channels > 1) ? "Stereo" : "Mono", af_fmt2str_short(format)); @@ -278,7 +234,6 @@ ao_data.buffersize=obtained.size; ao_data.outburst = CHUNK_SIZE; - reset(); /* unsilence audio, if callback is ready */ SDL_PauseAudio(0); @@ -292,6 +247,7 @@ usec_sleep(get_delay() * 1000 * 1000); SDL_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); + av_fifo_free(buffer); } // stop playing and empty buffers (for seeking/pause) @@ -301,8 +257,7 @@ SDL_PauseAudio(1); /* Reset ring-buffer state */ - read_pos = 0; - write_pos = 0; + av_fifo_reset(buffer); SDL_PauseAudio(0); } @@ -325,7 +280,7 @@ // return: how many bytes can be played without blocking static int get_space(void){ - return buf_free(); + return BUFFSIZE - av_fifo_size(buffer); } // plays 'len' bytes of 'data' @@ -352,7 +307,7 @@ // return: delay in seconds between first and last sample in buffer static float get_delay(void){ - int buffered = BUFFSIZE - CHUNK_SIZE - buf_free(); // could be less + int buffered = av_fifo_size(buffer); // could be less return (float)(buffered + ao_data.buffersize)/(float)ao_data.bps; }