diff options
author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2015-07-20 14:49:11 +0200 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2015-07-20 14:49:11 +0200 |
commit | fee073b676044d454220616fb99bca6586a21f19 (patch) | |
tree | 87b1198ba92bf7180b5aa1ebafe08874c5c62212 | |
parent | d6d430491cc7f81945e4061d3ae3bbe67593c0a7 (diff) | |
download | libuca-fee073b676044d454220616fb99bca6586a21f19.tar.gz libuca-fee073b676044d454220616fb99bca6586a21f19.tar.bz2 libuca-fee073b676044d454220616fb99bca6586a21f19.tar.xz libuca-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.
-rw-r--r-- | bin/gui/control.c | 52 |
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; } |