diff options
-rw-r--r-- | src/cameras/uca-mock-camera.c | 4 | ||||
-rw-r--r-- | src/cameras/uca-pco-camera.c | 109 | ||||
-rw-r--r-- | src/cameras/uca-pco-camera.h | 3 | ||||
-rw-r--r-- | src/uca-camera.c | 55 | ||||
-rw-r--r-- | src/uca-camera.h | 4 | ||||
-rw-r--r-- | test/CMakeLists.txt | 3 | ||||
-rw-r--r-- | test/grab.c | 73 | ||||
-rw-r--r-- | test/test-all.c | 38 |
8 files changed, 209 insertions, 80 deletions
diff --git a/src/cameras/uca-mock-camera.c b/src/cameras/uca-mock-camera.c index 9e74a01..0040e25 100644 --- a/src/cameras/uca-mock-camera.c +++ b/src/cameras/uca-mock-camera.c @@ -142,11 +142,11 @@ static void uca_mock_camera_stop_recording(UcaCamera *camera, GError **error) } } -static void uca_mock_camera_grab(UcaCamera *camera, gpointer data, GError **error) +static void uca_mock_camera_grab(UcaCamera *camera, gpointer *data, GError **error) { g_return_if_fail(UCA_IS_MOCK_CAMERA(camera)); UcaMockCameraPrivate *priv = UCA_MOCK_CAMERA_GET_PRIVATE(camera); - g_memmove(data, priv->dummy_data, priv->width * priv->height); + g_memmove(*data, priv->dummy_data, priv->width * priv->height); } static void uca_mock_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) diff --git a/src/cameras/uca-pco-camera.c b/src/cameras/uca-pco-camera.c index 3e1791a..83cdb68 100644 --- a/src/cameras/uca-pco-camera.c +++ b/src/cameras/uca-pco-camera.c @@ -16,6 +16,7 @@ Franklin St, Fifth Floor, Boston, MA 02110, USA */ #include <stdlib.h> +#include <string.h> #include <libpco/libpco.h> #include <libpco/sc2_defs.h> #include <fgrab_struct.h> @@ -32,6 +33,22 @@ g_object_unref(camobj); \ return NULL; \ } } + +#define FG_SET_ERROR(err, fg, err_type) \ + if (err != FG_OK) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + err_type, \ + "%s", Fg_getLastErrorDescription(fg)); \ + return; \ + } + +#define HANDLE_PCO_ERROR(err) \ + if ((err) != PCO_NOERROR) { \ + g_set_error(error, UCA_PCO_CAMERA_ERROR, \ + UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL,\ + "libpco error %i", err); \ + return; \ + } #define UCA_PCO_CAMERA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UCA_TYPE_PCO_CAMERA, UcaPcoCameraPrivate)) @@ -44,6 +61,7 @@ G_DEFINE_TYPE(UcaPcoCamera, uca_pco_camera, UCA_TYPE_CAMERA) * @UCA_PCO_CAMERA_ERROR_UNSUPPORTED: Camera type is not supported * @UCA_PCO_CAMERA_ERROR_FG_INIT: Framegrabber initialization failed * @UCA_PCO_CAMERA_ERROR_FG_GENERAL: General framegrabber error + * @UCA_PCO_CAMERA_ERROR_FG_ACQUISITION: Framegrabber acquisition error */ GQuark uca_pco_camera_error_quark() { @@ -96,6 +114,24 @@ typedef struct { gboolean has_camram; } pco_cl_map_entry; +struct _UcaPcoCameraPrivate { + pco_handle pco; + pco_cl_map_entry *camera_description; + + Fg_Struct *fg; + guint fg_port; + dma_mem *fg_mem; + + guint frame_width; + guint frame_height; + gsize num_bytes; + + guint16 width; + guint16 height; + GValueArray *horizontal_binnings; + GValueArray *vertical_binnings; +}; + static pco_cl_map_entry pco_cl_map[] = { { CAMERATYPE_PCO_EDGE, "libFullAreaGray8.so", FG_CL_8BIT_FULL_10, FG_GRAY, 30.0f, FALSE }, { CAMERATYPE_PCO4000, "libDualAreaGray16.so", FG_CL_SINGLETAP_16_BIT, FG_GRAY16, 5.0f, TRUE }, @@ -116,20 +152,6 @@ static pco_cl_map_entry *get_pco_cl_map_entry(int camera_type) return NULL; } -struct _UcaPcoCameraPrivate { - pco_handle pco; - pco_cl_map_entry *camera_description; - - Fg_Struct *fg; - guint fg_port; - dma_mem *fg_mem; - - guint16 width; - guint16 height; - GValueArray *horizontal_binnings; - GValueArray *vertical_binnings; -}; - static guint fill_binnings(UcaPcoCameraPrivate *priv) { uint16_t *horizontal = NULL; @@ -250,18 +272,71 @@ UcaPcoCamera *uca_pco_camera_new(GError **error) static void uca_pco_camera_start_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - pco_start_recording(UCA_PCO_CAMERA_GET_PRIVATE(camera)->pco); + guint err = PCO_NOERROR; + + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + /* + * Get the actual size of the frame that we are going to grab based on the + * currently selected region of interest. This size is fixed until recording + * has stopped. + */ + guint16 roi[4] = {0}; + err = pco_get_roi(priv->pco, roi); + priv->frame_width = roi[2] - roi[0]; + priv->frame_height = roi[3] - roi[1]; + priv->num_bytes = 2; + + Fg_setParameter(priv->fg, FG_WIDTH, &priv->frame_width, priv->fg_port); + Fg_setParameter(priv->fg, FG_HEIGHT, &priv->frame_height, priv->fg_port); + + if (priv->camera_description->camera_type == CAMERATYPE_PCO_DIMAX_STD) + pco_clear_active_segment(priv->pco); + + err = pco_arm_camera(priv->pco); + HANDLE_PCO_ERROR(err); + + err = pco_start_recording(priv->pco); + HANDLE_PCO_ERROR(err); + + err = Fg_AcquireEx(priv->fg, 0, GRAB_INFINITE, ACQ_STANDARD, priv->fg_mem); + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); } static void uca_pco_camera_stop_recording(UcaCamera *camera, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); - pco_stop_recording(UCA_PCO_CAMERA_GET_PRIVATE(camera)->pco); + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + pco_stop_recording(priv->pco); + guint err = Fg_stopAcquireEx(priv->fg, 0, priv->fg_mem, STOP_SYNC); + + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_ACQUISITION); } -static void uca_pco_camera_grab(UcaCamera *camera, gpointer data, GError **error) +static void uca_pco_camera_grab(UcaCamera *camera, gpointer *data, GError **error) { g_return_if_fail(UCA_IS_PCO_CAMERA(camera)); + static frameindex_t last_frame = 0; + UcaPcoCameraPrivate *priv = UCA_PCO_CAMERA_GET_PRIVATE(camera); + + pco_request_image(priv->pco); + + last_frame = Fg_getLastPicNumberBlockingEx(priv->fg, last_frame+1, priv->fg_port, 5, priv->fg_mem); + + if (last_frame <= 0) { + guint err = FG_OK + 1; + FG_SET_ERROR(err, priv->fg, UCA_PCO_CAMERA_ERROR_FG_GENERAL); + } + + guint16 *frame = Fg_getImagePtrEx(priv->fg, last_frame, PORT_A, priv->fg_mem); + + if (*data == NULL) + *data = g_malloc0(priv->frame_width * priv->frame_height * priv->num_bytes); + + if (priv->camera_description->camera_type == CAMERATYPE_PCO_EDGE) + pco_get_reorder_func(priv->pco)((guint16 *) *data, frame, priv->frame_width, priv->frame_height); + else + memcpy((gchar *) *data, (gchar *) frame, priv->frame_width * priv->frame_height * priv->num_bytes); } static void uca_pco_camera_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) diff --git a/src/cameras/uca-pco-camera.h b/src/cameras/uca-pco-camera.h index 25009c0..c0b7bf4 100644 --- a/src/cameras/uca-pco-camera.h +++ b/src/cameras/uca-pco-camera.h @@ -34,7 +34,8 @@ typedef enum { UCA_PCO_CAMERA_ERROR_LIBPCO_GENERAL, UCA_PCO_CAMERA_ERROR_UNSUPPORTED, UCA_PCO_CAMERA_ERROR_FG_INIT, - UCA_PCO_CAMERA_ERROR_FG_GENERAL + UCA_PCO_CAMERA_ERROR_FG_GENERAL, + UCA_PCO_CAMERA_ERROR_FG_ACQUISITION } UcaPcoCameraError; typedef struct _UcaPcoCamera UcaPcoCamera; diff --git a/src/uca-camera.c b/src/uca-camera.c index 97215bb..2d2963b 100644 --- a/src/uca-camera.c +++ b/src/uca-camera.c @@ -67,6 +67,10 @@ enum { PROP_SENSOR_VERTICAL_BINNING, PROP_SENSOR_VERTICAL_BINNINGS, PROP_SENSOR_MAX_FRAME_RATE, + PROP_ROI_X, + PROP_ROI_Y, + PROP_ROI_WIDTH, + PROP_ROI_HEIGHT, PROP_HAS_STREAMING, PROP_HAS_CAMRAM_RECORDING, PROP_TRANSFER_ASYNCHRONOUSLY, @@ -87,6 +91,11 @@ static void uca_camera_set_property(GObject *object, guint property_id, const GV { UcaCameraPrivate *priv = UCA_CAMERA_GET_PRIVATE(object); + if (priv->is_recording) { + g_warning("You cannot change properties during data acquisition"); + return; + } + switch (property_id) { case PROP_TRANSFER_ASYNCHRONOUSLY: priv->transfer_async = g_value_get_boolean(value); @@ -182,6 +191,34 @@ static void uca_camera_class_init(UcaCameraClass *klass) 1, G_MAXUINT, 1, G_PARAM_READABLE), G_PARAM_READABLE); + camera_properties[PROP_ROI_X] = + g_param_spec_uint("roi-x", + "Horizontal coordinate", + "Horizontal coordinate", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + camera_properties[PROP_ROI_Y] = + g_param_spec_uint("roi-y", + "Vertical coordinate", + "Vertical coordinate", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + camera_properties[PROP_ROI_WIDTH] = + g_param_spec_uint("roi-width", + "Width", + "Width of the region of interest", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + + camera_properties[PROP_ROI_HEIGHT] = + g_param_spec_uint("roi-height", + "Height", + "Height of the region of interest", + 1, G_MAXUINT, 1, + G_PARAM_READABLE); + camera_properties[PROP_SENSOR_MAX_FRAME_RATE] = g_param_spec_float("max-frame-rate", "Maximum frame rate", @@ -377,6 +414,7 @@ void uca_camera_stop_recording(UcaCamera *camera, GError **error) /** * uca_camera_set_grab_func: + * @camera: A #UcaCamera object * func: A #UcaCameraGrabFunc callback function * * Set the grab function that is called whenever a frame is readily transfered. @@ -387,7 +425,21 @@ void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointe camera->user_data = user_data; } -void uca_camera_grab(UcaCamera *camera, gpointer data, GError **error) +/** + * uca_camera_grab: + * @camera: A #UcaCamera object + * @data: Pointer to pointer to the data. Must not be %NULL. + * @error: Location to store a #UcaCameraError error or %NULL + * + * Grab a frame a single frame and store the result in @data. If the pointer + * pointing to the data is %NULL, memory will be allocated otherwise it will be + * used to store the frame. If memory is allocated by uca_camera_grab() it must + * be freed by the caller. + * + * You must have called uca_camera_start_recording() before, otherwise you will + * get a #UCA_CAMERA_ERROR_NOT_RECORDING error. + */ +void uca_camera_grab(UcaCamera *camera, gpointer *data, GError **error) { g_return_if_fail(UCA_IS_CAMERA(camera)); @@ -395,6 +447,7 @@ void uca_camera_grab(UcaCamera *camera, gpointer data, GError **error) g_return_if_fail(klass != NULL); g_return_if_fail(klass->grab != NULL); + g_return_if_fail(data != NULL); if (!camera->priv->is_recording) { g_set_error(error, UCA_CAMERA_ERROR, UCA_CAMERA_ERROR_NOT_RECORDING, diff --git a/src/uca-camera.h b/src/uca-camera.h index a540d16..c10173b 100644 --- a/src/uca-camera.h +++ b/src/uca-camera.h @@ -71,7 +71,7 @@ struct _UcaCameraClass { void (*start_recording) (UcaCamera *camera, GError **error); void (*stop_recording) (UcaCamera *camera, GError **error); - void (*grab) (UcaCamera *camera, gpointer data, GError **error); + void (*grab) (UcaCamera *camera, gpointer *data, GError **error); void (*recording_started) (UcaCamera *camera); void (*recording_stopped) (UcaCamera *camera); @@ -82,7 +82,7 @@ UcaCamera *uca_camera_new(const gchar *type, GError **error); void uca_camera_start_recording(UcaCamera *camera, GError **error); void uca_camera_stop_recording(UcaCamera *camera, GError **error); -void uca_camera_grab(UcaCamera *camera, gpointer data, GError **error); +void uca_camera_grab(UcaCamera *camera, gpointer *data, GError **error); void uca_camera_set_grab_func(UcaCamera *camera, UcaCameraGrabFunc func, gpointer user_data); GType uca_camera_get_type(void); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e2e0d5..c14e7ce 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,11 +15,12 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/run.py ${CMAKE_CURRENT_BINARY_DIR}) # --- Build targets ----------------------------------------------------------- #add_executable(enum enum.c) +add_executable(grab grab.c) #add_executable(grab-async grab-async.c) #add_executable(benchmark benchmark.c) #target_link_libraries(enum uca) -#target_link_libraries(grab uca) +target_link_libraries(grab uca-gobject) #target_link_libraries(grab-async uca) #target_link_libraries(benchmark uca) diff --git a/test/grab.c b/test/grab.c index 740522b..56b7cd6 100644 --- a/test/grab.c +++ b/test/grab.c @@ -15,80 +15,69 @@ with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ +#include <glib-object.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include "uca.h" +#include "uca-camera.h" #define handle_error(errno) {if ((errno) != UCA_NO_ERROR) printf("error at <%s:%i>\n", \ __FILE__, __LINE__);} -uca *u = NULL; +static UcaCamera *camera = NULL; void sigint_handler(int signal) { printf("Closing down libuca\n"); - handle_error(uca_cam_stop_recording(u->cameras)); - uca_destroy(u); + uca_camera_stop_recording(camera, NULL); + g_object_unref(camera); exit(signal); } int main(int argc, char *argv[]) { + GError *error = NULL; (void) signal(SIGINT, sigint_handler); - u = uca_init(NULL); - if (u == NULL) { - printf("Couldn't find a camera\n"); + g_type_init(); + camera = uca_camera_new("pco", &error); + + if (camera == NULL) { + g_print("Couldn't initialize camera\n"); return 1; } - /* take first camera */ - uca_camera *cam = u->cameras; - - uint32_t val = 5000; - handle_error(uca_cam_set_property(cam, UCA_PROP_EXPOSURE, &val)); - val = 0; - handle_error(uca_cam_set_property(cam, UCA_PROP_DELAY, &val)); - val = UCA_TIMESTAMP_ASCII | UCA_TIMESTAMP_BINARY; - handle_error(uca_cam_set_property(cam, UCA_PROP_TIMESTAMP_MODE, &val)); - val = 1; - handle_error(uca_cam_set_property(cam, UCA_PROP_GRAB_AUTO, &val)); - - uint32_t width, height, bits; - handle_error(uca_cam_get_property(cam, UCA_PROP_WIDTH, &width, 0)); - handle_error(uca_cam_get_property(cam, UCA_PROP_HEIGHT, &height, 0)); - handle_error(uca_cam_get_property(cam, UCA_PROP_BITDEPTH, &bits, 0)); - - handle_error(uca_cam_alloc(cam, 20)); + guint width, height, bits; + g_object_get(G_OBJECT(camera), + "sensor-width", &width, + "sensor-height", &height, + "sensor-bitdepth", &bits, + NULL); const int pixel_size = bits == 8 ? 1 : 2; - uint16_t *buffer = (uint16_t *) malloc(width * height * pixel_size); + gpointer buffer = g_malloc0(width * height * pixel_size); - handle_error(uca_cam_start_recording(cam)); - /* sleep(3); */ + uca_camera_start_recording(camera, &error); - uint32_t error = UCA_NO_ERROR; - char filename[FILENAME_MAX]; - int counter = 0; + gchar filename[FILENAME_MAX]; + gint counter = 0; - while ((error == UCA_NO_ERROR) && (counter < 20)) { - printf(" grab frame ... "); - error = uca_cam_grab(cam, (char *) buffer, NULL); - if (error != UCA_NO_ERROR) + while (counter < 20) { + g_print(" grab frame ... "); + uca_camera_grab(camera, &buffer, &error); + if (error != NULL) break; - printf("done\n"); + g_print("done\n"); snprintf(filename, FILENAME_MAX, "frame-%08i.raw", counter++); FILE *fp = fopen(filename, "wb"); fwrite(buffer, width*height, pixel_size, fp); fclose(fp); } - handle_error(uca_cam_stop_recording(cam)); - uca_destroy(u); - free(buffer); + uca_camera_stop_recording(camera, &error); + g_object_unref(camera); + g_free(buffer); - return error != UCA_NO_ERROR ? 1 : 0; + return error != NULL ? 1 : 0; } diff --git a/test/test-all.c b/test/test-all.c index 3fb81e7..f6e3002 100644 --- a/test/test-all.c +++ b/test/test-all.c @@ -47,24 +47,16 @@ static void test_recording(Fixture *fixture, gconstpointer data) g_error_free(error); error = NULL; - uca_camera_start_recording(camera, &error); - g_assert_no_error(error); - uca_camera_stop_recording(camera, &error); - g_assert_no_error(error); -} - -static void test_recording_signal(Fixture *fixture, gconstpointer data) -{ - UcaCamera *camera = UCA_CAMERA(fixture->camera); gboolean success = FALSE; g_signal_connect(G_OBJECT(camera), "notify::is-recording", (GCallback) on_property_change, &success); - - uca_camera_start_recording(camera, NULL); + uca_camera_start_recording(camera, &error); + g_assert_no_error(error); g_assert(success == TRUE); success = FALSE; - uca_camera_stop_recording(camera, NULL); + uca_camera_stop_recording(camera, &error); + g_assert_no_error(error); g_assert(success == TRUE); } @@ -99,6 +91,24 @@ static void test_recording_async(Fixture *fixture, gconstpointer data) uca_camera_stop_recording(camera, &error); g_assert_no_error(error); + g_assert(success == TRUE); +} + +static void test_recording_grab(Fixture *fixture, gconstpointer data) +{ + UcaCamera *camera = UCA_CAMERA(fixture->camera); + GError *error = NULL; + gpointer frame = NULL; + + uca_camera_start_recording(camera, &error); + g_assert_no_error(error); + + uca_camera_grab(camera, &frame, &error); + g_assert_no_error(error); + g_assert(frame != NULL); + + uca_camera_stop_recording(camera, &error); + g_assert_no_error(error); } static void test_recording_property(Fixture *fixture, gconstpointer data) @@ -165,7 +175,7 @@ int main(int argc, char *argv[]) */ static const gchar *paths[] = { "/recording", - "/recording/signal", + "/recording/grab", "/recording/asynchronous", "/properties/base", "/properties/recording", @@ -175,7 +185,7 @@ int main(int argc, char *argv[]) static UcaFixtureFunc test_funcs[] = { test_recording, - test_recording_signal, + test_recording_grab, test_recording_async, test_base_properties, test_recording_property, |