diff --git a/CMakeLists.txt b/CMakeLists.txt index 350091a4..8c5e25a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,5 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) -if (POLICY CMP0053) -cmake_policy(SET CMP0053 OLD) -endif () - -if (POLICY CMP0054) -cmake_policy(SET CMP0054 OLD) -endif () project(uca C) diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index cb2d9207..d467979d 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) add_subdirectory(gui) add_subdirectory(tools) diff --git a/bin/gui/CMakeLists.txt b/bin/gui/CMakeLists.txt index a8869dd7..dcb8e161 100644 --- a/bin/gui/CMakeLists.txt +++ b/bin/gui/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) find_package(PkgConfig) find_program(GLIB_COMPILE_RESOURCES glib-compile-resources REQUIRED) diff --git a/bin/gui/uca-camera-control.c b/bin/gui/uca-camera-control.c index 94f3bb8f..414152d8 100644 --- a/bin/gui/uca-camera-control.c +++ b/bin/gui/uca-camera-control.c @@ -887,7 +887,7 @@ preview_frames (void *args) update_pixbuf (data, data->shadow); gdk_threads_leave (); - gpointer buffer = uca_ring_buffer_get_write_pointer (data->buffer); + gpointer buffer = uca_ring_buffer_get_write_pointer (data->buffer, TODO, TODO); memcpy (buffer, data->shadow, uca_ring_buffer_get_block_size (data->buffer)); g_free (data->shadow); @@ -916,7 +916,7 @@ record_frames (gpointer args) if (n_max > 0 && n_frames >= n_max) break; - buffer = uca_ring_buffer_get_write_pointer (data->buffer); + buffer = uca_ring_buffer_get_write_pointer (data->buffer, TODO, TODO); uca_camera_grab (data->camera, buffer, NULL); uca_ring_buffer_write_advance (data->buffer); @@ -977,7 +977,7 @@ update_current_frame (ThreadData *data) else { /* we were in preview mode. Grab the 'next' frame in the buffer */ uca_ring_buffer_write_advance (data->buffer); - buffer = uca_ring_buffer_get_read_pointer (data->buffer); + buffer = uca_ring_buffer_get_read_pointer (data->buffer, TODO, TODO); } egg_histogram_view_update (EGG_HISTOGRAM_VIEW (data->histogram_view), buffer); @@ -1118,7 +1118,7 @@ download_frames (ThreadData *data) uca_ring_buffer_reset (data->buffer); while (error == NULL) { - buffer = uca_ring_buffer_get_write_pointer (data->buffer); + buffer = uca_ring_buffer_get_write_pointer (data->buffer, TODO, TODO); uca_camera_grab (data->camera, buffer, &error); uca_ring_buffer_write_advance (data->buffer); diff --git a/bin/tools/CMakeLists.txt b/bin/tools/CMakeLists.txt index 3f0044b8..da6f63e5 100644 --- a/bin/tools/CMakeLists.txt +++ b/bin/tools/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) #{{{ Variables set(libs uca) diff --git a/bin/tools/grab.c b/bin/tools/grab.c index dbe826cd..b6083016 100644 --- a/bin/tools/grab.c +++ b/bin/tools/grab.c @@ -96,8 +96,8 @@ write_tiff (UcaRingBuffer *buffer, for (guint i = 0; i < n_frames; i++) { gpointer data; gsize offset = 0; - - data = uca_ring_buffer_get_read_pointer (buffer); + gpointer metadata; + uca_ring_buffer_get_read_pointer (buffer, data, metadata); TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width); TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height); @@ -144,7 +144,7 @@ write_raw (UcaRingBuffer *buffer, for (gint i = 0; i < n_frames; i++) { gpointer data; - + gpointer metadata; if (multiple_files) { gchar *filename; filename = g_strdup_printf (opts->filename, i); @@ -152,7 +152,7 @@ write_raw (UcaRingBuffer *buffer, g_free (filename); } - data = uca_ring_buffer_get_read_pointer (buffer); + uca_ring_buffer_get_read_pointer (buffer, data, metadata); fwrite (data, size, 1, fp); if (multiple_files) @@ -210,7 +210,9 @@ record_frames (UcaCamera *camera, Options *opts) while (1) { g_timer_continue (frame_timer); - uca_camera_grab (camera, uca_ring_buffer_get_write_pointer (buffer), &error); + gpointer image, metadata; + uca_ring_buffer_get_write_pointer (buffer, image, metadata); + uca_camera_grab (camera, image, &error); g_timer_stop (frame_timer); uca_ring_buffer_write_advance (buffer); diff --git a/plugins/file/CMakeLists.txt b/plugins/file/CMakeLists.txt index 68741685..1e17951d 100644 --- a/plugins/file/CMakeLists.txt +++ b/plugins/file/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) project(ucafile C) find_package(TIFF) diff --git a/plugins/mock/CMakeLists.txt b/plugins/mock/CMakeLists.txt index 48a11beb..5cdca4a2 100644 --- a/plugins/mock/CMakeLists.txt +++ b/plugins/mock/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) project(ucamock C) set(UCA_CAMERA_NAME "mock") diff --git a/plugins/mock/uca-mock-camera.c b/plugins/mock/uca-mock-camera.c index 8d7aed5d..7dd3e892 100644 --- a/plugins/mock/uca-mock-camera.c +++ b/plugins/mock/uca-mock-camera.c @@ -375,6 +375,37 @@ uca_mock_camera_grab (UcaCamera *camera, gpointer data, GError **error) return TRUE; } +static gboolean +uca_mock_camera_grab_with_metadata (UcaCamera *camera, gpointer data, gpointer metadata, GError **error) +{ + g_return_val_if_fail(UCA_IS_CAMERA(camera), FALSE); + g_return_val_if_fail(data != NULL, FALSE); + g_return_val_if_fail(metadata != NULL, FALSE); + + UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE (camera); + + // normal grab + guint frame_number = priv->current_frame; + gboolean success = uca_mock_camera_grab(camera, data, error); + + if (success) { + // time in epoch + GTimeVal current_time; + g_get_current_time(¤t_time); + + // convert to microseconds + guint64 timestamp = (guint64) current_time.tv_sec * 1000000 + current_time.tv_usec; + + // put as string + gchar *timestamp_str = g_strdup_printf("%" G_GUINT64_FORMAT, timestamp); + g_hash_table_insert(metadata, g_strdup("timestamp"), ×tamp); + g_hash_table_insert(metadata, g_strdup("frame_number"), &frame_number); + } + + return success; +} + + static gboolean uca_mock_camera_readout (UcaCamera *camera, gpointer data, guint index, GError **error) { @@ -555,6 +586,7 @@ uca_mock_camera_class_init(UcaMockCameraClass *klass) camera_class->grab = uca_mock_camera_grab; camera_class->readout = uca_mock_camera_readout; camera_class->trigger = uca_mock_camera_trigger; + camera_class->grab_with_metadata = uca_mock_camera_grab_with_metadata; for (guint i = 0; mock_overrideables[i] != 0; i++) g_object_class_override_property(gobject_class, mock_overrideables[i], uca_camera_props[mock_overrideables[i]]); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d047003..40fbf3a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) project(uca C) #{{{ Sources diff --git a/src/uca-camera.c b/src/uca-camera.c index 341c5030..5a1d0641 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -670,10 +670,26 @@ buffer_thread (UcaCamera *camera) while (!camera->priv->cancelling_recording) { gpointer buffer; + gpointer metadata; + uca_ring_buffer_get_write_pointer (camera->priv->ring_buffer, buffer, metadata); - buffer = uca_ring_buffer_get_write_pointer (camera->priv->ring_buffer); + // select if grab_with_metadata is there. - if (!(*klass->grab) (camera, buffer, &error)) { + + int grab_success; + + if (klass->grab_with_metadata != NULL) { + // if plugin implements grab_with_metadata, use it + grab_success = klass->grab_with_metadata(camera, buffer, metadata, error); + } else { + // if plugin does not implement grab_with_metadata, use grab + if (metadata != NULL) { + memset(metadata, 0, sizeof(metadata)); + } + grab_success = klass->grab(camera, buffer, error); + } + + if (!grab_success) { camera->priv->cancelling_grab = TRUE; break; } @@ -1234,6 +1250,7 @@ uca_camera_grab (UcaCamera *camera, gpointer data, GError **error) } else { gpointer buffer; + gpointer metadata; if (camera->priv->ring_buffer == NULL) return FALSE; @@ -1249,13 +1266,14 @@ uca_camera_grab (UcaCamera *camera, gpointer data, GError **error) } } - buffer = uca_ring_buffer_get_read_pointer (camera->priv->ring_buffer); + uca_ring_buffer_get_read_pointer (camera->priv->ring_buffer, buffer, metadata); if (buffer == NULL) { g_set_error (error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_END_OF_STREAM, "Ring buffer is empty"); } else { + // TODO copy metadata memcpy (data, buffer, uca_ring_buffer_get_block_size (camera->priv->ring_buffer)); result = TRUE; } @@ -1263,6 +1281,27 @@ uca_camera_grab (UcaCamera *camera, gpointer data, GError **error) return result; } +gboolean uca_camera_grab_with_metadata(UcaCamera *camera, gpointer data, gpointer metadata, GError **error) +{ + g_return_val_if_fail(UCA_IS_CAMERA(camera), FALSE); + g_return_val_if_fail(data != NULL, FALSE); + + UcaCameraClass *klass; + klass = UCA_CAMERA_GET_CLASS(camera); + + if (klass->grab_with_metadata != NULL) { + // if plugin implements grab_with_metadata, use it + return klass->grab_with_metadata(camera, data, metadata, error); + } else { + // if plugin does not implement grab_with_metadata, use grab + if (metadata != NULL) { + memset(metadata, 0, sizeof(metadata)); + } + return klass->grab(camera, data, error); + } +} + + /** * uca_camera_readout: * @camera: A #UcaCamera object diff --git a/src/uca-camera.h b/src/uca-camera.h index ad7d128e..9e964552 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -146,6 +146,7 @@ struct _UcaCameraClass { void (*trigger) (UcaCamera *camera, GError **error); void (*write) (UcaCamera *camera, const gchar *name, gpointer data, gsize size, GError **error); gboolean (*grab) (UcaCamera *camera, gpointer data, GError **error); + gboolean (*grab_with_metadata) (UcaCamera *camera, gpointer data, gpointer metadata, GError **error); gboolean (*readout) (UcaCamera *camera, gpointer data, guint index, GError **error); }; @@ -176,6 +177,9 @@ gboolean uca_camera_grab (UcaCamera *camera, gpointer data, GError **error) __attribute__((nonnull (2))); +gboolean uca_camera_grab_with_metadata(UcaCamera *camera, + gpointer data, gpointer metadata, GError **error) + __attribute__((nonnull (2))); gboolean uca_camera_readout (UcaCamera *camera, gpointer data, guint index, diff --git a/src/uca-ring-buffer.c b/src/uca-ring-buffer.c index 2334b7c1..700d4a10 100644 --- a/src/uca-ring-buffer.c +++ b/src/uca-ring-buffer.c @@ -30,6 +30,7 @@ struct _UcaRingBufferPrivate { guint read_index; guint read; guint written; + GHashTable *metadata; }; enum { @@ -84,10 +85,11 @@ uca_ring_buffer_available (UcaRingBuffer *buffer) * Get pointer to current read location. If no data is available, %NULL is * returned. * - * Return value: (transfer none): Pointer to current read location + * @param image GPointer to image buffer + * @param metadata GPointer to metadata has table */ -gpointer -uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer) +void +uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer, gpointer image, gpointer metadata) { UcaRingBufferPrivate *priv; gpointer data; @@ -96,11 +98,12 @@ uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer) priv = buffer->priv; g_return_val_if_fail (priv->read_index != priv->write_index, NULL); - data = priv->data + (priv->read_index % priv->n_blocks_total) * priv->block_size; + image = priv->data + (priv->read_index % priv->n_blocks_total) * priv->block_size; + metadata = (gpointer) priv->metadata + priv->read_index % priv->n_blocks_total; priv->read_index++; - return data; } + /** * uca_ring_buffer_get_write_pointer: * @buffer: A #UcaRingBuffer object @@ -109,8 +112,8 @@ uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer) * * Return value: (transfer none): Pointer to current write location */ -gpointer -uca_ring_buffer_get_write_pointer (UcaRingBuffer *buffer) +void +uca_ring_buffer_get_write_pointer(UcaRingBuffer *buffer, gpointer image, gpointer metadata) { UcaRingBufferPrivate *priv; gpointer data; @@ -118,9 +121,9 @@ uca_ring_buffer_get_write_pointer (UcaRingBuffer *buffer) 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; + image = priv->data + (priv->write_index % priv->n_blocks_total) * priv->block_size; + metadata = (gpointer) priv->metadata + (priv->write_index % priv->n_blocks_total); - return data; } void @@ -181,8 +184,11 @@ realloc_mem (UcaRingBufferPrivate *priv) { if (priv->data != NULL) g_free (priv->data); + if (priv->metadata != NULL) + g_free (priv->metadata); priv->data = g_malloc0_n (priv->n_blocks_total, priv->block_size); + priv->metadata = g_malloc0_n (priv->n_blocks_total, priv->n_blocks_total); } static void @@ -253,6 +259,8 @@ uca_ring_buffer_finalize (GObject *object) priv = UCA_RING_BUFFER_GET_PRIVATE (object); g_free (priv->data); priv->data = NULL; + g_free (priv->metadata); + priv->metadata = NULL; G_OBJECT_CLASS (uca_ring_buffer_parent_class)->finalize (object); } @@ -297,4 +305,5 @@ uca_ring_buffer_init (UcaRingBuffer *buffer) priv->n_blocks_total = 0; priv->block_size = 0; priv->data = NULL; + priv->metadata = NULL; } diff --git a/src/uca-ring-buffer.h b/src/uca-ring-buffer.h index 9fcf3b61..d34e8a3d 100644 --- a/src/uca-ring-buffer.h +++ b/src/uca-ring-buffer.h @@ -35,8 +35,8 @@ gsize uca_ring_buffer_get_block_size (UcaRingBuffer *buffer); 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); +void uca_ring_buffer_get_read_pointer (UcaRingBuffer *buffer, gpointer image, gpointer metadata); +void uca_ring_buffer_get_write_pointer(UcaRingBuffer *buffer, gpointer image, gpointer metadata); void uca_ring_buffer_write_advance (UcaRingBuffer *buffer); gpointer uca_ring_buffer_get_pointer (UcaRingBuffer *buffer, guint index); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0e8cfadd..80e33cde 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gtester.xsl ${CMAKE_CURRENT_BINARY_DIR}/gtester.xsl) diff --git a/test/test-mock.c b/test/test-mock.c index 2efc5438..69ac51e7 100644 --- a/test/test-mock.c +++ b/test/test-mock.c @@ -183,6 +183,49 @@ test_recording_buffered (Fixture *fixture, gconstpointer data) g_free (buffer); } +static void +test_metadata (Fixture *fixture, gconstpointer data) +{ + UcaCamera *camera = UCA_CAMERA (fixture->camera); + GError *error = NULL; + guint width, height, bitdepth; + gsize buffer_size; + gchar *buffer; + GHashTable *metadata = g_hash_table_new (g_str_hash, g_str_equal); + + g_object_get (G_OBJECT (camera), + "roi-width", &width, + "roi-height", &height, + "sensor-bitdepth", &bitdepth, + NULL); + + buffer_size = width * height * (bitdepth <= 8 ? 1 : 2); + buffer = g_malloc0 (buffer_size); + + g_object_set (G_OBJECT (camera), + "buffered", FALSE, + NULL); + + uca_camera_start_recording (camera, &error); + g_assert_no_error (error); + + for (int i = 0; i < 10; i++) { + g_assert (uca_camera_grab_with_metadata (camera, (gpointer) buffer,(gpointer) metadata ,&error)); + g_assert_no_error (error); + g_assert(metadata != NULL); + g_assert (g_hash_table_size (metadata) > 0); + g_assert (g_hash_table_contains (metadata, "timestamp")); + g_assert (g_hash_table_contains (metadata, "frame_number")); + const guint f = *(guint *) g_hash_table_lookup(metadata, "frame_number"); + g_assert (f == i); + } + + uca_camera_stop_recording (camera, &error); + g_assert_no_error (error); + + g_free (buffer); +} + static void test_base_properties (Fixture *fixture, gconstpointer data) @@ -339,6 +382,7 @@ int main (int argc, char *argv[]) {"/recording/signal", test_recording_signal}, {"/recording/asynchronous", test_recording_async}, {"/recording/buffered", test_recording_buffered}, + {"/recording/metadata", test_metadata}, {"/properties/base", test_base_properties}, {"/properties/recording", test_recording_property}, {"/properties/frames-per-second", test_fps_property}, diff --git a/test/test-ring-buffer.c b/test/test-ring-buffer.c index e868cd4e..a9fbf357 100644 --- a/test/test-ring-buffer.c +++ b/test/test-ring-buffer.c @@ -14,7 +14,10 @@ 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_write_pointer (buffer) != NULL); + gpointer image; + gpointer metadata; + uca_ring_buffer_get_write_pointer (buffer,image,metadata); + g_assert (image != NULL); g_object_unref (buffer); } @@ -28,7 +31,9 @@ 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_write_pointer (buffer) != NULL); + gpointer image, metadata; + uca_ring_buffer_get_write_pointer (buffer, image, metadata); + g_assert (image != NULL); g_object_unref (buffer); } @@ -38,26 +43,26 @@ test_ring (void) { UcaRingBuffer *buffer; guint32 *data; - + gpointer metadata; buffer = uca_ring_buffer_new (512, 2); - data = uca_ring_buffer_get_write_pointer (buffer); + uca_ring_buffer_get_write_pointer (buffer, data, metadata); data[0] = 0xBADF00D; uca_ring_buffer_write_advance (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); + uca_ring_buffer_get_write_pointer (buffer, data, metadata); data[0] = 0xDEADBEEF; uca_ring_buffer_write_advance (buffer); g_assert (uca_ring_buffer_get_num_blocks (buffer) == 2); - data = uca_ring_buffer_get_read_pointer (buffer); + uca_ring_buffer_get_read_pointer (buffer, data, metadata); g_assert (data[0] == 0xBADF00D); - data = uca_ring_buffer_get_read_pointer (buffer); + uca_ring_buffer_get_read_pointer (buffer, data, metadata); g_assert (data[0] == 0xDEADBEEF); g_assert (!uca_ring_buffer_available (buffer)); @@ -71,18 +76,18 @@ test_overwrite (void) { UcaRingBuffer *buffer; guint32 *data; - + gpointer metadata; buffer = uca_ring_buffer_new (512, 1); - data = uca_ring_buffer_get_write_pointer (buffer); + uca_ring_buffer_get_write_pointer (buffer, data, metadata); data[0] = 0xBADF00D; uca_ring_buffer_write_advance (buffer); - data = uca_ring_buffer_get_write_pointer (buffer); + uca_ring_buffer_get_write_pointer (buffer, data, metadata); data[0] = 0xDEADBEEF; uca_ring_buffer_write_advance (buffer); - data = uca_ring_buffer_get_read_pointer (buffer); + uca_ring_buffer_get_read_pointer (buffer, data, metadata); g_assert (data[0] == 0xDEADBEEF); }