aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--src/output/osx_plugin.c93
2 files changed, 39 insertions, 56 deletions
diff --git a/NEWS b/NEWS
index 317679bd3..ddb612c3b 100644
--- a/NEWS
+++ b/NEWS
@@ -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 = {