[aravis] stream: implement new-buffer signal.



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]