diff options
author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2014-02-14 14:28:59 +0100 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2014-02-14 14:34:47 +0100 |
commit | f15d21389a81f8df36b00113aed5c81d27143861 (patch) | |
tree | c7a6247afd73254c202a8ccbb1e93bb43287b315 | |
parent | df1ae54168a7dda396050077f14fed33c4882c47 (diff) | |
download | libuca-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.c | 93 | ||||
-rw-r--r-- | bin/tools/grab.c | 7 | ||||
-rw-r--r-- | plugins/mock/uca-mock-camera.c | 49 | ||||
-rw-r--r-- | src/uca-ring-buffer.c | 92 | ||||
-rw-r--r-- | src/uca-ring-buffer.h | 11 | ||||
-rw-r--r-- | test/test-ring-buffer.c | 38 |
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 (); } |