summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--audio/format.c10
-rw-r--r--audio/format.h1
-rw-r--r--audio/out/ao_coreaudio.c43
-rw-r--r--audio/out/ao_coreaudio/ca_ringbuffer.c106
-rw-r--r--audio/out/ao_coreaudio/ca_ringbuffer_internal.h37
-rw-r--r--core/mp_memory_barrier.h23
-rw-r--r--core/mp_ring.c155
-rw-r--r--core/mp_ring.h125
9 files changed, 338 insertions, 166 deletions
diff --git a/Makefile b/Makefile
index 670eb8de26..d39f37c971 100644
--- a/Makefile
+++ b/Makefile
@@ -84,8 +84,7 @@ SOURCES-$(ALSA) += audio/out/ao_alsa.c
SOURCES-$(CACA) += video/out/vo_caca.c
SOURCES-$(SDL) += audio/out/ao_sdl.c
SOURCES-$(SDL2) += video/out/vo_sdl.c
-SOURCES-$(COREAUDIO) += audio/out/ao_coreaudio.c \
- audio/out/ao_coreaudio/ca_ringbuffer.c
+SOURCES-$(COREAUDIO) += audio/out/ao_coreaudio.c
SOURCES-$(COREVIDEO) += video/out/vo_corevideo.m
SOURCES-$(DIRECT3D) += video/out/vo_direct3d.c \
video/out/w32_common.c
@@ -180,6 +179,7 @@ SOURCES = talloc.c \
core/mp_common.c \
core/mp_fifo.c \
core/mp_msg.c \
+ core/mp_ring.c \
core/mplayer.c \
core/options.c \
core/parser-cfg.c \
diff --git a/audio/format.c b/audio/format.c
index 5b1262956c..f9bfcb5ba8 100644
--- a/audio/format.c
+++ b/audio/format.c
@@ -110,6 +110,16 @@ static bool af_fmt_valid(int format)
return (format & AF_FORMAT_MASK) == format;
}
+int af_fmt_seconds_to_bytes(int format, float seconds, int channels)
+{
+ int bps = (af_fmt2bits(format) / 8);
+ int framelen = channels * bps;
+ int bytes = seconds * bps;
+ if (bytes % framelen)
+ bytes += framelen - (bytes % framelen);
+ return bytes;
+}
+
int af_str2fmt_short(bstr str)
{
if (bstr_startswith0(str, "0x")) {
diff --git a/audio/format.h b/audio/format.h
index 30a4aa1cea..bbc7f0fa69 100644
--- a/audio/format.h
+++ b/audio/format.h
@@ -132,6 +132,7 @@ extern const struct af_fmt_entry af_fmtstr_table[];
int af_str2fmt_short(bstr str);
int af_fmt2bits(int format);
char* af_fmt2str(int format, char* str, int size);
+int af_fmt_seconds_to_bytes(int format, float seconds, int channels);
const char* af_fmt2str_short(int format);
#endif /* MPLAYER_AF_FORMAT_H */
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index 930bb2d741..d3491f17f8 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -49,8 +49,7 @@
#include "audio/format.h"
#include "osdep/timer.h"
#include "core/subopt-helper.h"
-
-#include "ao_coreaudio/ca_ringbuffer_internal.h"
+#include "core/mp_ring.h"
#define ca_msg(a, b, c ...) mp_msg(a, b, "AO: [coreaudio] " c)
@@ -58,10 +57,10 @@ static void audio_pause(struct ao *ao);
static void audio_resume(struct ao *ao);
static void reset(struct ao *ao);
-static void print_buffer(struct ca_ringbuffer *buffer)
+static void print_buffer(struct mp_ring *buffer)
{
void *tctx = talloc_new(NULL);
- ca_msg(MSGT_AO, MSGL_V, "%s\n", ca_ringbuffer_repr(buffer, tctx));
+ ca_msg(MSGT_AO, MSGL_V, "%s\n", mp_ring_repr(buffer, tctx));
talloc_free(tctx);
}
@@ -92,7 +91,7 @@ struct priv
int packetSize;
int paused;
- struct ca_ringbuffer *buffer;
+ struct mp_ring *buffer;
};
static OSStatus theRenderProc(void *inRefCon,
@@ -104,14 +103,14 @@ static OSStatus theRenderProc(void *inRefCon,
struct ao *ao = inRefCon;
struct priv *p = ao->priv;
- int buffered = ca_ringbuffer_buffered(p->buffer);
+ int buffered = mp_ring_buffered(p->buffer);
int requested = inNumFrames * p->packetSize;
if (buffered > requested)
buffered = requested;
if (buffered) {
- ca_ringbuffer_read(p->buffer,
+ mp_ring_read(p->buffer,
(unsigned char *)ioData->mBuffers[0].mData,
buffered);
} else {
@@ -622,8 +621,9 @@ static int init(struct ao *ao, char *params)
ao->bps = ao->samplerate * inDesc.mBytesPerFrame;
ao->buffersize = ao->bps;
- p->buffer = ca_ringbuffer_new2(p, ao->bps, maxFrames);
- ao->outburst = ca_ringbuffer_chunk_size(p->buffer);
+ int bufbytes = af_fmt_seconds_to_bytes(ao->format, 0.5, ao->channels.num);
+ p->buffer = mp_ring_new(p, bufbytes);
+ ao->outburst = maxFrames;
print_buffer(p->buffer);
@@ -859,8 +859,9 @@ static int OpenSPDIF(struct ao *ao)
/* For ac3/dts, just use packet size 6144 bytes as chunk size. */
int chunk_size = p->stream_format.mBytesPerPacket;
ao->buffersize = ao->bps;
- p->buffer = ca_ringbuffer_new2(p, ao->bps, chunk_size);
- ao->outburst = ca_ringbuffer_chunk_size(p->buffer);
+ int bufbytes = af_fmt_seconds_to_bytes(ao->format, 0.5, ao->channels.num);
+ p->buffer = mp_ring_new(p, bufbytes);
+ ao->outburst = chunk_size;
print_buffer(p->buffer);
@@ -1071,7 +1072,7 @@ static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice,
{
struct ao *ao = threadGlobals;
struct priv *p = ao->priv;
- int amt = ca_ringbuffer_buffered(p->buffer);
+ int amt = mp_ring_buffered(p->buffer);
AudioBuffer ca_buffer = outOutputData->mBuffers[p->i_stream_index];
int req = ca_buffer.mDataByteSize;
@@ -1079,9 +1080,9 @@ static OSStatus RenderCallbackSPDIF(AudioDeviceID inDevice,
amt = req;
if (amt) {
if (p->b_muted) {
- ca_ringbuffer_read(p->buffer, NULL, amt);
+ mp_ring_read(p->buffer, NULL, amt);
} else {
- ca_ringbuffer_read(p->buffer, (unsigned char *)ca_buffer.mData, amt);
+ mp_ring_read(p->buffer, (unsigned char *)ca_buffer.mData, amt);
}
}
@@ -1116,7 +1117,7 @@ static int play(struct ao *ao, void *output_samples, int num_bytes, int flags)
"Detected current stream does not support digital.\n");
}
- wrote = ca_ringbuffer_write(p->buffer, output_samples, num_bytes);
+ wrote = mp_ring_write(p->buffer, output_samples, num_bytes);
audio_resume(ao);
return wrote;
@@ -1127,7 +1128,7 @@ static void reset(struct ao *ao)
{
struct priv *p = ao->priv;
audio_pause(ao);
- ca_ringbuffer_reset(p->buffer);
+ mp_ring_reset(p->buffer);
}
@@ -1135,7 +1136,7 @@ static void reset(struct ao *ao)
static int get_space(struct ao *ao)
{
struct priv *p = ao->priv;
- return ca_ringbuffer_available(p->buffer);
+ return mp_ring_available(p->buffer);
}
@@ -1144,7 +1145,7 @@ static float get_delay(struct ao *ao)
{
// inaccurate, should also contain the data buffered e.g. by the OS
struct priv *p = ao->priv;
- return ca_ringbuffer_buffered(p->buffer) / (float)ao->bps;
+ return mp_ring_buffered(p->buffer) / (float)ao->bps;
}
static void uninit(struct ao *ao, bool immed)
@@ -1154,9 +1155,9 @@ static void uninit(struct ao *ao, bool immed)
if (!immed) {
long long timeleft =
- (1000000LL * ca_ringbuffer_buffered(p->buffer)) / ao->bps;
- ca_msg(MSGT_AO, MSGL_DBG2, "%d bytes left @%d bps (%d usec)\n", ca_ringbuffer_buffered(
- p->buffer), ao->bps, (int)timeleft);
+ (1000000LL * mp_ring_buffered(p->buffer)) / ao->bps;
+ ca_msg(MSGT_AO, MSGL_DBG2, "%d bytes left @%d bps (%d usec)\n",
+ mp_ring_buffered(p->buffer), ao->bps, (int)timeleft);
mp_sleep_us((int)timeleft);
}
diff --git a/audio/out/ao_coreaudio/ca_ringbuffer.c b/audio/out/ao_coreaudio/ca_ringbuffer.c
deleted file mode 100644
index 717466945d..0000000000
--- a/audio/out/ao_coreaudio/ca_ringbuffer.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libavutil/fifo.h>
-#include "talloc.h"
-
-#include "ca_ringbuffer_internal.h"
-
-struct ca_ringbuffer {
- AVFifoBuffer *fifo;
- int len;
- int chunks;
- int chunk_size;
-};
-
-struct ca_ringbuffer *ca_ringbuffer_new(void *talloc_ctx, int chunks, int chunk_size)
-{
- struct ca_ringbuffer *buffer =
- talloc_zero(talloc_ctx, struct ca_ringbuffer);
-
- *buffer = (struct ca_ringbuffer) {
- .fifo = av_fifo_alloc(chunks * chunk_size),
- .len = chunks * chunk_size,
- .chunks = chunks,
- .chunk_size = chunk_size,
- };
-
- return buffer;
-}
-
-struct ca_ringbuffer *ca_ringbuffer_new2(void *talloc_ctx, int bps, int chunk_size)
-{
- int chunks = (bps + chunk_size - 1) / chunk_size;
- return ca_ringbuffer_new(talloc_ctx, chunks, chunk_size);
-}
-
-int ca_ringbuffer_read(struct ca_ringbuffer *buffer,
- unsigned char *data, int len)
-{
- int buffered = ca_ringbuffer_buffered(buffer);
- if (len > buffered)
- len = buffered;
- if (data)
- av_fifo_generic_read(buffer->fifo, data, len, NULL);
- else
- av_fifo_drain(buffer->fifo, len);
- return len;
-}
-
-int ca_ringbuffer_write(struct ca_ringbuffer *buffer,
- unsigned char *data, int len)
-{
- int free = buffer->len - av_fifo_size(buffer->fifo);
- if (len > free)
- len = free;
- return av_fifo_generic_write(buffer->fifo, data, len, NULL);
-}
-
-void ca_ringbuffer_reset(struct ca_ringbuffer *buffer)
-{
- av_fifo_reset(buffer->fifo);
-}
-
-int ca_ringbuffer_available(struct ca_ringbuffer *buffer)
-{
- return ca_ringbuffer_size(buffer) - ca_ringbuffer_buffered(buffer);
-}
-
-int ca_ringbuffer_size(struct ca_ringbuffer *buffer)
-{
- return buffer->len;
-}
-
-int ca_ringbuffer_buffered(struct ca_ringbuffer *buffer)
-{
- return av_fifo_size(buffer->fifo);
-}
-
-int ca_ringbuffer_chunk_size(struct ca_ringbuffer *buffer)
-{
- return buffer->chunk_size;
-}
-
-char *ca_ringbuffer_repr(struct ca_ringbuffer *buffer, void *talloc_ctx)
-{
- return talloc_asprintf(
- talloc_ctx,
- "Ringbuffer { .chunks = %d bytes, .chunk_size = %d bytes, .size = %d bytes }",
- buffer->chunks,
- ca_ringbuffer_chunk_size(buffer),
- ca_ringbuffer_size(buffer));
-}
diff --git a/audio/out/ao_coreaudio/ca_ringbuffer_internal.h b/audio/out/ao_coreaudio/ca_ringbuffer_internal.h
deleted file mode 100644
index 50b41871b9..0000000000
--- a/audio/out/ao_coreaudio/ca_ringbuffer_internal.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef MPV_AUDIO_OUT_CA_RINGBUFFER_H
-#define MPV_AUDIO_OUT_CA_RINGBUFFER_H
-
-struct ca_ringbuffer;
-
-struct ca_ringbuffer *ca_ringbuffer_new(void *talloc_ctx, int chunks, int chunk_size);
-struct ca_ringbuffer *ca_ringbuffer_new2(void *talloc_ctx, int bps, int chunk_size);
-int ca_ringbuffer_read(struct ca_ringbuffer *buffer, unsigned char *data, int len);
-int ca_ringbuffer_write(struct ca_ringbuffer *buffer, unsigned char *data, int len);
-
-void ca_ringbuffer_reset(struct ca_ringbuffer *buffer);
-
-int ca_ringbuffer_available(struct ca_ringbuffer *buffer);
-int ca_ringbuffer_size(struct ca_ringbuffer *buffer);
-int ca_ringbuffer_buffered(struct ca_ringbuffer *buffer);
-int ca_ringbuffer_chunk_size(struct ca_ringbuffer *buffer);
-
-char *ca_ringbuffer_repr(struct ca_ringbuffer *buffer, void *talloc_ctx);
-
-#endif
diff --git a/core/mp_memory_barrier.h b/core/mp_memory_barrier.h
new file mode 100644
index 0000000000..e27825de8f
--- /dev/null
+++ b/core/mp_memory_barrier.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of mpv.
+ * Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// At this point both gcc and clang had __sync_synchronize support for some
+// time. We only support a full memory barrier.
+
+#define mp_memory_barrier() __sync_synchronize()
+#define mp_atomic_add_and_fetch(a, b) __sync_add_and_fetch(a, b)
diff --git a/core/mp_ring.c b/core/mp_ring.c
new file mode 100644
index 0000000000..207dc62e86
--- /dev/null
+++ b/core/mp_ring.c
@@ -0,0 +1,155 @@
+/*
+ * This file is part of mpv.
+ * Copyright (c) 2012 wm4
+ * Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <inttypes.h>
+#include <libavutil/common.h>
+#include <assert.h>
+#include "talloc.h"
+#include "core/mp_memory_barrier.h"
+#include "core/mp_ring.h"
+
+struct mp_ring {
+ uint8_t *buffer;
+
+ /* Positions of thes first readable/writeable chunks. Do not read this
+ * fields but use the atomic private accessors `mp_ring_get_wpos`
+ * and `mp_ring_get_rpos`. */
+ uint32_t rpos, wpos;
+};
+
+static uint32_t mp_ring_get_wpos(struct mp_ring *buffer)
+{
+ mp_memory_barrier();
+ return buffer->wpos;
+}
+
+static uint32_t mp_ring_get_rpos(struct mp_ring *buffer)
+{
+ mp_memory_barrier();
+ return buffer->rpos;
+}
+
+struct mp_ring *mp_ring_new(void *talloc_ctx, int size)
+{
+ struct mp_ring *ringbuffer =
+ talloc_zero(talloc_ctx, struct mp_ring);
+
+ *ringbuffer = (struct mp_ring) {
+ .buffer = talloc_size(talloc_ctx, size),
+ };
+
+ return ringbuffer;
+}
+
+int mp_ring_drain(struct mp_ring *buffer, int len)
+{
+ int buffered = mp_ring_buffered(buffer);
+ int drain_len = FFMIN(len, buffered);
+ mp_atomic_add_and_fetch(&buffer->rpos, drain_len);
+ mp_memory_barrier();
+ return drain_len;
+}
+
+int mp_ring_read(struct mp_ring *buffer, unsigned char *dest, int len)
+{
+ if (!dest) return mp_ring_drain(buffer, len);
+
+ int size = mp_ring_size(buffer);
+ int buffered = mp_ring_buffered(buffer);
+ int read_len = FFMIN(len, buffered);
+ int read_ptr = mp_ring_get_rpos(buffer) % size;
+
+ int len1 = FFMIN(size - read_ptr, read_len);
+ int len2 = read_len - len1;
+
+ memcpy(dest, buffer->buffer + read_ptr, len1);
+ memcpy(dest + len1, buffer->buffer, len2);
+
+ mp_atomic_add_and_fetch(&buffer->rpos, read_len);
+ mp_memory_barrier();
+
+ return read_len;
+}
+
+int mp_ring_read_cb(struct mp_ring *buffer, void *ctx, int len,
+ void (*func)(void*, void*, int))
+{
+ // The point of this function is defining custom read behaviour, assume
+ // it's a programmers error if func is null.
+ assert(func);
+
+ int size = mp_ring_size(buffer);
+ int buffered = mp_ring_buffered(buffer);
+ int read_len = FFMIN(len, buffered);
+ int read_ptr = mp_ring_get_rpos(buffer) % size;
+
+ func(ctx, buffer->buffer + read_ptr, len);
+
+ return mp_ring_drain(buffer, read_len);
+}
+
+int mp_ring_write(struct mp_ring *buffer, unsigned char *src, int len)
+{
+ int size = mp_ring_size(buffer);
+ int free = mp_ring_available(buffer);
+ int write_len = FFMIN(len, free);
+ int write_ptr = mp_ring_get_wpos(buffer) % size;
+
+ int len1 = FFMIN(size - write_ptr, write_len);
+ int len2 = write_len - len1;
+
+ memcpy(buffer->buffer + write_ptr, src, len1);
+ memcpy(buffer->buffer, src + len1, len2);
+
+ mp_atomic_add_and_fetch(&buffer->wpos, write_len);
+ mp_memory_barrier();
+
+ return write_len;
+}
+
+void mp_ring_reset(struct mp_ring *buffer)
+{
+ buffer->wpos = buffer->rpos = 0;
+ mp_memory_barrier();
+}
+
+int mp_ring_available(struct mp_ring *buffer)
+{
+ return mp_ring_size(buffer) - mp_ring_buffered(buffer);
+}
+
+int mp_ring_size(struct mp_ring *buffer)
+{
+ return talloc_get_size(buffer->buffer);
+}
+
+int mp_ring_buffered(struct mp_ring *buffer)
+{
+ return (mp_ring_get_wpos(buffer) - mp_ring_get_rpos(buffer));
+}
+
+char *mp_ring_repr(struct mp_ring *buffer, void *talloc_ctx)
+{
+ return talloc_asprintf(
+ talloc_ctx,
+ "Ringbuffer { .size = %dB, .buffered = %dB, .available = %dB }",
+ mp_ring_size(buffer),
+ mp_ring_buffered(buffer),
+ mp_ring_available(buffer));
+}
diff --git a/core/mp_ring.h b/core/mp_ring.h
new file mode 100644
index 0000000000..52e885287d
--- /dev/null
+++ b/core/mp_ring.h
@@ -0,0 +1,125 @@
+/*
+ * This file is part of mpv.
+ * Copyright (c) 2012 wm4
+ * Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
+ *
+ * mpv is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MPV_MP_RING_H
+#define MPV_MP_RING_H
+
+/**
+ * A simple non-blocking SPSC (single producer, single consumer) ringbuffer
+ * implementation. Thread safety is accomplished through atomic operations.
+ */
+
+struct mp_ring;
+
+/**
+ * Instantiate a new ringbuffer
+ *
+ * talloc_ctx: talloc context of the newly created object
+ * size: total size in bytes
+ * return: the newly created ringbuffer
+ */
+struct mp_ring *mp_ring_new(void *talloc_ctx, int size);
+
+/**
+ * Read data from the ringbuffer
+ *
+ * buffer: target ringbuffer instance
+ * dest: destination buffer for the read data. If NULL read data is discarded.
+ * len: maximum number of bytes to read
+ * return: number of bytes read
+ */
+int mp_ring_read(struct mp_ring *buffer, unsigned char *dest, int len);
+
+/**
+ * Read data from the ringbuffer
+ *
+ * This function behaves similarly to `av_fifo_generic_read` and was actually
+ * added for compatibility with code that was written for it.
+ * This function will drain the returned amount of bytes from the ringbuffer
+ * so you don't have to handle that in inside `func`.
+ *
+ * buffer: target ringbuffer instance
+ * ctx: context for the callback function
+ * len: maximum number of bytes to read
+ * func: callback function to customize reading behaviour
+ * return: number of bytes read
+ */
+int mp_ring_read_cb(struct mp_ring *buffer, void *ctx, int len,
+ void (*func)(void*, void*, int));
+
+/**
+ * Write data to the ringbuffer
+ *
+ * buffer: target ringbuffer instance
+ * src: source buffer for the write data
+ * len: maximum number of bytes to write
+ * return: number of bytes written
+ */
+int mp_ring_write(struct mp_ring *buffer, unsigned char *src, int len);
+
+/**
+ * Drain data from the ringbuffer
+ *
+ * buffer: target ringbuffer instance
+ * len: maximum number of bytes to drain
+ * return: number of bytes drained
+ */
+int mp_ring_drain(struct mp_ring *buffer, int len);
+
+/**
+ * Reset the ringbuffer discarding any content
+ *
+ * buffer: target ringbuffer instance
+ */
+void mp_ring_reset(struct mp_ring *buffer);
+
+/**
+ * Get the available size for writing
+ *
+ * buffer: target ringbuffer instance
+ * return: number of bytes that can be written
+ */
+int mp_ring_available(struct mp_ring *buffer);
+
+/**
+ * Get the total size
+ *
+ * buffer: target ringbuffer instance
+ * return: total ringbuffer size
+ */
+int mp_ring_size(struct mp_ring *buffer);
+
+/**
+ * Get the available size for reading
+ *
+ * buffer: target ringbuffer instance
+ * return: number of bytes ready for reading
+ */
+int mp_ring_buffered(struct mp_ring *buffer);
+
+/**
+ * Get a string representation of the ringbuffer
+ *
+ * buffer: target ringbuffer instance
+ * talloc_ctx: talloc context of the newly created string
+ * return: string representing the ringbuffer
+ */
+char *mp_ring_repr(struct mp_ring *buffer, void *talloc_ctx);
+
+#endif