[aravis] stream: implement new-buffer signal.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aravis] stream: implement new-buffer signal.
- Date: Wed, 24 Nov 2010 15:14:16 +0000 (UTC)
commit 5a9c22fb142d9162fde3bb40ad20424c467b2cd0
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Wed Nov 24 16:13:26 2010 +0100
stream: implement new-buffer signal.
And also base arv-camera-test on a glib mainloop, using this new signal.
docs/reference/aravis/aravis-sections.txt | 5 +
src/arvfakestream.c | 10 +-
src/arvgvstream.c | 13 +-
src/arvstream.c | 175 +++++++++++++++++++++++++++--
src/arvstream.h | 30 +++--
tests/arvcameratest.c | 83 ++++++++++----
6 files changed, 256 insertions(+), 60 deletions(-)
---
diff --git a/docs/reference/aravis/aravis-sections.txt b/docs/reference/aravis/aravis-sections.txt
index ff7d3f7..357eebd 100644
--- a/docs/reference/aravis/aravis-sections.txt
+++ b/docs/reference/aravis/aravis-sections.txt
@@ -272,6 +272,8 @@ arv_stream_push_buffer
arv_stream_pop_buffer
arv_stream_get_n_buffers
arv_stream_get_statistics
+arv_stream_get_emit_signals
+arv_stream_set_emit_signals
<SUBSECTION Standard>
ARV_STREAM
ARV_IS_STREAM
@@ -281,6 +283,9 @@ ARV_STREAM_CLASS
ARV_IS_STREAM_CLASS
ARV_STREAM_GET_CLASS
<SUBSECTION Private>
+ArvStreamPrivate
+arv_stream_pop_input_buffer
+arv_stream_push_output_buffer
ArvStreamClass
</SECTION>
diff --git a/src/arvfakestream.c b/src/arvfakestream.c
index 067d55d..ed9f32a 100644
--- a/src/arvfakestream.c
+++ b/src/arvfakestream.c
@@ -42,13 +42,12 @@ struct _ArvFakeStreamPrivate {
typedef struct {
ArvFakeCamera *camera;
+ ArvStream *stream;
ArvStreamCallback callback;
void *user_data;
gboolean cancel;
- GAsyncQueue *input_queue;
- GAsyncQueue *output_queue;
/* Statistics */
@@ -70,7 +69,7 @@ arv_fake_stream_thread (void *data)
while (!thread_data->cancel) {
arv_fake_camera_wait_for_next_frame (thread_data->camera);
- buffer = g_async_queue_try_pop (thread_data->input_queue);
+ buffer = arv_stream_pop_input_buffer (thread_data->stream);
if (buffer != NULL) {
arv_fake_camera_fill_buffer (thread_data->camera, buffer);
if (buffer->status == ARV_BUFFER_STATUS_SUCCESS)
@@ -80,7 +79,7 @@ arv_fake_stream_thread (void *data)
if (thread_data->callback != NULL)
thread_data->callback (thread_data->user_data, ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE,
buffer);
- g_async_queue_push (thread_data->output_queue, buffer);
+ arv_stream_push_output_buffer (thread_data->stream, buffer);
} else
thread_data->n_underruns++;
}
@@ -111,12 +110,11 @@ arv_fake_stream_new (ArvFakeCamera *camera, ArvStreamCallback callback, void *us
stream = ARV_STREAM (fake_stream);
thread_data = g_new (ArvFakeStreamThreadData, 1);
+ thread_data->stream = stream;
thread_data->camera = camera;
thread_data->callback = callback;
thread_data->user_data = user_data;
thread_data->cancel = FALSE;
- thread_data->input_queue = stream->input_queue;
- thread_data->output_queue = stream->output_queue;
thread_data->n_completed_buffers = 0;
thread_data->n_failures = 0;
diff --git a/src/arvgvstream.c b/src/arvgvstream.c
index b1bc7f0..779aa9d 100644
--- a/src/arvgvstream.c
+++ b/src/arvgvstream.c
@@ -41,6 +41,8 @@ static GObjectClass *parent_class = NULL;
/* Acquisition thread */
typedef struct {
+ ArvStream *stream;
+
ArvStreamCallback callback;
void *user_data;
@@ -52,8 +54,6 @@ typedef struct {
guint64 timestamp_tick_frequency;
gboolean cancel;
- GAsyncQueue *input_queue;
- GAsyncQueue *output_queue;
guint32 packet_count;
@@ -194,7 +194,9 @@ _close_buffer (ArvGvStreamThreadData *thread_data, ArvGvStreamThreadState *state
state->last_time_us = current_time_us;
state->last_timestamp_ns = state->buffer->timestamp_ns;
- g_async_queue_push (thread_data->output_queue, state->buffer);
+
+ arv_stream_push_output_buffer (thread_data->stream, state->buffer);
+
state->buffer = NULL;
}
@@ -206,7 +208,7 @@ _process_data_leader (ArvGvStreamThreadData *thread_data, ArvGvStreamThreadState
if (state->buffer != NULL)
_close_buffer (thread_data, state);
- state->buffer = g_async_queue_try_pop (thread_data->input_queue);
+ state->buffer = arv_stream_pop_input_buffer (thread_data->stream);
if (state->buffer == NULL) {
thread_data->n_underruns++;
return;
@@ -457,6 +459,7 @@ arv_gv_stream_new (GInetAddress *device_address, guint16 port,
g_socket_bind (gv_stream->socket, gv_stream->incoming_address, TRUE, NULL);
thread_data = g_new (ArvGvStreamThreadData, 1);
+ thread_data->stream = stream;
thread_data->callback = callback;
thread_data->user_data = user_data;
thread_data->socket = gv_stream->socket;
@@ -464,8 +467,6 @@ arv_gv_stream_new (GInetAddress *device_address, guint16 port,
thread_data->packet_resend = ARV_GV_STREAM_PACKET_RESEND_ALWAYS;
thread_data->timestamp_tick_frequency = timestamp_tick_frequency;
thread_data->cancel = FALSE;
- thread_data->input_queue = stream->input_queue;
- thread_data->output_queue = stream->output_queue;
thread_data->packet_count = 1;
diff --git a/src/arvstream.c b/src/arvstream.c
index 1d42685..73fd2ff 100644
--- a/src/arvstream.c
+++ b/src/arvstream.c
@@ -34,8 +34,29 @@
#include <arvbuffer.h>
#include <arvdebug.h>
+enum {
+ ARV_STREAM_SIGNAL_NEW_BUFFER,
+ ARV_STREAM_SIGNAL_LAST
+} ArvStreamSignals;
+
+static guint arv_stream_signals[ARV_STREAM_SIGNAL_LAST] = {0};
+
+enum {
+ ARV_STREAM_PROPERTY_0,
+ ARV_STREAM_PROPERTY_EMIT_SIGNALS,
+ ARV_STREAM_PROPERTY_LAST
+} ArvStreamProperties;
+
static GObjectClass *parent_class = NULL;
+
+struct _ArvStreamPrivate {
+ GAsyncQueue *input_queue;
+ GAsyncQueue *output_queue;
+
+ gboolean emit_signals;
+};
+
/**
* arv_stream_push_buffer:
* @stream: a #ArvStream
@@ -51,7 +72,7 @@ arv_stream_push_buffer (ArvStream *stream, ArvBuffer *buffer)
g_return_if_fail (ARV_IS_STREAM (stream));
g_return_if_fail (ARV_IS_BUFFER (buffer));
- g_async_queue_push (stream->input_queue, buffer);
+ g_async_queue_push (stream->priv->input_queue, buffer);
}
/**
@@ -68,7 +89,27 @@ arv_stream_pop_buffer (ArvStream *stream)
{
g_return_val_if_fail (ARV_IS_STREAM (stream), NULL);
- return g_async_queue_try_pop (stream->output_queue);
+ return g_async_queue_try_pop (stream->priv->output_queue);
+}
+
+ArvBuffer *
+arv_stream_pop_input_buffer (ArvStream *stream)
+{
+ g_return_val_if_fail (ARV_IS_STREAM (stream), NULL);
+
+ return g_async_queue_try_pop (stream->priv->input_queue);
+}
+
+void
+arv_stream_push_output_buffer (ArvStream *stream, ArvBuffer *buffer)
+{
+ g_return_if_fail (ARV_IS_STREAM (stream));
+ g_return_if_fail (ARV_IS_BUFFER (buffer));
+
+ g_async_queue_push (stream->priv->output_queue, buffer);
+
+ if (stream->priv->emit_signals)
+ g_signal_emit (stream, arv_stream_signals[ARV_STREAM_SIGNAL_NEW_BUFFER], 0);
}
/**
@@ -92,9 +133,9 @@ arv_stream_get_n_buffers (ArvStream *stream, gint *n_input_buffers, gint *n_outp
}
if (n_input_buffers != NULL)
- *n_input_buffers = g_async_queue_length (stream->input_queue);
+ *n_input_buffers = g_async_queue_length (stream->priv->input_queue);
if (n_output_buffers != NULL)
- *n_output_buffers = g_async_queue_length (stream->output_queue);
+ *n_output_buffers = g_async_queue_length (stream->priv->output_queue);
}
/**
@@ -134,11 +175,86 @@ arv_stream_get_statistics (ArvStream *stream,
stream_class->get_statistics (stream, n_completed_buffers, n_failures, n_underruns);
}
+/**
+ * arv_stream_set_emit_signals:
+ * @stream: a #ArvStream
+ * @emit_signals: the new state
+ *
+ * Make stream emit signals. This option is
+ * by default disabled because signal emission is expensive and unneeded when
+ * the application prefers to operate in pull mode.
+ *
+ * Since: 0.1.3
+ */
+
+void
+arv_stream_set_emit_signals (ArvStream *stream, gboolean emit_signals)
+{
+ g_return_if_fail (ARV_IS_STREAM (stream));
+
+ stream->priv->emit_signals = emit_signals;
+}
+
+/**
+ * arv_stream_get_emit_signals:
+ * @stream: a #ArvStream
+ *
+ * Check if stream will emit its signals.
+ *
+ * Returns: %TRUE if @appsink is emiting its signals.
+ *
+ * Since: 0.1.3
+ */
+
+gboolean
+arv_stream_get_emit_signals (ArvStream *stream)
+{
+ g_return_val_if_fail (ARV_IS_STREAM (stream), FALSE);
+
+ return stream->priv->emit_signals;
+}
+
+static void
+arv_stream_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ ArvStream *stream = ARV_STREAM (object);
+
+ switch (prop_id) {
+ case ARV_STREAM_PROPERTY_EMIT_SIGNALS:
+ arv_stream_set_emit_signals (stream, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+arv_stream_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ ArvStream *stream = ARV_STREAM (object);
+
+ switch (prop_id) {
+ case ARV_STREAM_PROPERTY_EMIT_SIGNALS:
+ g_value_set_boolean (value, arv_stream_get_emit_signals (stream));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
arv_stream_init (ArvStream *stream)
{
- stream->input_queue = g_async_queue_new ();
- stream->output_queue = g_async_queue_new ();
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, ARV_TYPE_STREAM, ArvStreamPrivate);
+
+ stream->priv->input_queue = g_async_queue_new ();
+ stream->priv->output_queue = g_async_queue_new ();
+
+ stream->priv->emit_signals = FALSE;
}
static void
@@ -149,25 +265,25 @@ arv_stream_finalize (GObject *object)
arv_debug ("stream",
"[Stream::finalize] Flush %d buffer[s] in input queue",
- g_async_queue_length (stream->input_queue));
+ g_async_queue_length (stream->priv->input_queue));
arv_debug ("stream",
"[Stream::finalize] Flush %d buffer[s] in output queue",
- g_async_queue_length (stream->output_queue));
+ g_async_queue_length (stream->priv->output_queue));
do {
- buffer = g_async_queue_try_pop (stream->output_queue);
+ buffer = g_async_queue_try_pop (stream->priv->output_queue);
if (buffer != NULL)
g_object_unref (buffer);
} while (buffer != NULL);
do {
- buffer = g_async_queue_try_pop (stream->input_queue);
+ buffer = g_async_queue_try_pop (stream->priv->input_queue);
if (buffer != NULL)
g_object_unref (buffer);
} while (buffer != NULL);
- g_async_queue_unref (stream->input_queue);
- g_async_queue_unref (stream->output_queue);
+ g_async_queue_unref (stream->priv->input_queue);
+ g_async_queue_unref (stream->priv->output_queue);
parent_class->finalize (object);
}
@@ -177,9 +293,44 @@ arv_stream_class_init (ArvStreamClass *node_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (node_class);
+ g_type_class_add_private (node_class, sizeof (ArvStreamPrivate));
+
parent_class = g_type_class_peek_parent (node_class);
object_class->finalize = arv_stream_finalize;
+ object_class->set_property = arv_stream_set_property;
+ object_class->get_property = arv_stream_get_property;
+
+ /**
+ * ArvStream::new-buffer:
+ * @stream: the stream that emited the signal
+ *
+ * Signal that a new buffer is available.
+ *
+ * This signal is emited from the stream receive thread and only when the
+ * "emit-signals" property is %TRUE.
+ *
+ * The new buffer can be retrieved with arv_stream_pop_buffer().
+ *
+ * Note that this signal is only emited when the "emit-signals" property is
+ * set to %TRUE, which it is not by default for performance reasons.
+ */
+
+ arv_stream_signals[ARV_STREAM_SIGNAL_NEW_BUFFER] =
+ g_signal_new ("new-buffer",
+ G_TYPE_FROM_CLASS (node_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ArvStreamClass, new_buffer),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
+
+ g_object_class_install_property (
+ object_class, ARV_STREAM_PROPERTY_EMIT_SIGNALS,
+ g_param_spec_boolean ("emit-signals", "Emit signals",
+ "Emit signals", FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+ );
+
}
G_DEFINE_ABSTRACT_TYPE (ArvStream, arv_stream, G_TYPE_OBJECT)
diff --git a/src/arvstream.h b/src/arvstream.h
index e8c444c..c419a76 100644
--- a/src/arvstream.h
+++ b/src/arvstream.h
@@ -53,13 +53,13 @@ typedef void (*ArvStreamCallback) (void *user_data, ArvStreamCallbackType type,
#define ARV_IS_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ARV_TYPE_STREAM))
#define ARV_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), ARV_TYPE_STREAM, ArvStreamClass))
+typedef struct _ArvStreamPrivate ArvStreamPrivate;
typedef struct _ArvStreamClass ArvStreamClass;
struct _ArvStream {
GObject object;
- GAsyncQueue *input_queue;
- GAsyncQueue *output_queue;
+ ArvStreamPrivate *priv;
};
struct _ArvStreamClass {
@@ -67,19 +67,27 @@ struct _ArvStreamClass {
void (*get_statistics) (ArvStream *stream, guint64 *n_completed_buffers,
guint64 *n_failures, guint64 *n_underruns);
+
+ void (*new_buffer) (ArvStream *stream);
};
GType arv_stream_get_type (void);
-void arv_stream_push_buffer (ArvStream *stream, ArvBuffer *buffer);
-ArvBuffer * arv_stream_pop_buffer (ArvStream *stream);
-void arv_stream_get_n_buffers (ArvStream *stream,
- gint *n_input_buffers,
- gint *n_output_buffers);
-void arv_stream_get_statistics (ArvStream *stream,
- guint64 *n_completed_buffers,
- guint64 *n_failures,
- guint64 *n_underruns);
+void arv_stream_push_buffer (ArvStream *stream, ArvBuffer *buffer);
+ArvBuffer * arv_stream_pop_buffer (ArvStream *stream);
+void arv_stream_get_n_buffers (ArvStream *stream,
+ gint *n_input_buffers,
+ gint *n_output_buffers);
+void arv_stream_get_statistics (ArvStream *stream,
+ guint64 *n_completed_buffers,
+ guint64 *n_failures,
+ guint64 *n_underruns);
+
+void arv_stream_set_emit_signals (ArvStream *stream, gboolean emit_signals);
+gboolean arv_stream_get_emit_signals (ArvStream *stream);
+
+ArvBuffer * arv_stream_pop_input_buffer (ArvStream *stream);
+void arv_stream_push_output_buffer (ArvStream *stream, ArvBuffer *buffer);
G_END_DECLS
diff --git a/tests/arvcameratest.c b/tests/arvcameratest.c
index d1970ff..501a05d 100644
--- a/tests/arvcameratest.c
+++ b/tests/arvcameratest.c
@@ -1,13 +1,6 @@
#include <arv.h>
#include <stdlib.h>
-
-static gboolean cancel = FALSE;
-
-static void
-set_cancel (int signal)
-{
- cancel = TRUE;
-}
+#include <signal.h>
static char *arv_option_camera_name = NULL;
static char *arv_option_debug_domains = NULL;
@@ -51,9 +44,53 @@ static const GOptionEntry arv_option_entries[] =
{ NULL }
};
+typedef struct {
+ GMainLoop *main_loop;
+ int buffer_count;
+} ApplicationData;
+
+static gboolean cancel = FALSE;
+
+static void
+set_cancel (int signal)
+{
+ cancel = TRUE;
+}
+
+static void
+new_buffer_cb (ArvStream *stream, ApplicationData *data)
+{
+ ArvBuffer *buffer;
+
+ buffer = arv_stream_pop_buffer (stream);
+ if (buffer != NULL) {
+ if (buffer->status == ARV_BUFFER_STATUS_SUCCESS)
+ data->buffer_count++;
+ /* Image processing here */
+ arv_stream_push_buffer (stream, buffer);
+ }
+}
+
+static gboolean
+periodic_task_cb (void *abstract_data)
+{
+ ApplicationData *data = abstract_data;
+
+ g_printf ("Frame rate = %d Hz\n", data->buffer_count);
+ data->buffer_count = 0;
+
+ if (cancel) {
+ g_main_loop_quit (data->main_loop);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
int
main (int argc, char **argv)
{
+ ApplicationData data;
ArvCamera *camera;
ArvStream *stream;
ArvBuffer *buffer;
@@ -61,6 +98,8 @@ main (int argc, char **argv)
GError *error = NULL;
int i;
+ data.buffer_count = 0;
+
g_thread_init (NULL);
g_type_init ();
@@ -85,6 +124,7 @@ main (int argc, char **argv)
camera = arv_camera_new (arv_option_camera_name);
if (camera != NULL) {
+ void (*old_sigint_handler)(int);
gint payload;
gint x, y, width, height;
gint dx, dy;
@@ -121,7 +161,7 @@ main (int argc, char **argv)
ARV_GV_STREAM_OPTION_SOCKET_BUFFER_AUTO,
0);
- for (i = 0; i < 200; i++)
+ for (i = 0; i < 50; i++)
arv_stream_push_buffer (stream, arv_buffer_new (payload, NULL));
arv_camera_set_acquisition_mode (camera, ARV_ACQUISITION_MODE_CONTINUOUS);
@@ -134,27 +174,20 @@ main (int argc, char **argv)
arv_camera_start_acquisition (camera);
- signal (SIGINT, set_cancel);
+ g_signal_connect (stream, "new-buffer", G_CALLBACK (new_buffer_cb), &data);
+ arv_stream_set_emit_signals (stream, TRUE);
+
+ g_timeout_add_seconds (1, periodic_task_cb, &data);
- do {
- int buffer_count;
+ data.main_loop = g_main_loop_new (NULL, FALSE);
- g_usleep (1000000);
+ old_sigint_handler = signal (SIGINT, set_cancel);
- buffer_count = 0;
- do {
- buffer = arv_stream_pop_buffer (stream);
- if (buffer != NULL) {
- if (buffer->status == ARV_BUFFER_STATUS_SUCCESS)
- buffer_count++;
- /* Image processing here */
- arv_stream_push_buffer (stream, buffer);
- }
- } while (buffer != NULL);
+ g_main_loop_run (data.main_loop);
- g_printf ("Frame rate = %d\n", buffer_count);
+ signal (SIGINT, old_sigint_handler);
- } while (!cancel);
+ g_main_loop_unref (data.main_loop);
arv_stream_get_statistics (stream, &n_completed_buffers, &n_failures, &n_underruns);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]