summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cameras/uca-mock-camera.c4
-rw-r--r--src/cameras/uca-pco-camera.c109
-rw-r--r--src/cameras/uca-pco-camera.h3
-rw-r--r--src/uca-camera.c55
-rw-r--r--src/uca-camera.h4
-rw-r--r--test/CMakeLists.txt3
-rw-r--r--test/grab.c73
-rw-r--r--test/test-all.c38
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,