summaryrefslogtreecommitdiffstats
path: root/bin/gui
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2015-07-20 14:49:11 +0200
committerMatthias Vogelgesang <matthias.vogelgesang@kit.edu>2015-07-20 14:49:11 +0200
commitfee073b676044d454220616fb99bca6586a21f19 (patch)
tree87b1198ba92bf7180b5aa1ebafe08874c5c62212 /bin/gui
parentd6d430491cc7f81945e4061d3ae3bbe67593c0a7 (diff)
downloaduca-fee073b676044d454220616fb99bca6586a21f19.tar.gz
uca-fee073b676044d454220616fb99bca6586a21f19.tar.bz2
uca-fee073b676044d454220616fb99bca6586a21f19.tar.xz
uca-fee073b676044d454220616fb99bca6586a21f19.zip
Fix #72: avoid race condition
The advance_buffers variable introduced in 954bcbc was not properly locked thus leading to race conditions in the UI update thread and the actual grab thread. With this change, we always grab into a single buffer that is updated whenever the GUI is ready. This avoids latencies but might cause noticeable tearing.
Diffstat (limited to 'bin/gui')
-rw-r--r--bin/gui/control.c52
1 files changed, 18 insertions, 34 deletions
diff --git a/bin/gui/control.c b/bin/gui/control.c
index 8e650be..0b13ac1 100644
--- a/bin/gui/control.c
+++ b/bin/gui/control.c
@@ -82,6 +82,7 @@ typedef struct {
GtkAdjustment *frame_slider;
UcaRingBuffer *buffer;
+ guchar *shadow;
guchar *pixels;
gint display_width, display_height;
gint colormap;
@@ -90,7 +91,6 @@ typedef struct {
State state;
guint n_recorded;
gboolean data_in_camram;
- gboolean advance_buffers;
gint timestamp;
gint width, height;
@@ -676,20 +676,13 @@ grab_async (void *args)
GError *error = NULL;
while (data->state == RUNNING) {
- if (data->advance_buffers) {
- uca_ring_buffer_write_advance (data->buffer);
- data->advance_buffers = FALSE;
- }
-
- gpointer *buffer = uca_ring_buffer_peek_pointer (data->buffer);
- uca_camera_grab (data->camera, buffer, &error);
+ uca_camera_grab (data->camera, data->shadow, &error);
- if (error != NULL) {
+ if (error != NULL)
print_and_free_error (&error);
- }
}
- return NULL;
+ return NULL;
}
static gpointer
@@ -697,15 +690,12 @@ preview_frames (void *args)
{
ThreadData *data = (ThreadData *) args;
gint counter = 0;
- data->n_recorded = 0;
- uca_ring_buffer_reset (data->buffer);
GError *error = NULL;
+ data->n_recorded = 0;
+ data->shadow = g_malloc (uca_ring_buffer_get_block_size (data->buffer));
- /* manually grab first frame*/
- gpointer *buffer = uca_ring_buffer_peek_pointer (data->buffer);
- uca_camera_grab (data->camera, buffer, &error);
- data->advance_buffers = TRUE;
+ uca_camera_grab (data->camera, data->shadow, &error);
if (!g_thread_create (grab_async, data, FALSE, &error)) {
g_printerr ("Failed to create thread: %s\n", error->message);
@@ -715,21 +705,12 @@ preview_frames (void *args)
}
while (data->state == RUNNING) {
- /* wait for the grab thread to finish moving to the next buffer */
- if (data->advance_buffers)
- continue;
-
- /* buffer-pointer was already set either manually (before the while-loop
- * started) or ar the end of the while loop to make sure we get the
- * 'last' buffer which was used before the ring buffer was advanced to
- * the next block
- */
- up_and_down_scale (data, buffer);
+ up_and_down_scale (data, data->shadow);
gdk_threads_enter ();
update_pixbuf (data);
- egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view), buffer);
+ egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view), data->shadow);
if ((data->ev_x >= 0) && (data->ev_y >= 0) &&
(data->ev_y <= data->display_height) && (data->ev_x <= data->display_width)) {
@@ -738,13 +719,13 @@ preview_frames (void *args)
gint i = (data->display_y / data->zoom_factor) * data->width + data->display_x / data->zoom_factor;
if (data->pixel_size == 1) {
- guint8 *input = (guint8 *) buffer;
+ guint8 *input = (guint8 *) data->shadow;
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 *input = (guint16 *) data->shadow;
guint16 val = input[i];
g_string_printf (string, "val = %i", val);
gtk_label_set_text (data->val_label, string->str);
@@ -762,11 +743,14 @@ preview_frames (void *args)
gdk_threads_leave ();
counter++;
-
- /*prefetch pointer to current buffer location before advancing */
- buffer = uca_ring_buffer_get_read_pointer (data->buffer);
- data->advance_buffers = TRUE;
}
+
+ up_and_down_scale (data, data->shadow);
+ gdk_threads_enter ();
+ update_pixbuf (data);
+ gdk_threads_leave ();
+
+ g_free (data->shadow);
return NULL;
}