From a6b78893c0b1af1a0b3ab61806e64f932d47595c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 17 Oct 2008 13:19:05 +0000 Subject: [PATCH] Add methods to more accuratly control the pulling thread of a ringbuffer. Original commit message from CVS: * docs/libs/gst-plugins-base-libs-sections.txt: * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_convert), (gst_ring_buffer_activate), (gst_ring_buffer_is_active): * gst-libs/gst/audio/gstringbuffer.h: Add methods to more accuratly control the pulling thread of a ringbuffer. Add format conversion helper code to the ringbuffer. API: GstRingBuffer:gst_ring_buffer_activate() API: GstRingBuffer:gst_ring_buffer_is_active() API: GstRingBuffer:gst_ring_buffer_convert() --- ChangeLog | 13 ++ docs/libs/gst-plugins-base-libs-sections.txt | 4 + gst-libs/gst/audio/gstringbuffer.c | 193 ++++++++++++++++++++++++++- gst-libs/gst/audio/gstringbuffer.h | 15 ++- 4 files changed, 223 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 14a2e81..6a506d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-10-17 Wim Taymans + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_convert), + (gst_ring_buffer_activate), (gst_ring_buffer_is_active): + * gst-libs/gst/audio/gstringbuffer.h: + Add methods to more accuratly control the pulling thread of a + ringbuffer. + Add format conversion helper code to the ringbuffer. + API: GstRingBuffer:gst_ring_buffer_activate() + API: GstRingBuffer:gst_ring_buffer_is_active() + API: GstRingBuffer:gst_ring_buffer_convert() + 2008-10-16 Wim Taymans * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func), diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index 3a0dc9b..4a08e9f 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -172,6 +172,9 @@ gst_ring_buffer_acquire gst_ring_buffer_release gst_ring_buffer_is_acquired +gst_ring_buffer_activate +gst_ring_buffer_is_active + gst_ring_buffer_start gst_ring_buffer_pause gst_ring_buffer_stop @@ -181,6 +184,7 @@ gst_ring_buffer_samples_done gst_ring_buffer_set_sample gst_ring_buffer_commit gst_ring_buffer_commit_full +gst_ring_buffer_convert gst_ring_buffer_prepare_read gst_ring_buffer_read diff --git a/gst-libs/gst/audio/gstringbuffer.c b/gst-libs/gst/audio/gstringbuffer.c index 7312436..e9023c8 100644 --- a/gst-libs/gst/audio/gstringbuffer.c +++ b/gst-libs/gst/audio/gstringbuffer.c @@ -433,6 +433,101 @@ parse_error: } /** + * gst_ring_buffer_convert: + * @buf: the #GstRingBuffer + * @src_fmt: the source format + * @src_val: the source value + * @dest_fmt: the destination format + * @dest_val: a location to store the converted value + * + * Convert @src_val in @src_fmt to the equivalent value in @dest_fmt. The result + * will be put in @dest_val. + * + * Returns: TRUE if the conversion succeeded. + * + * Since: 0.10.22. + */ +gboolean +gst_ring_buffer_convert (GstRingBuffer * buf, + GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val) +{ + gboolean res = TRUE; + gint bps, rate; + + GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)", + src_val, gst_format_get_name (src_fmt), src_fmt, + gst_format_get_name (dest_fmt), dest_fmt); + + if (src_fmt == dest_fmt || src_val == -1) { + *dest_val = src_val; + goto done; + } + + /* get important info */ + GST_OBJECT_LOCK (buf); + bps = buf->spec.bytes_per_sample; + rate = buf->spec.rate; + GST_OBJECT_UNLOCK (buf); + + if (bps == 0 || rate == 0) { + GST_DEBUG ("no rate or bps configured"); + res = FALSE; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_BYTES: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = gst_util_uint64_scale_int (src_val / bps, GST_SECOND, + rate); + break; + case GST_FORMAT_DEFAULT: + *dest_val = src_val / bps; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate); + break; + case GST_FORMAT_BYTES: + *dest_val = src_val * bps; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND); + break; + case GST_FORMAT_BYTES: + *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND); + *dest_val *= bps; + break; + default: + res = FALSE; + break; + } + break; + default: + res = FALSE; + break; + } +done: + GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val); + + return res; +} + +/** * gst_ring_buffer_set_callback: * @buf: the #GstRingBuffer to set the callback on * @cb: the callback to set @@ -608,7 +703,6 @@ gst_ring_buffer_device_is_open (GstRingBuffer * buf) return res; } - /** * gst_ring_buffer_acquire: * @buf: the #GstRingBuffer to acquire @@ -801,6 +895,103 @@ gst_ring_buffer_is_acquired (GstRingBuffer * buf) } /** + * gst_ring_buffer_activate: + * @buf: the #GstRingBuffer to activate + * @active: the new mode + * + * Activate @buf to start or stop pulling data. + * + * Returns: TRUE if the device could be activated in the requested mode, + * FALSE on error. + * + * Since: 0.10.22. + * + * MT safe. + */ +gboolean +gst_ring_buffer_activate (GstRingBuffer * buf, gboolean active) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "activate device"); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (active && !buf->acquired)) + goto not_acquired; + + if (G_UNLIKELY (buf->abidata.ABI.active == active)) + goto was_active; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + /* if there is no activate function we assume it was started/released + * in the acquire method */ + if (G_LIKELY (rclass->activate)) + res = rclass->activate (buf, active); + else + res = TRUE; + + if (G_UNLIKELY (!res)) + goto activate_failed; + + buf->abidata.ABI.active = active; + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +not_acquired: + { + GST_DEBUG_OBJECT (buf, "device not acquired"); + g_critical ("Device for %p not acquired", buf); + res = FALSE; + goto done; + } +was_active: + { + res = TRUE; + GST_DEBUG_OBJECT (buf, "device was active in mode %d", active); + goto done; + } +activate_failed: + { + GST_DEBUG_OBJECT (buf, "failed to activate device"); + goto done; + } +} + +/** + * gst_ring_buffer_is_active: + * @buf: the #GstRingBuffer + * + * Check if @buf is activated. + * + * Returns: TRUE if the device is active. + * + * Since: 0.10.22. + * + * MT safe. + */ +gboolean +gst_ring_buffer_is_active (GstRingBuffer * buf) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_OBJECT_LOCK (buf); + res = buf->abidata.ABI.active; + GST_OBJECT_UNLOCK (buf); + + return res; +} + + +/** * gst_ring_buffer_set_flushing: * @buf: the #GstRingBuffer to flush * @flushing: the new mode diff --git a/gst-libs/gst/audio/gstringbuffer.h b/gst-libs/gst/audio/gstringbuffer.h index 8d2a40f..be0b27c 100644 --- a/gst-libs/gst/audio/gstringbuffer.h +++ b/gst-libs/gst/audio/gstringbuffer.h @@ -279,6 +279,7 @@ struct _GstRingBuffer { gboolean flushing; /* ATOMIC */ gint may_start; + gboolean active; } ABI; /* adding + 0 to mark ABI change to be undone later */ gpointer _gst_reserved[GST_PADDING + 0]; @@ -297,6 +298,7 @@ struct _GstRingBuffer { * @resume: resume processing of samples after pause * @stop: stop processing of samples * @delay: get number of samples queued in device + * @activate: activate the thread that starts pulling. Since 0.10.22 * * The vmethods that subclasses can override to implement the ringbuffer. */ @@ -316,8 +318,11 @@ struct _GstRingBufferClass { guint (*delay) (GstRingBuffer *buf); + /* ABI added */ + gboolean (*activate) (GstRingBuffer *buf, gboolean active); + /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gpointer _gst_reserved[GST_PADDING - 1]; }; GType gst_ring_buffer_get_type(void); @@ -330,6 +335,10 @@ gboolean gst_ring_buffer_parse_caps (GstRingBufferSpec *spec, GstCap void gst_ring_buffer_debug_spec_caps (GstRingBufferSpec *spec); void gst_ring_buffer_debug_spec_buff (GstRingBufferSpec *spec); +gboolean gst_ring_buffer_convert (GstRingBuffer * buf, GstFormat src_fmt, + gint64 src_val, GstFormat dest_fmt, + gint64 * dest_val); + /* device state */ gboolean gst_ring_buffer_open_device (GstRingBuffer *buf); gboolean gst_ring_buffer_close_device (GstRingBuffer *buf); @@ -342,6 +351,10 @@ gboolean gst_ring_buffer_release (GstRingBuffer *buf); gboolean gst_ring_buffer_is_acquired (GstRingBuffer *buf); +/* activating */ +gboolean gst_ring_buffer_activate (GstRingBuffer *buf, gboolean active); +gboolean gst_ring_buffer_is_active (GstRingBuffer *buf); + /* flushing */ void gst_ring_buffer_set_flushing (GstRingBuffer *buf, gboolean flushing); -- 2.7.4