gst-libs/gst/audio/TODO: Updated TODO

Original commit message from CVS:
* gst-libs/gst/audio/TODO:
Updated TODO

* gst-libs/gst/audio/gstaudiosink.c:
(gst_audioringbuffer_open_device),
(gst_audioringbuffer_close_device), (gst_audioringbuffer_acquire),
(gst_audioringbuffer_release):
Small cleanups.

* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_class_init), (gst_base_audio_sink_render),
(gst_base_audio_sink_change_state):
Slave to the master clock when going to PLAYING and unslave when
going to PAUSED.

* gst-libs/gst/audio/gstringbuffer.c:
(gst_ring_buffer_open_device), (gst_ring_buffer_close_device),
(gst_ring_buffer_acquire), (gst_ring_buffer_release),
(gst_ring_buffer_samples_done), (gst_ring_buffer_set_sample),
(gst_ring_buffer_clear_all), (wait_segment),
(gst_ring_buffer_commit), (gst_ring_buffer_read),
(gst_ring_buffer_advance):
* gst-libs/gst/audio/gstringbuffer.h:
Add some docs and cleanups.
This commit is contained in:
Wim Taymans 2005-11-28 15:53:55 +00:00
parent 0767718887
commit 3f05db1828
6 changed files with 283 additions and 116 deletions

View file

@ -1,3 +1,30 @@
2005-11-28 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/audio/TODO:
Updated TODO
* gst-libs/gst/audio/gstaudiosink.c:
(gst_audioringbuffer_open_device),
(gst_audioringbuffer_close_device), (gst_audioringbuffer_acquire),
(gst_audioringbuffer_release):
Small cleanups.
* gst-libs/gst/audio/gstbaseaudiosink.c:
(gst_base_audio_sink_class_init), (gst_base_audio_sink_render),
(gst_base_audio_sink_change_state):
Slave to the master clock when going to PLAYING and unslave when
going to PAUSED.
* gst-libs/gst/audio/gstringbuffer.c:
(gst_ring_buffer_open_device), (gst_ring_buffer_close_device),
(gst_ring_buffer_acquire), (gst_ring_buffer_release),
(gst_ring_buffer_samples_done), (gst_ring_buffer_set_sample),
(gst_ring_buffer_clear_all), (wait_segment),
(gst_ring_buffer_commit), (gst_ring_buffer_read),
(gst_ring_buffer_advance):
* gst-libs/gst/audio/gstringbuffer.h:
Add some docs and cleanups.
2005-11-28 Julien MOUTTE <julien@moutte.net> 2005-11-28 Julien MOUTTE <julien@moutte.net>
* sys/xvimage/xvimagesink.c: * sys/xvimage/xvimagesink.c:

View file

@ -8,3 +8,8 @@ TODO
- implement seek/query/convert - implement seek/query/convert
- implement getrange scheduling - implement getrange scheduling
- on EOS, only post EOS when the complete ringbuffer has been played. - on EOS, only post EOS when the complete ringbuffer has been played.
- more accurate clipping of samples outside of the segment
- simple resampling
- more accurate master/slave calibration handling
- faster audio cutoff when going to PAUSED
- resubmit samples from ringbuffer when doing PAUSED->PLAYING again

View file

@ -264,6 +264,7 @@ gst_audioringbuffer_open_device (GstRingBuffer * buf)
could_not_open: could_not_open:
{ {
GST_DEBUG ("could not open device");
return FALSE; return FALSE;
} }
} }
@ -282,12 +283,13 @@ gst_audioringbuffer_close_device (GstRingBuffer * buf)
result = csink->close (sink); result = csink->close (sink);
if (!result) if (!result)
goto could_not_open; goto could_not_close;
return result; return result;
could_not_open: could_not_close:
{ {
GST_DEBUG ("could not close device");
return FALSE; return FALSE;
} }
} }
@ -307,7 +309,7 @@ gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
result = csink->prepare (sink, spec); result = csink->prepare (sink, spec);
if (!result) if (!result)
goto could_not_open; goto could_not_prepare;
/* allocate one more segment as we need some headroom */ /* allocate one more segment as we need some headroom */
spec->segtotal++; spec->segtotal++;
@ -325,8 +327,9 @@ gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
return result; return result;
could_not_open: could_not_prepare:
{ {
GST_DEBUG ("could not prepare device");
return FALSE; return FALSE;
} }
} }
@ -360,7 +363,16 @@ gst_audioringbuffer_release (GstRingBuffer * buf)
if (csink->unprepare) if (csink->unprepare)
result = csink->unprepare (sink); result = csink->unprepare (sink);
if (!result)
goto could_not_unprepare;
return result; return result;
could_not_unprepare:
{
GST_DEBUG ("could not unprepare device");
return FALSE;
}
} }
static gboolean static gboolean

View file

@ -68,8 +68,6 @@ static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement *
element, GstStateChange transition); element, GstStateChange transition);
static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem); static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem);
static gboolean gst_base_audio_sink_set_clock (GstElement * elem,
GstClock * clock);
static GstClockTime gst_base_audio_sink_get_time (GstClock * clock, static GstClockTime gst_base_audio_sink_get_time (GstClock * clock,
GstBaseAudioSink * sink); GstBaseAudioSink * sink);
static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data,
@ -127,8 +125,6 @@ gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state); GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
gstelement_class->provide_clock = gstelement_class->provide_clock =
GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock); GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
gstelement_class->set_clock =
GST_DEBUG_FUNCPTR (gst_base_audio_sink_set_clock);
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event); gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event);
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll); gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll);
@ -184,25 +180,6 @@ gst_base_audio_sink_provide_clock (GstElement * elem)
return clock; return clock;
} }
static gboolean
gst_base_audio_sink_set_clock (GstElement * elem, GstClock * clock)
{
GstBaseAudioSink *sink;
gboolean ret;
sink = GST_BASE_AUDIO_SINK (elem);
GST_OBJECT_LOCK (sink);
if (clock != sink->provided_clock) {
ret = gst_clock_set_master (sink->provided_clock, clock);
} else {
ret = gst_clock_set_master (sink->provided_clock, NULL);
}
GST_OBJECT_UNLOCK (sink);
return ret;
}
static GstClockTime static GstClockTime
gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink) gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
{ {
@ -593,10 +570,13 @@ gst_base_audio_sink_change_state (GstElement * element,
break; break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING: case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
{ {
GstClock *clock;
GST_OBJECT_LOCK (sink);
clock = GST_ELEMENT_CLOCK (sink);
/* if we are slaved to a clock, we need to set the initial /* if we are slaved to a clock, we need to set the initial
* calibration */ * calibration */
/* FIXME, this is not yet accurate enough for smooth playback */ if (clock != sink->provided_clock) {
if (gst_clock_get_master (sink->provided_clock)) {
GstClockTime time; GstClockTime time;
GstClockTime rate_num, rate_denom; GstClockTime rate_num, rate_denom;
@ -605,12 +585,15 @@ gst_base_audio_sink_change_state (GstElement * element,
GST_DEBUG_OBJECT (sink, "time: %" GST_TIME_FORMAT, GST_DEBUG_OBJECT (sink, "time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (time)); GST_TIME_ARGS (time));
gst_clock_set_master (sink->provided_clock, clock);
/* FIXME, this is not yet accurate enough for smooth playback */
gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num, gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
&rate_denom); &rate_denom);
/* Does not work yet. */ /* Does not work yet. */
gst_clock_set_calibration (sink->provided_clock, gst_clock_set_calibration (sink->provided_clock,
time, element->base_time, rate_num, rate_denom); time, element->base_time, rate_num, rate_denom);
} }
GST_OBJECT_UNLOCK (sink);
break; break;
} }
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
@ -625,6 +608,8 @@ gst_base_audio_sink_change_state (GstElement * element,
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
gst_ring_buffer_pause (sink->ringbuffer); gst_ring_buffer_pause (sink->ringbuffer);
/* slop slaving ourselves to the master, if any */
gst_clock_set_master (sink->provided_clock, NULL);
break; break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_ring_buffer_release (sink->ringbuffer); gst_ring_buffer_release (sink->ringbuffer);

View file

@ -18,6 +18,15 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
/**
* SECTION:gstringbuffer
* @short_description: Base class for audio ringbuffer implementations
*
* This object is the base class for audio ringbuffers used by the base
* audio source and sink classes.
*
* Last reviewed on 2005-11-24 (0.9.6)
*/
#include <string.h> #include <string.h>
@ -183,6 +192,12 @@ build_linear_format (int depth, int width, int unsignd, int big_endian)
return ((int (*)[2][2]) linear_formats)[depth][!!unsignd][!!big_endian]; return ((int (*)[2][2]) linear_formats)[depth][!!unsignd][!!big_endian];
} }
/**
* gst_ring_buffer_debug_spec_caps:
* @spec: the spec to debug
*
* Print debug info about the parsed caps in @spec to the debug log.
*/
void void
gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec) gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
{ {
@ -198,6 +213,12 @@ gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec)
GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample); GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample);
} }
/**
* gst_ring_buffer_debug_spec_buff:
* @spec: the spec to debug
*
* Print debug info about the buffer sized in @spec to the debug log.
*/
void void
gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec) gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
{ {
@ -213,6 +234,15 @@ gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec)
spec->segsize * spec->segtotal / spec->bytes_per_sample); spec->segsize * spec->segtotal / spec->bytes_per_sample);
} }
/**
* gst_ring_buffer_parse_caps:
* @spec: a spec
* @caps: a #GstCaps
*
* Parse @caps into @spec.
*
* Returns: TRUE if the caps could be parsed.
*/
gboolean gboolean
gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps) gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps)
{ {
@ -355,11 +385,9 @@ gst_ring_buffer_open_device (GstRingBuffer * buf)
GST_DEBUG_OBJECT (buf, "opening device"); GST_DEBUG_OBJECT (buf, "opening device");
GST_OBJECT_LOCK (buf); GST_OBJECT_LOCK (buf);
if (buf->open) { if (buf->open)
g_warning ("Device for ring buffer %p already open, fix your code", buf); goto was_opened;
res = TRUE;
goto done;
}
buf->open = TRUE; buf->open = TRUE;
/* if this fails, something is wrong in this file */ /* if this fails, something is wrong in this file */
@ -369,17 +397,30 @@ gst_ring_buffer_open_device (GstRingBuffer * buf)
if (rclass->open_device) if (rclass->open_device)
res = rclass->open_device (buf); res = rclass->open_device (buf);
if (!res) { if (!res)
buf->open = FALSE; goto open_failed;
GST_DEBUG_OBJECT (buf, "failed opening device");
} else { GST_DEBUG_OBJECT (buf, "opened device");
GST_DEBUG_OBJECT (buf, "opened device");
}
done: done:
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
return res; return res;
/* ERRORS */
was_opened:
{
GST_DEBUG_OBJECT (buf, "Device for ring buffer already open");
g_warning ("Device for ring buffer %p already open, fix your code", buf);
res = TRUE;
goto done;
}
open_failed:
{
buf->open = FALSE;
GST_DEBUG_OBJECT (buf, "failed opening device");
goto done;
}
} }
/** /**
@ -404,17 +445,11 @@ gst_ring_buffer_close_device (GstRingBuffer * buf)
GST_DEBUG_OBJECT (buf, "closing device"); GST_DEBUG_OBJECT (buf, "closing device");
GST_OBJECT_LOCK (buf); GST_OBJECT_LOCK (buf);
if (!buf->open) { if (!buf->open)
g_warning ("Device for ring buffer %p already closed, fix your code", buf); goto was_closed;
res = TRUE;
goto done;
}
if (buf->acquired) { if (buf->acquired)
g_critical ("Resources for ring buffer %p still acquired", buf); goto was_acquired;
res = FALSE;
goto done;
}
buf->open = FALSE; buf->open = FALSE;
@ -422,17 +457,37 @@ gst_ring_buffer_close_device (GstRingBuffer * buf)
if (rclass->close_device) if (rclass->close_device)
res = rclass->close_device (buf); res = rclass->close_device (buf);
if (!res) { if (!res)
buf->open = TRUE; goto close_error;
GST_DEBUG_OBJECT (buf, "error closing device");
} else { GST_DEBUG_OBJECT (buf, "closed device");
GST_DEBUG_OBJECT (buf, "closed device");
}
done: done:
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
return res; return res;
/* ERRORS */
was_closed:
{
GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed");
g_warning ("Device for ring buffer %p already closed, fix your code", buf);
res = TRUE;
goto done;
}
was_acquired:
{
GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired");
g_critical ("Resources for ring buffer %p still acquired", buf);
res = FALSE;
goto done;
}
close_error:
{
buf->open = TRUE;
GST_DEBUG_OBJECT (buf, "error closing device");
goto done;
}
} }
/** /**
@ -480,56 +535,78 @@ gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec)
{ {
gboolean res = FALSE; gboolean res = FALSE;
GstRingBufferClass *rclass; GstRingBufferClass *rclass;
gint i, j;
gint segsize, bps;
g_return_val_if_fail (buf != NULL, FALSE); g_return_val_if_fail (buf != NULL, FALSE);
GST_DEBUG_OBJECT (buf, "acquiring device"); GST_DEBUG_OBJECT (buf, "acquiring device");
GST_OBJECT_LOCK (buf); GST_OBJECT_LOCK (buf);
if (!buf->open) { if (!buf->open)
g_critical ("Device for %p not opened", buf); goto not_opened;
res = FALSE;
goto done; if (buf->acquired)
} goto was_acquired;
if (buf->acquired) {
res = TRUE;
GST_DEBUG_OBJECT (buf, "device was acquired");
goto done;
}
buf->acquired = TRUE; buf->acquired = TRUE;
rclass = GST_RING_BUFFER_GET_CLASS (buf); rclass = GST_RING_BUFFER_GET_CLASS (buf);
if (rclass->acquire) if (rclass->acquire)
res = rclass->acquire (buf, spec); res = rclass->acquire (buf, spec);
if (!res) { if (!res)
buf->acquired = FALSE; goto acquire_failed;
GST_DEBUG_OBJECT (buf, "failed to acquire device");
} else {
if (buf->spec.bytes_per_sample != 0) {
gint i, j;
buf->samples_per_seg = buf->spec.segsize / buf->spec.bytes_per_sample; if ((bps = buf->spec.bytes_per_sample) == 0)
goto invalid_bps;
/* create an empty segment */ segsize = buf->spec.segsize;
g_free (buf->empty_seg);
buf->empty_seg = g_malloc (buf->spec.segsize); buf->samples_per_seg = segsize / bps;
for (i = 0, j = 0; i < buf->spec.segsize; i++) {
buf->empty_seg[i] = buf->spec.silence_sample[j]; /* create an empty segment */
j = (j + 1) % buf->spec.bytes_per_sample; g_free (buf->empty_seg);
} buf->empty_seg = g_malloc (segsize);
GST_DEBUG_OBJECT (buf, "acquired device"); for (i = 0, j = 0; i < segsize; i++) {
} else { buf->empty_seg[i] = buf->spec.silence_sample[j];
g_warning j = (j + 1) % bps;
("invalid bytes_per_sample from acquire ringbuffer, fix the element");
buf->acquired = FALSE;
res = FALSE;
}
} }
GST_DEBUG_OBJECT (buf, "acquired device");
done: done:
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
return res; return res;
/* ERRORS */
not_opened:
{
GST_DEBUG_OBJECT (buf, "device not opened");
g_critical ("Device for %p not opened", buf);
res = FALSE;
goto done;
}
was_acquired:
{
res = TRUE;
GST_DEBUG_OBJECT (buf, "device was acquired");
goto done;
}
acquire_failed:
{
buf->acquired = FALSE;
GST_DEBUG_OBJECT (buf, "failed to acquire device");
goto done;
}
invalid_bps:
{
g_warning
("invalid bytes_per_sample from acquire ringbuffer, fix the element");
buf->acquired = FALSE;
res = FALSE;
goto done;
}
} }
/** /**
@ -555,11 +632,9 @@ gst_ring_buffer_release (GstRingBuffer * buf)
gst_ring_buffer_stop (buf); gst_ring_buffer_stop (buf);
GST_OBJECT_LOCK (buf); GST_OBJECT_LOCK (buf);
if (!buf->acquired) { if (!buf->acquired)
res = TRUE; goto was_released;
GST_DEBUG_OBJECT (buf, "device was released");
goto done;
}
buf->acquired = FALSE; buf->acquired = FALSE;
/* if this fails, something is wrong in this file */ /* if this fails, something is wrong in this file */
@ -572,19 +647,31 @@ gst_ring_buffer_release (GstRingBuffer * buf)
/* signal any waiters */ /* signal any waiters */
GST_RING_BUFFER_SIGNAL (buf); GST_RING_BUFFER_SIGNAL (buf);
if (!res) { if (!res)
buf->acquired = TRUE; goto release_failed;
GST_DEBUG_OBJECT (buf, "failed to release device");
} else { g_free (buf->empty_seg);
g_free (buf->empty_seg); buf->empty_seg = NULL;
buf->empty_seg = NULL; GST_DEBUG_OBJECT (buf, "released device");
GST_DEBUG_OBJECT (buf, "released device");
}
done: done:
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
return res; return res;
/* ERRORS */
was_released:
{
res = TRUE;
GST_DEBUG_OBJECT (buf, "device was released");
goto done;
}
release_failed:
{
buf->acquired = TRUE;
GST_DEBUG_OBJECT (buf, "failed to release device");
goto done;
}
} }
/** /**
@ -891,8 +978,8 @@ gst_ring_buffer_samples_done (GstRingBuffer * buf)
if (samples >= delay) if (samples >= delay)
samples -= delay; samples -= delay;
GST_DEBUG ("processed samples: raw %llu, delay %u, real %llu", raw, delay, GST_DEBUG_OBJECT (buf, "processed samples: raw %llu, delay %u, real %llu",
samples); raw, delay, samples);
return samples; return samples;
} }
@ -929,7 +1016,8 @@ gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample)
gst_ring_buffer_clear_all (buf); gst_ring_buffer_clear_all (buf);
GST_DEBUG ("set sample to %llu, segbase %d", sample, buf->segbase); GST_DEBUG_OBJECT (buf, "set sample to %llu, segbase %d", sample,
buf->segbase);
} }
/** /**
@ -951,7 +1039,7 @@ gst_ring_buffer_clear_all (GstRingBuffer * buf)
if (buf->spec.segtotal <= 0) if (buf->spec.segtotal <= 0)
return; return;
GST_DEBUG ("clear all segments"); GST_DEBUG_OBJECT (buf, "clear all segments");
for (i = 0; i < buf->spec.segtotal; i++) { for (i = 0; i < buf->spec.segtotal; i++) {
gst_ring_buffer_clear (buf, i); gst_ring_buffer_clear (buf, i);
@ -964,7 +1052,7 @@ wait_segment (GstRingBuffer * buf)
{ {
/* buffer must be started now or we deadlock since nobody is reading */ /* buffer must be started now or we deadlock since nobody is reading */
if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED) { if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED) {
GST_DEBUG ("start!"); GST_DEBUG_OBJECT (buf, "start!");
gst_ring_buffer_start (buf); gst_ring_buffer_start (buf);
} }
@ -974,7 +1062,7 @@ wait_segment (GstRingBuffer * buf)
goto flushing; goto flushing;
if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) { if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) {
GST_DEBUG ("waiting.."); GST_DEBUG_OBJECT (buf, "waiting..");
if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED) if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
goto not_started; goto not_started;
@ -993,13 +1081,13 @@ wait_segment (GstRingBuffer * buf)
not_started: not_started:
{ {
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
GST_DEBUG ("stopped processing"); GST_DEBUG_OBJECT (buf, "stopped processing");
return FALSE; return FALSE;
} }
flushing: flushing:
{ {
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
GST_DEBUG ("flushing"); GST_DEBUG_OBJECT (buf, "flushing");
return FALSE; return FALSE;
} }
} }
@ -1016,7 +1104,7 @@ flushing:
* the ringbuffer. * the ringbuffer.
* *
* @len not needs to be a multiple of the segment size of the ringbuffer * @len not needs to be a multiple of the segment size of the ringbuffer
* although it is recommended. * although it is recommended for optimal performance.
* *
* Returns: The number of samples written to the ringbuffer or -1 on * Returns: The number of samples written to the ringbuffer or -1 on
* error. * error.
@ -1086,7 +1174,7 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
writeseg = writeseg % segtotal; writeseg = writeseg % segtotal;
sampleslen = MIN (sps - sampleoff, len); sampleslen = MIN (sps - sampleoff, len);
GST_DEBUG ("write @%p seg %d, off %d, len %d", GST_DEBUG_OBJECT (buf, "write @%p seg %d, off %d, len %d",
dest + writeseg * segsize, writeseg, sampleoff, sampleslen); dest + writeseg * segsize, writeseg, sampleoff, sampleslen);
memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data, memcpy (dest + (writeseg * segsize) + (sampleoff * bps), data,
@ -1103,7 +1191,7 @@ gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data,
/* ERRORS */ /* ERRORS */
not_started: not_started:
{ {
GST_DEBUG ("stopped processing"); GST_DEBUG_OBJECT (buf, "stopped processing");
return -1; return -1;
} }
} }
@ -1198,7 +1286,7 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
readseg = readseg % segtotal; readseg = readseg % segtotal;
sampleslen = MIN (sps - sampleoff, len); sampleslen = MIN (sps - sampleoff, len);
GST_DEBUG ("read @%p seg %d, off %d, len %d", GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, len %d",
dest + readseg * segsize, readseg, sampleoff, sampleslen); dest + readseg * segsize, readseg, sampleoff, sampleslen);
memcpy (data, dest + (readseg * segsize) + (sampleoff * bps), memcpy (data, dest + (readseg * segsize) + (sampleoff * bps),
@ -1215,7 +1303,7 @@ gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data,
/* ERRORS */ /* ERRORS */
not_started: not_started:
{ {
GST_DEBUG ("stopped processing"); GST_DEBUG_OBJECT (buf, "stopped processing");
return -1; return -1;
} }
} }
@ -1293,7 +1381,7 @@ gst_ring_buffer_advance (GstRingBuffer * buf, guint advance)
* waiting for the signal */ * waiting for the signal */
if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) { if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) {
GST_OBJECT_LOCK (buf); GST_OBJECT_LOCK (buf);
GST_DEBUG ("signal waiter"); GST_DEBUG_OBJECT (buf, "signal waiter");
GST_RING_BUFFER_SIGNAL (buf); GST_RING_BUFFER_SIGNAL (buf);
GST_OBJECT_UNLOCK (buf); GST_OBJECT_UNLOCK (buf);
} }

View file

@ -41,12 +41,29 @@ typedef struct _GstRingBufferSpec GstRingBufferSpec;
/* called to fill data with len bytes of samples */ /* called to fill data with len bytes of samples */
typedef void (*GstRingBufferCallback) (GstRingBuffer *rbuf, guint8* data, guint len, gpointer user_data); typedef void (*GstRingBufferCallback) (GstRingBuffer *rbuf, guint8* data, guint len, gpointer user_data);
/**
* GstRingBufferState:
* @GST_RING_BUFFER_STATE_STOPPED: The ringbuffer is stopped
* @GST_RING_BUFFER_STATE_PAUSED: The ringbuffer is paused
* @GST_RING_BUFFER_STATE_STARTED: The ringbuffer is started
*
* The state of the ringbuffer.
*/
typedef enum { typedef enum {
GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STOPPED,
GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_PAUSED,
GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STARTED,
} GstRingBufferState; } GstRingBufferState;
/**
* GstRingBufferSegState:
* @GST_SEGSTATE_INVALID: The content of the segment is invalid
* @GST_SEGSTATE_EMPTY: The segment is empty
* @GST_SEGSTATE_FILLED: The segment contains valid data
* @GST_SEGSTATE_PARTIAL: The segment partially contains valid data
*
* The state of a segment in the ringbuffer.
*/
typedef enum { typedef enum {
GST_SEGSTATE_INVALID, GST_SEGSTATE_INVALID,
GST_SEGSTATE_EMPTY, GST_SEGSTATE_EMPTY,
@ -54,6 +71,18 @@ typedef enum {
GST_SEGSTATE_PARTIAL, GST_SEGSTATE_PARTIAL,
} GstRingBufferSegState; } GstRingBufferSegState;
/**
* GstBufferFormatType:
* @GST_BUFTYPE_LINEAR: samples in linear PCM
* @GST_BUFTYPE_FLOAT: samples in float
* @GST_BUFTYPE_MU_LAW: samples in mulaw
* @GST_BUFTYPE_A_LAW: samples in alaw
* @GST_BUFTYPE_IMA_ADPCM: samples in ima adpcm
* @GST_BUFTYPE_MPEG: samples in mpeg audio format
* @GST_BUFTYPE_GSM: samples in gsm format
*
* The format of the samples in the ringbuffer.
*/
typedef enum typedef enum
{ {
GST_BUFTYPE_LINEAR, GST_BUFTYPE_LINEAR,
@ -116,8 +145,29 @@ typedef enum
} GstBufferFormat; } GstBufferFormat;
/**
* GstRingBufferSpec:
* @caps: The caps that generated the Spec.
* @type: the sample type
* @format: the sample format
* @sign: the sample sign
* @bigend: the endianness of the samples
* @width: the width of the samples
* @depth: th depth of the samples
* @rate: the samplerate
* @channels: the number of channels
* @latency_time: the latency in time units
* @buffer_time: the total buffer size in time units
* @segsize: the size of one segment in bytes
* @segtotal: the total number of segments
* @bytes_per_sample: number of bytes in one sample
* @silence_sample: bytes representing one sample of silence
*
* The structure containing the format specification of the ringbuffer.
*/
struct _GstRingBufferSpec struct _GstRingBufferSpec
{ {
/*< public >*/
/* in */ /* in */
GstCaps *caps; /* the caps of the buffer */ GstCaps *caps; /* the caps of the buffer */
@ -215,8 +265,8 @@ void gst_ring_buffer_set_callback (GstRingBuffer *buf, GstRingBufferCall
gpointer user_data); gpointer user_data);
gboolean gst_ring_buffer_parse_caps (GstRingBufferSpec *spec, GstCaps *caps); gboolean gst_ring_buffer_parse_caps (GstRingBufferSpec *spec, GstCaps *caps);
void gst_ring_buffer_debug_spec_caps (GstRingBufferSpec *spec); void gst_ring_buffer_debug_spec_caps (GstRingBufferSpec *spec);
void gst_ring_buffer_debug_spec_buff (GstRingBufferSpec *spec); void gst_ring_buffer_debug_spec_buff (GstRingBufferSpec *spec);
/* device state */ /* device state */
gboolean gst_ring_buffer_open_device (GstRingBuffer *buf); gboolean gst_ring_buffer_open_device (GstRingBuffer *buf);