diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/output/osx_plugin.c | 93 |
2 files changed, 39 insertions, 56 deletions
@@ -3,6 +3,8 @@ ver 0.16.8 (2012/??/??) * decoder: - vorbis (and others): fix seeking at startup - ffmpeg: read the "year" tag +* output: + - osx: fix stuttering due to buffering bug * fix endless loop in text file reader diff --git a/src/output/osx_plugin.c b/src/output/osx_plugin.c index 5284afc29..501dcec10 100644 --- a/src/output/osx_plugin.c +++ b/src/output/osx_plugin.c @@ -19,6 +19,7 @@ #include "config.h" #include "output_api.h" +#include "fifo_buffer.h" #include <glib.h> #include <AudioUnit/AudioUnit.h> @@ -31,10 +32,8 @@ struct osx_output { AudioUnit au; GMutex *mutex; GCond *condition; - char *buffer; - size_t buffer_size; - size_t pos; - size_t len; + + struct fifo_buffer *buffer; }; /** @@ -64,11 +63,6 @@ osx_output_init(G_GNUC_UNUSED const struct audio_format *audio_format, oo->mutex = g_mutex_new(); oo->condition = g_cond_new(); - oo->pos = 0; - oo->len = 0; - oo->buffer = NULL; - oo->buffer_size = 0; - return oo; } @@ -76,7 +70,6 @@ static void osx_output_finish(void *data) { struct osx_output *od = data; - g_free(od->buffer); g_mutex_free(od->mutex); g_cond_free(od->condition); g_free(od); @@ -87,7 +80,7 @@ static void osx_output_cancel(void *data) struct osx_output *od = data; g_mutex_lock(od->mutex); - od->len = 0; + fifo_buffer_clear(od->buffer); g_mutex_unlock(od->mutex); } @@ -98,6 +91,8 @@ static void osx_output_close(void *data) AudioOutputUnitStop(od->au); AudioUnitUninitialize(od->au); CloseComponent(od->au); + + fifo_buffer_free(od->buffer); } static OSStatus @@ -111,37 +106,29 @@ osx_render(void *vdata, struct osx_output *od = (struct osx_output *) vdata; AudioBuffer *buffer = &buffer_list->mBuffers[0]; size_t buffer_size = buffer->mDataByteSize; - size_t bytes_to_copy; - size_t trailer_length; - size_t dest_pos = 0; - g_mutex_lock(od->mutex); + assert(od->buffer != NULL); - bytes_to_copy = MIN(od->len, buffer_size); - od->len -= bytes_to_copy; + g_mutex_lock(od->mutex); - trailer_length = od->buffer_size - od->pos; - if (bytes_to_copy > trailer_length) { - memcpy((unsigned char*)buffer->mData + dest_pos, - od->buffer + od->pos, trailer_length); - od->pos = 0; - dest_pos += trailer_length; - bytes_to_copy -= trailer_length; - } + size_t nbytes; + const void *src = fifo_buffer_read(od->buffer, &nbytes); - memcpy((unsigned char*)buffer->mData + dest_pos, - od->buffer + od->pos, bytes_to_copy); - od->pos += bytes_to_copy; + if (src != NULL) { + if (nbytes > buffer_size) + nbytes = buffer_size; - if (od->pos >= od->buffer_size) - od->pos = 0; + memcpy(buffer->mData, src, nbytes); + fifo_buffer_consume(od->buffer, nbytes); + } else + nbytes = 0; g_cond_signal(od->condition); g_mutex_unlock(od->mutex); - if (bytes_to_copy < buffer_size) - memset((unsigned char*)buffer->mData + bytes_to_copy, 0, - buffer_size - bytes_to_copy); + if (nbytes < buffer_size) + memset((unsigned char*)buffer->mData + nbytes, 0, + buffer_size - nbytes); return 0; } @@ -244,15 +231,12 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error) } /* create a buffer of 1s */ - od->buffer_size = (audio_format->sample_rate) * - audio_format_frame_size(audio_format); - od->buffer = g_realloc(od->buffer, od->buffer_size); - - od->pos = 0; - od->len = 0; + od->buffer = fifo_buffer_new(audio_format->sample_rate * + audio_format_frame_size(audio_format)); status = AudioOutputUnitStart(od->au); if (status != 0) { + fifo_buffer_free(od->buffer); g_set_error(error, osx_output_quark(), 0, "unable to start audio output: %s", GetMacOSStatusCommentString(status)); @@ -267,33 +251,30 @@ osx_output_play(void *data, const void *chunk, size_t size, G_GNUC_UNUSED GError **error) { struct osx_output *od = data; - size_t start, nbytes; g_mutex_lock(od->mutex); - while (od->len >= od->buffer_size) - /* wait for some free space in the buffer */ - g_cond_wait(od->condition, od->mutex); - - start = od->pos + od->len; - if (start >= od->buffer_size) - start -= od->buffer_size; + void *dest; + size_t max_length; - nbytes = start < od->pos - ? od->pos - start - : od->buffer_size - start; + while (true) { + dest = fifo_buffer_write(od->buffer, &max_length); + if (dest != NULL) + break; - assert(nbytes > 0); + /* wait for some free space in the buffer */ + g_cond_wait(od->condition, od->mutex); + } - if (nbytes > size) - nbytes = size; + if (size > max_length) + size = max_length; - memcpy(od->buffer + start, chunk, nbytes); - od->len += nbytes; + memcpy(dest, chunk, size); + fifo_buffer_append(od->buffer, size); g_mutex_unlock(od->mutex); - return nbytes; + return size; } const struct audio_output_plugin osxPlugin = { |