summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2014-02-14 14:28:59 +0100
committerMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2014-02-14 14:34:47 +0100
commitf15d21389a81f8df36b00113aed5c81d27143861 (patch)
treec7a6247afd73254c202a8ccbb1e93bb43287b315
parentdf1ae54168a7dda396050077f14fed33c4882c47 (diff)
downloadlibuca-f15d21389a81f8df36b00113aed5c81d27143861.tar.gz
libuca-f15d21389a81f8df36b00113aed5c81d27143861.tar.bz2
libuca-f15d21389a81f8df36b00113aed5c81d27143861.tar.xz
libuca-f15d21389a81f8df36b00113aed5c81d27143861.zip
Use read-write ring buffer
-rw-r--r--bin/gui/control.c93
-rw-r--r--bin/tools/grab.c7
-rw-r--r--plugins/mock/uca-mock-camera.c49
-rw-r--r--src/uca-ring-buffer.c92
-rw-r--r--src/uca-ring-buffer.h11
-rw-r--r--test/test-ring-buffer.c38
6 files changed, 153 insertions, 137 deletions
diff --git a/bin/gui/control.c b/bin/gui/control.c
index 545c095..d4191a1 100644
--- a/bin/gui/control.c
+++ b/bin/gui/control.c
@@ -309,7 +309,7 @@ get_statistics (ThreadData *data, gdouble *mean, gdouble *sigma, guint *_max, gu
guint n = data->width * data->height;
if (data->pixel_size == 1) {
- guint8 *input = (guint8 *) uca_ring_buffer_get_current_pointer (data->buffer);
+ guint8 *input = (guint8 *) uca_ring_buffer_peek_pointer (data->buffer);
for (gint i = 0; i < n; i++) {
guint8 val = input[i];
@@ -325,7 +325,7 @@ get_statistics (ThreadData *data, gdouble *mean, gdouble *sigma, guint *_max, gu
}
}
else {
- guint16 *input = (guint16 *) uca_ring_buffer_get_current_pointer (data->buffer);
+ guint16 *input = (guint16 *) uca_ring_buffer_peek_pointer (data->buffer);
for (gint i = 0; i < n; i++) {
guint16 val = input[i];
@@ -407,7 +407,7 @@ on_motion_notify (GtkWidget *event_box, GdkEventMotion *event, ThreadData *data)
gpointer *buffer;
GString *string;
- buffer = uca_ring_buffer_get_current_pointer (data->buffer);
+ buffer = uca_ring_buffer_peek_pointer (data->buffer);
string = g_string_new_len (NULL, 32);
gint i = (data->display_y / data->zoom_factor) * data->width + data->display_x / data->zoom_factor;
@@ -560,9 +560,6 @@ update_pixbuf (ThreadData *data)
gtk_widget_queue_draw_area (data->image, 0, 0, data->display_width, data->display_height);
- egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view),
- uca_ring_buffer_get_current_pointer (data->buffer));
-
if ((data->adj_width > 0) && (data->adj_height > 0)) {
x = data->from_x;
y = data->from_y;
@@ -681,48 +678,52 @@ preview_frames (void *args)
while (data->state == RUNNING) {
gpointer *buffer;
- buffer = uca_ring_buffer_get_current_pointer (data->buffer);
+ buffer = uca_ring_buffer_peek_pointer (data->buffer);
uca_camera_grab (data->camera, buffer, &error);
- if (error == NULL) {
- up_and_down_scale (data, buffer);
-
- gdk_threads_enter ();
- update_pixbuf (data);
+ if (error != NULL) {
+ print_and_free_error (&error);
+ continue;
+ }
- if ((data->ev_x >= 0) && (data->ev_y >= 0) && (data->ev_y <= data->display_height) && (data->ev_x <= data->display_width)) {
- GString *string;
- string = g_string_new_len (NULL, 32);
- gint i = (data->display_y / data->zoom_factor) * data->width + data->display_x / data->zoom_factor;
+ up_and_down_scale (data, buffer);
- if (data->pixel_size == 1) {
- guint8 *input = (guint8 *) buffer;
- guint8 val = input[i];
- g_string_printf (string, "val = %i", val);
- gtk_label_set_text (data->val_label, string->str);
- }
- else if (data->pixel_size == 2) {
- guint16 *input = (guint16 *) buffer;
- guint16 val = input[i];
- g_string_printf (string, "val = %i", val);
- gtk_label_set_text (data->val_label, string->str);
- }
+ gdk_threads_enter ();
- g_string_printf (string, "x = %i", data->display_x);
- gtk_label_set_text (data->x_label, string->str);
+ update_pixbuf (data);
+ egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view), buffer);
- g_string_printf (string, "y = %i", data->display_y);
- gtk_label_set_text (data->y_label, string->str);
+ if ((data->ev_x >= 0) && (data->ev_y >= 0) &&
+ (data->ev_y <= data->display_height) && (data->ev_x <= data->display_width)) {
+ GString *string;
+ string = g_string_new_len (NULL, 32);
+ gint i = (data->display_y / data->zoom_factor) * data->width + data->display_x / data->zoom_factor;
- g_string_free (string, TRUE);
+ if (data->pixel_size == 1) {
+ guint8 *input = (guint8 *) buffer;
+ guint8 val = input[i];
+ g_string_printf (string, "val = %i", val);
+ gtk_label_set_text (data->val_label, string->str);
+ }
+ else if (data->pixel_size == 2) {
+ guint16 *input = (guint16 *) buffer;
+ guint16 val = input[i];
+ g_string_printf (string, "val = %i", val);
+ gtk_label_set_text (data->val_label, string->str);
}
- gdk_threads_leave ();
+ g_string_printf (string, "x = %i", data->display_x);
+ gtk_label_set_text (data->x_label, string->str);
- counter++;
+ g_string_printf (string, "y = %i", data->display_y);
+ gtk_label_set_text (data->y_label, string->str);
+
+ g_string_free (string, TRUE);
}
- else
- print_and_free_error (&error);
+
+ gdk_threads_leave ();
+
+ counter++;
}
return NULL;
}
@@ -749,11 +750,10 @@ record_frames (gpointer args)
if (n_max > 0 && n_frames >= n_max)
break;
- buffer = uca_ring_buffer_get_current_pointer (data->buffer);
+ buffer = uca_ring_buffer_get_write_pointer (data->buffer);
uca_camera_grab (data->camera, buffer, NULL);
if (error == NULL) {
- uca_ring_buffer_proceed (data->buffer);
n_frames++;
data->n_recorded++;
}
@@ -806,9 +806,8 @@ update_current_frame (ThreadData *data)
if (n_max > 0)
index = (index + data->n_recorded - n_max) % n_max;
- uca_ring_buffer_set_current_pointer (data->buffer, index);
-
- buffer = uca_ring_buffer_get_current_pointer (data->buffer);
+ buffer = uca_ring_buffer_get_pointer (data->buffer, index);
+ egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view), buffer);
up_and_down_scale (data, buffer);
update_pixbuf (data);
}
@@ -948,9 +947,9 @@ download_frames (ThreadData *data)
uca_ring_buffer_reset (data->buffer);
while (error == NULL) {
- buffer = uca_ring_buffer_get_current_pointer (data->buffer);
+ buffer = uca_ring_buffer_get_write_pointer (data->buffer);
uca_camera_grab (data->camera, buffer, &error);
- uca_ring_buffer_proceed (data->buffer);
+
gdk_threads_enter ();
gtk_adjustment_set_value (data->download_adjustment, current_frame++);
gdk_threads_leave ();
@@ -1002,7 +1001,7 @@ static void
update_zoomed_pixbuf (ThreadData *data)
{
update_pixbuf_dimensions (data);
- up_and_down_scale (data, uca_ring_buffer_get_current_pointer (data->buffer));
+ up_and_down_scale (data, uca_ring_buffer_peek_pointer (data->buffer));
update_pixbuf (data);
}
@@ -1068,7 +1067,7 @@ on_colormap_changed (GtkComboBox *widget, ThreadData *data)
data->colormap = map;
update_pixbuf_dimensions (data);
- up_and_down_scale (data, uca_ring_buffer_get_current_pointer (data->buffer));
+ up_and_down_scale (data, uca_ring_buffer_peek_pointer (data->buffer));
update_pixbuf (data);
}
@@ -1178,7 +1177,7 @@ create_main_window (GtkBuilder *builder, const gchar* camera_name)
ring_buffer = uca_ring_buffer_new (image_size, n_frames);
egg_histogram_view_update (EGG_HISTOGRAM_VIEW (histogram_view),
- uca_ring_buffer_get_current_pointer (ring_buffer));
+ uca_ring_buffer_peek_pointer (ring_buffer));
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
diff --git a/bin/tools/grab.c b/bin/tools/grab.c
index 50c70a8..a3dd544 100644
--- a/bin/tools/grab.c
+++ b/bin/tools/grab.c
@@ -77,7 +77,7 @@ write_tiff (UcaRingBuffer *buffer,
gpointer data;
gsize offset = 0;
- data = uca_ring_buffer_get_pointer (buffer, i);
+ data = uca_ring_buffer_get_read_pointer (buffer);
TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height);
@@ -119,7 +119,7 @@ write_raw (UcaRingBuffer *buffer,
filename = g_strdup_printf ("frame-%08i.raw", i);
fp = fopen(filename, "wb");
- data = uca_ring_buffer_get_pointer (buffer, i);
+ data = uca_ring_buffer_get_read_pointer (buffer);
fwrite (data, size, 1, fp);
fclose (fp);
@@ -169,8 +169,7 @@ record_frames (UcaCamera *camera, Options *opts)
while (1) {
gdouble elapsed;
- uca_camera_grab (camera, uca_ring_buffer_get_current_pointer (buffer), &error);
- uca_ring_buffer_proceed (buffer);
+ uca_camera_grab (camera, uca_ring_buffer_get_write_pointer (buffer), &error);
if (error != NULL)
return error;
diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c
index 18ac7db..b75882e 100644
--- a/plugins/mock/uca-mock-camera.c
+++ b/plugins/mock/uca-mock-camera.c
@@ -155,6 +155,7 @@ static void
print_current_frame (UcaMockCameraPrivate *priv, gchar *buffer)
{
guint number = priv->current_frame;
+ char default_line[priv->width];
guint divisor = 10000000;
int x = 1;
@@ -165,45 +166,33 @@ print_current_frame (UcaMockCameraPrivate *priv, gchar *buffer)
x += DIGIT_WIDTH + 1;
}
-
- //Rainbow pattern is the same for every row. Just calculate one single
- //Scanline, so we can reuse it and dont have to do the whole calculation
- //for every row again.
- char default_line[priv->width];
for (int p = 0; p < priv->width; p++) {
default_line[p] = (char) ((p*256) / (priv->width));
}
-
- //Use memcpy to quickly fill every row with the precalculated rainbow
- //pattern
for (guint y = 16; y < priv->height; y++) {
guint index = y * priv->width;
- memcpy(&buffer[index], &default_line[0], priv->width);
+ memcpy (&buffer[index], &default_line[0], priv->width);
}
- #ifdef __CREATE_RANDOM_IMAGE_DATA__
-
- //This block will fill a square at the center of the image with noraml
- //distributed random data
- const double mean = 128.0;
- const double std = 32.0;
-
- for (guint y = (priv->height/3); y < ((priv->height*2)/3); y++) {
- guint row_start = y * priv->width;
- for (guint i = (priv->width/3); i < ((priv->width*2)/3); i++) {
- int index = row_start + i;
- double u1 = g_rand_double(priv->rand);
- double u2 = g_rand_double(priv->rand);
- double r = sqrt(-2 * log(u1)) * cos(2 * G_PI * u2);
- buffer[index] = (guint8) (r * std + mean);
- }
+#ifdef __CREATE_RANDOM_IMAGE_DATA__
+ //This block will fill a square at the center of the image with noraml
+ //distributed random data
+ const double mean = 128.0;
+ const double std = 32.0;
+
+ for (guint y = (priv->height/3); y < ((priv->height*2)/3); y++) {
+ guint row_start = y * priv->width;
+
+ for (guint i = (priv->width/3); i < ((priv->width*2)/3); i++) {
+ int index = row_start + i;
+ double u1 = g_rand_double (priv->rand);
+ double u2 = g_rand_double (priv->rand);
+ double r = sqrt (-2 * log(u1)) * cos(2 * G_PI * u2);
+ buffer[index] = (guint8) (r * std + mean);
}
-
- #endif
-
-
-
+ }
+#endif
}
static gpointer
diff --git a/src/uca-ring-buffer.c b/src/uca-ring-buffer.c
index 40d7a25..98ede8f 100644
--- a/src/uca-ring-buffer.c
+++ b/src/uca-ring-buffer.c
@@ -26,8 +26,11 @@ struct _UcaRingBufferPrivate {
guchar *data;
gsize block_size;
guint n_blocks_total;
- guint n_blocks_used;
- guint current_index;
+ guint write_index;
+ guint read_index;
+ guint read;
+ guint written;
+ gboolean full;
};
enum {
@@ -57,8 +60,9 @@ uca_ring_buffer_reset (UcaRingBuffer *buffer)
{
g_return_if_fail (UCA_IS_RING_BUFFER (buffer));
- buffer->priv->n_blocks_used = 0;
- buffer->priv->current_index = 0;
+ buffer->priv->write_index = 0;
+ buffer->priv->read_index = 0;
+ buffer->priv->full = FALSE;
}
gsize
@@ -68,6 +72,13 @@ uca_ring_buffer_get_block_size (UcaRingBuffer *buffer)
return buffer->priv->block_size;
}
+gboolean
+uca_ring_buffer_available (UcaRingBuffer *buffer)
+{
+ g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), FALSE);
+ return buffer->priv->read_index < buffer->priv->write_index;
+}
+
/**
* uca_ring_buffer_get_current_pointer:
* @buffer: A #UcaRingBuffer object
@@ -79,66 +90,63 @@ uca_ring_buffer_get_block_size (UcaRingBuffer *buffer)
* Return value: (transfer none): Pointer to data block
*/
gpointer
-uca_ring_buffer_get_current_pointer (UcaRingBuffer *buffer)
+uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer)
{
UcaRingBufferPrivate *priv;
+ gpointer data;
g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), NULL);
priv = buffer->priv;
- return priv->data + (priv->current_index % priv->n_blocks_total) * priv->block_size;
+ data = priv->data + (priv->read_index % priv->n_blocks_total) * priv->block_size;
+ priv->read_index++;
+ return data;
}
-void
-uca_ring_buffer_set_current_pointer (UcaRingBuffer *buffer,
- guint index)
+gpointer
+uca_ring_buffer_get_write_pointer (UcaRingBuffer *buffer)
{
- g_return_if_fail (UCA_IS_RING_BUFFER (buffer));
- g_assert (index < buffer->priv->n_blocks_total);
- buffer->priv->current_index = index;
+ UcaRingBufferPrivate *priv;
+ gpointer data;
+
+ g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), NULL);
+
+ priv = buffer->priv;
+ data = priv->data + (priv->write_index % priv->n_blocks_total) * priv->block_size;
+ priv->write_index++;
+
+ if ((priv->write_index - priv->read_index) == priv->n_blocks_total)
+ priv->full = TRUE;
+
+ return data;
}
-/**
- * uca_ring_buffer_get_pointer:
- * @buffer: A #UcaRingBuffer object
- * @index: Block index to get the pointer for
- *
- * Get a pointer to the data for @index block. @index must be less than
- * :num-blocks.
- *
- * Return value: (transfer none): Pointer to data block
- */
gpointer
-uca_ring_buffer_get_pointer (UcaRingBuffer *buffer,
- guint index)
+uca_ring_buffer_peek_pointer (UcaRingBuffer *buffer)
{
UcaRingBufferPrivate *priv;
-
g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), NULL);
- g_assert (index < buffer->priv->n_blocks_total);
priv = buffer->priv;
- return priv->data + ((priv->current_index - priv->n_blocks_used + index) % priv->n_blocks_total) * priv->block_size;
+ return ((guint8 *) priv->data) + ((priv->write_index % priv->n_blocks_total) * priv->block_size);
}
-guint
-uca_ring_buffer_get_num_blocks (UcaRingBuffer *buffer)
+gpointer
+uca_ring_buffer_get_pointer (UcaRingBuffer *buffer,
+ guint index)
{
- g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), 0);
- return buffer->priv->n_blocks_used;
+ UcaRingBufferPrivate *priv;
+ g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), NULL);
+ priv = buffer->priv;
+ return ((guint8 *) priv->data) + (((priv->read_index + index) % priv->n_blocks_total) * priv->block_size);
}
-void
-uca_ring_buffer_proceed (UcaRingBuffer *buffer)
+guint
+uca_ring_buffer_get_num_blocks (UcaRingBuffer *buffer)
{
UcaRingBufferPrivate *priv;
- g_return_if_fail (UCA_IS_RING_BUFFER (buffer));
+ g_return_val_if_fail (UCA_IS_RING_BUFFER (buffer), 0);
priv = buffer->priv;
- priv->current_index++;
-
- if (priv->n_blocks_used < priv->n_blocks_total)
- priv->n_blocks_used++;
- else
- priv->current_index = priv->current_index % priv->n_blocks_total;
+ return priv->write_index < priv->n_blocks_total ? priv->write_index : priv->n_blocks_total;
}
static void
@@ -259,9 +267,7 @@ uca_ring_buffer_init (UcaRingBuffer *buffer)
UcaRingBufferPrivate *priv;
priv = buffer->priv = UCA_RING_BUFFER_GET_PRIVATE (buffer);
- priv->n_blocks_used = 0;
- priv->current_index = 0;
- priv->block_size = 0;
priv->n_blocks_total = 0;
+ priv->block_size = 0;
priv->data = NULL;
}
diff --git a/src/uca-ring-buffer.h b/src/uca-ring-buffer.h
index 03e2cae..c90f2d2 100644
--- a/src/uca-ring-buffer.h
+++ b/src/uca-ring-buffer.h
@@ -32,13 +32,14 @@ UcaRingBuffer * uca_ring_buffer_new (gsize block_size,
guint n_blocks);
void uca_ring_buffer_reset (UcaRingBuffer *buffer);
gsize uca_ring_buffer_get_block_size (UcaRingBuffer *buffer);
-gpointer uca_ring_buffer_get_current_pointer (UcaRingBuffer *buffer);
-void uca_ring_buffer_set_current_pointer (UcaRingBuffer *buffer,
- guint index);
-gpointer uca_ring_buffer_get_pointer (UcaRingBuffer *buffer,
- guint index);
guint uca_ring_buffer_get_num_blocks (UcaRingBuffer *buffer);
+gboolean uca_ring_buffer_available (UcaRingBuffer *buffer);
void uca_ring_buffer_proceed (UcaRingBuffer *buffer);
+gpointer uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer);
+gpointer uca_ring_buffer_get_write_pointer (UcaRingBuffer *buffer);
+gpointer uca_ring_buffer_get_pointer (UcaRingBuffer *buffer,
+ guint index);
+gpointer uca_ring_buffer_peek_pointer (UcaRingBuffer *buffer);
GType uca_ring_buffer_get_type (void);
diff --git a/test/test-ring-buffer.c b/test/test-ring-buffer.c
index 2026408..02bf1eb 100644
--- a/test/test-ring-buffer.c
+++ b/test/test-ring-buffer.c
@@ -14,7 +14,7 @@ test_new_constructor (void)
g_assert (uca_ring_buffer_get_block_size (buffer) == 512);
g_assert (uca_ring_buffer_get_num_blocks (buffer) == 0);
- g_assert (uca_ring_buffer_get_current_pointer (buffer) != NULL);
+ g_assert (uca_ring_buffer_get_write_pointer (buffer) != NULL);
g_object_unref (buffer);
}
@@ -28,7 +28,7 @@ test_new_func (void)
g_assert (uca_ring_buffer_get_block_size (buffer) == 512);
g_assert (uca_ring_buffer_get_num_blocks (buffer) == 0);
- g_assert (uca_ring_buffer_get_current_pointer (buffer) != NULL);
+ g_assert (uca_ring_buffer_get_write_pointer (buffer) != NULL);
g_object_unref (buffer);
}
@@ -41,26 +41,47 @@ test_ring (void)
buffer = uca_ring_buffer_new (512, 2);
- data = uca_ring_buffer_get_current_pointer (buffer);
+ data = uca_ring_buffer_get_write_pointer (buffer);
data[0] = 0xBADF00D;
- uca_ring_buffer_proceed (buffer);
- data = uca_ring_buffer_get_current_pointer (buffer);
+ g_assert (uca_ring_buffer_available (buffer));
+ g_assert (uca_ring_buffer_get_num_blocks (buffer) == 1);
+
+ data = uca_ring_buffer_get_write_pointer (buffer);
data[0] = 0xDEADBEEF;
- uca_ring_buffer_proceed (buffer);
g_assert (uca_ring_buffer_get_num_blocks (buffer) == 2);
- data = uca_ring_buffer_get_current_pointer (buffer);
+ data = uca_ring_buffer_get_read_pointer (buffer);
g_assert (data[0] == 0xBADF00D);
- data = uca_ring_buffer_get_pointer (buffer, 1);
+ data = uca_ring_buffer_get_read_pointer (buffer);
g_assert (data[0] == 0xDEADBEEF);
+ g_assert (!uca_ring_buffer_available (buffer));
+
uca_ring_buffer_reset (buffer);
g_assert (uca_ring_buffer_get_num_blocks (buffer) == 0);
}
+static void
+test_overwrite (void)
+{
+ UcaRingBuffer *buffer;
+ guint32 *data;
+
+ buffer = uca_ring_buffer_new (512, 1);
+
+ data = uca_ring_buffer_get_write_pointer (buffer);
+ data[0] = 0xBADF00D;
+
+ data = uca_ring_buffer_get_write_pointer (buffer);
+ data[0] = 0xDEADBEEF;
+
+ data = uca_ring_buffer_get_read_pointer (buffer);
+ g_assert (data[0] == 0xDEADBEEF);
+}
+
int
main (int argc, char *argv[])
{
@@ -70,6 +91,7 @@ main (int argc, char *argv[])
g_test_add_func ("/ringbuffer/new/constructor", test_new_constructor);
g_test_add_func ("/ringbuffer/new/func", test_new_func);
g_test_add_func ("/ringbuffer/functionality ", test_ring);
+ g_test_add_func ("/ringbuffer/overwrite ", test_overwrite);
return g_test_run ();
}