From f200da9c7915521f77c6c23e825181da73db474d Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 28 Feb 2011 11:09:43 +0100 Subject: Add support for multiple cameras --- src/cameras/uca_pco.c | 72 +++++++++++++++++++++-------------------- src/cameras/uca_pco.h | 4 +-- src/uca.c | 89 +++++++++++++++++++++++++++++---------------------- src/uca.h | 68 +++++++++++++++++++++------------------ test/test.c | 66 +++++++++++++++++++++----------------- 5 files changed, 162 insertions(+), 137 deletions(-) diff --git a/src/cameras/uca_pco.c b/src/cameras/uca_pco.c index 33b09d6..8a89fa0 100644 --- a/src/cameras/uca_pco.c +++ b/src/cameras/uca_pco.c @@ -19,73 +19,73 @@ struct pco_cam_t { #define set_void(p, type, value) { *((type *) p) = value; } -static uint32_t uca_pco_set_bitdepth(struct uca_t *uca, uint8_t *bitdepth) +static uint32_t uca_pco_set_bitdepth(struct uca_camera_t *cam, uint8_t *bitdepth) { /* TODO: it's not possible via CameraLink so do it via frame grabber */ return 0; } -static uint32_t uca_pco_set_exposure(struct uca_t *uca, uint32_t *exposure) +static uint32_t uca_pco_set_exposure(struct uca_camera_t *cam, uint32_t *exposure) { uint32_t e, d; - if (pco_get_delay_exposure(GET_PCO(uca), &d, &e) != PCO_NOERROR) + if (pco_get_delay_exposure(GET_PCO(cam), &d, &e) != PCO_NOERROR) return UCA_ERR_PROP_GENERAL; - if (pco_set_delay_exposure(GET_PCO(uca), d, *exposure) != PCO_NOERROR) + if (pco_set_delay_exposure(GET_PCO(cam), d, *exposure) != PCO_NOERROR) return UCA_ERR_PROP_GENERAL; return UCA_NO_ERROR; } -static uint32_t uca_pco_set_delay(struct uca_t *uca, uint32_t *delay) +static uint32_t uca_pco_set_delay(struct uca_camera_t *cam, uint32_t *delay) { uint32_t e, d; - if (pco_get_delay_exposure(GET_PCO(uca), &d, &e) != PCO_NOERROR) + if (pco_get_delay_exposure(GET_PCO(cam), &d, &e) != PCO_NOERROR) return UCA_ERR_PROP_GENERAL; - if (pco_set_delay_exposure(GET_PCO(uca), *delay, e) != PCO_NOERROR) + if (pco_set_delay_exposure(GET_PCO(cam), *delay, e) != PCO_NOERROR) return UCA_ERR_PROP_GENERAL; return UCA_NO_ERROR; } -static uint32_t uca_pco_acquire_image(struct uca_t *uca, void *buffer) +static uint32_t uca_pco_acquire_image(struct uca_camera_t *cam, void *buffer) { return UCA_NO_ERROR; } -static uint32_t uca_pco_destroy(struct uca_t *uca) +static uint32_t uca_pco_destroy(struct uca_camera_t *cam) { - Fg_FreeGrabber(GET_FG(uca)); - pco_destroy(GET_PCO(uca)); - free(uca->user); + Fg_FreeGrabber(GET_FG(cam)); + pco_destroy(GET_PCO(cam)); + free(cam->user); return UCA_NO_ERROR; } -static uint32_t uca_pco_set_property(struct uca_t *uca, int32_t property, void *data) +static uint32_t uca_pco_set_property(struct uca_camera_t *cam, int32_t property, void *data) { switch (property) { case UCA_PROP_WIDTH: - if (Fg_setParameter(GET_FG(uca), FG_WIDTH, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_setParameter(GET_FG(cam), FG_WIDTH, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_VALUE_OUT_OF_RANGE; break; case UCA_PROP_HEIGHT: - if (Fg_setParameter(GET_FG(uca), FG_HEIGHT, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_setParameter(GET_FG(cam), FG_HEIGHT, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_VALUE_OUT_OF_RANGE; break; case UCA_PROP_X_OFFSET: - if (Fg_setParameter(GET_FG(uca), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_setParameter(GET_FG(cam), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_VALUE_OUT_OF_RANGE; break; case UCA_PROP_Y_OFFSET: - if (Fg_setParameter(GET_FG(uca), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_setParameter(GET_FG(cam), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_VALUE_OUT_OF_RANGE; break; case UCA_PROP_EXPOSURE: - return uca_pco_set_exposure(uca, (uint32_t *) data); + return uca_pco_set_exposure(cam, (uint32_t *) data); case UCA_PROP_DELAY: - return uca_pco_set_delay(uca, (uint32_t *) data); + return uca_pco_set_delay(cam, (uint32_t *) data); default: return UCA_ERR_PROP_INVALID; @@ -94,9 +94,9 @@ static uint32_t uca_pco_set_property(struct uca_t *uca, int32_t property, void * } -static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void *data) +static uint32_t uca_pco_get_property(struct uca_camera_t *cam, int32_t property, void *data) { - struct pco_edge_t *pco = GET_PCO(uca); + struct pco_edge_t *pco = GET_PCO(cam); switch (property) { case UCA_PROP_NAME: @@ -141,12 +141,12 @@ static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void * break; case UCA_PROP_X_OFFSET: - if (Fg_getParameter(GET_FG(uca), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_getParameter(GET_FG(cam), FG_XOFFSET, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_GENERAL; break; case UCA_PROP_Y_OFFSET: - if (Fg_getParameter(GET_FG(uca), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK) + if (Fg_getParameter(GET_FG(cam), FG_YOFFSET, (uint32_t *) data, PORT_A) != FG_OK) return UCA_ERR_PROP_GENERAL; break; @@ -176,37 +176,39 @@ static uint32_t uca_pco_get_property(struct uca_t *uca, int32_t property, void * return UCA_NO_ERROR; } -uint32_t uca_pco_alloc(struct uca_t *uca, uint32_t n_buffers) +uint32_t uca_pco_alloc(struct uca_camera_t *cam, uint32_t n_buffers) { } -uint32_t uca_pco_init(struct uca_t *uca) +uint32_t uca_pco_init(struct uca_camera_t **cam) { - uca->user = (struct pco_cam_t *) malloc(sizeof(struct pco_cam_t)); - - struct pco_cam_t *pco_cam = uca->user; + struct pco_cam_t *pco_cam = (struct pco_cam_t *) malloc(sizeof(struct pco_cam_t)); struct pco_edge_t *pco = pco_cam->pco = pco_init(); if (pco == NULL) { - free(uca->user); + free(pco_cam); return UCA_ERR_INIT_NOT_FOUND; } if ((pco->serial_ref == NULL) || !pco_active(pco)) { - free(uca->user); + free(pco_cam); pco_destroy(pco); return UCA_ERR_INIT_NOT_FOUND; } Fg_Struct *fg = pco_cam->fg = Fg_Init("libFullAreaGray8.so", 0); + struct uca_camera_t *uca = (struct uca_camera_t *) malloc(sizeof(struct uca_camera_t)); + uca->user = pco_cam; + *cam = uca; + /* Camera found, set function pointers... */ - uca->cam_destroy = &uca_pco_destroy; - uca->cam_set_property = &uca_pco_set_property; - uca->cam_get_property = &uca_pco_get_property; - uca->cam_alloc = &uca_pco_alloc; - uca->cam_acquire_image = &uca_pco_acquire_image; + uca->destroy = &uca_pco_destroy; + uca->set_property = &uca_pco_set_property; + uca->get_property = &uca_pco_get_property; + uca->alloc = &uca_pco_alloc; + uca->acquire_image = &uca_pco_acquire_image; /* Prepare camera for recording */ pco_set_rec_state(pco, 0); diff --git a/src/cameras/uca_pco.h b/src/cameras/uca_pco.h index 07c3ef2..240e675 100644 --- a/src/cameras/uca_pco.h +++ b/src/cameras/uca_pco.h @@ -1,8 +1,8 @@ #ifndef __UNIFIED_CAMERA_ACCESS_PCO_H #define __UNIFIED_CAMERA_ACCESS_PCO_H -struct uca_t; +struct uca_camera_t; -uint32_t uca_pco_init(struct uca_t *uca); +uint32_t uca_pco_init(struct uca_camera_t **uca); #endif diff --git a/src/uca.c b/src/uca.c index 73dd79e..0e9e184 100644 --- a/src/uca.c +++ b/src/uca.c @@ -19,6 +19,7 @@ struct uca_t *uca_init() { struct uca_t *uca = (struct uca_t *) malloc(sizeof(struct uca_t)); + uca->cameras = NULL; uca_cam_init inits[] = { #ifdef HAVE_PCO_EDGE @@ -32,58 +33,70 @@ struct uca_t *uca_init() #endif NULL }; - /* Set all function pointers to NULL and thus make the class abstract */ - uca->cam_set_property = NULL; - uca->cam_get_property = NULL; - uca->cam_alloc = NULL; - uca->cam_acquire_image = NULL; - int i = 0; + struct uca_camera_t* current = NULL; + while (inits[i] != NULL) { + struct uca_camera_t *cam = NULL; uca_cam_init init = inits[i]; - if (init(uca) != UCA_ERR_INIT_NOT_FOUND) - return uca; + if (init(&cam) != UCA_ERR_INIT_NOT_FOUND) { + if (current == NULL) + uca->cameras = current = cam; + else { + current->next = cam; + current = cam; + } + current->next = NULL; + } i++; } - /* No camera found then indicate error */ - free(uca); - return NULL; + if (uca->cameras == NULL) { + free(uca); + return NULL; + } + return uca; } void uca_destroy(struct uca_t *uca) { if (uca != NULL) { - uca->cam_destroy(uca); + struct uca_camera_t *current = uca->cameras, *tmp; + while (current != NULL) { + tmp = current; + current->destroy(current); + current = current->next; + free(tmp); + } free(uca); } } -static struct uca_property_t property_map[UCA_PROP_LAST] = { - { "name", uca_na, uca_string }, - { "width", uca_pixel, uca_uint32t }, - { "width.min", uca_pixel, uca_uint32t }, - { "width.max", uca_pixel, uca_uint32t }, - { "height", uca_pixel, uca_uint32t }, - { "height.min", uca_pixel, uca_uint32t }, - { "height.max", uca_pixel, uca_uint32t }, - { "offset.x", uca_pixel, uca_uint32t }, - { "offset.y", uca_pixel, uca_uint32t }, - { "bit-depth", uca_pixel, uca_uint8t }, - { "exposure", uca_us, uca_uint32t }, - { "exposure.min", uca_ns, uca_uint32t }, - { "exposure.max", uca_ms, uca_uint32t }, - { "delay", uca_us, uca_uint32t }, - { "delay.min", uca_ns, uca_uint32t }, - { "delay.max", uca_ms, uca_uint32t }, - { "frame-rate", uca_na, uca_uint32t }, - { "trigger-mode", uca_na, uca_uint32t }, - { "timestamp-mode", uca_na, uca_uint32t }, - { "scan-mode", uca_na, uca_uint32t }, - { "interlace.sample-rate", uca_na, uca_uint32t }, +static struct uca_property_t property_map[UCA_PROP_LAST+1] = { + { "name", uca_na, uca_string }, + { "width", uca_pixel, uca_uint32t }, + { "width.min", uca_pixel, uca_uint32t }, + { "width.max", uca_pixel, uca_uint32t }, + { "height", uca_pixel, uca_uint32t }, + { "height.min", uca_pixel, uca_uint32t }, + { "height.max", uca_pixel, uca_uint32t }, + { "offset.x", uca_pixel, uca_uint32t }, + { "offset.y", uca_pixel, uca_uint32t }, + { "bitdepth", uca_bits, uca_uint8t }, + { "exposure", uca_us, uca_uint32t }, + { "exposure.min", uca_ns, uca_uint32t }, + { "exposure.max", uca_ms, uca_uint32t }, + { "delay", uca_us, uca_uint32t }, + { "delay.min", uca_ns, uca_uint32t }, + { "delay.max", uca_ms, uca_uint32t }, + { "framerate", uca_na, uca_uint32t }, + { "triggermode", uca_na, uca_uint32t }, + { "timestampmode", uca_na, uca_uint32t }, + { "scan-mode", uca_na, uca_uint32t }, + { "interlace.samplerate", uca_na, uca_uint32t }, { "interlace.threshold.pixel", uca_na, uca_uint32t }, { "interlace.threshold.row", uca_na, uca_uint32t }, - { "correction-mode", uca_na, uca_uint32t }, + { "correctionmode", uca_na, uca_uint32t }, { NULL, 0, 0 } }; @@ -96,7 +109,7 @@ int32_t uca_get_property_id(const char *property_name) return i; i++; } - return UCA_PROP_INVALID; + return UCA_ERR_PROP_INVALID; } struct uca_property_t *uca_get_full_property(int32_t property_id) @@ -108,6 +121,6 @@ struct uca_property_t *uca_get_full_property(int32_t property_id) const char* uca_get_property_name(int32_t property_id) { - /* TODO: guard that thing */ - return property_map[property_id].name; + if ((property_id >= 0) && (property_id < UCA_PROP_LAST)) + return property_map[property_id].name; } diff --git a/src/uca.h b/src/uca.h index bf0cc21..c067d9f 100644 --- a/src/uca.h +++ b/src/uca.h @@ -14,18 +14,19 @@ #include struct uca_t; +struct uca_camera_t; struct uca_property_t; /** * \brief Camera probing and initialization * \return UCA_ERR_INIT_NOT_FOUND if camera is not found or could not be initialized */ -typedef uint32_t (*uca_cam_init) (struct uca_t *uca); +typedef uint32_t (*uca_cam_init) (struct uca_camera_t **cam); /** * \brief Free camera resouces */ -typedef uint32_t (*uca_cam_destroy) (struct uca_t *uca); +typedef uint32_t (*uca_cam_destroy) (struct uca_camera_t *cam); /** * \brief Set a property @@ -33,31 +34,31 @@ typedef uint32_t (*uca_cam_destroy) (struct uca_t *uca); * \return UCA_ERR_PROP_INVALID if property is not supported on the camera or * UCA_ERR_PROP_VALUE_OUT_OF_RANGE if value cannot be set. */ -typedef uint32_t (*uca_cam_set_property) (struct uca_t *uca, int32_t property, void *data); +typedef uint32_t (*uca_cam_set_property) (struct uca_camera_t *cam, int32_t property, void *data); /** * \brief Set a property * \param[in] property_name Name of the property as defined in XXX * \return UCA_ERR_PROP_INVALID if property is not supported on the camera */ -typedef uint32_t (*uca_cam_get_property) (struct uca_t *uca, int32_t property, void *data); +typedef uint32_t (*uca_cam_get_property) (struct uca_camera_t *cam, int32_t property, void *data); /** \brief Allocate number of buffers * * The size of each buffer is width x height x bits */ -typedef uint32_t (*uca_cam_alloc) (struct uca_t *uca, uint32_t n_buffers); +typedef uint32_t (*uca_cam_alloc) (struct uca_camera_t *cam, uint32_t n_buffers); /** * \brief Acquire one frame */ -typedef uint32_t (*uca_cam_acquire_image) (struct uca_t *uca, void *buffer); +typedef uint32_t (*uca_cam_acquire_image) (struct uca_camera_t *cam, void *buffer); /** * \brief Initialize the unified camera access interface * \return Pointer to a uca_t structure */ -struct uca_t *uca_init(); +struct uca_t *uca_init(void); /** * \brief Free resources of the unified camera access interface @@ -85,7 +86,6 @@ struct uca_property_t *uca_get_full_property(int32_t property_id); /* The property IDs must start with 0 and must be continuous. Whenever this * library is released, the IDs must not change to guarantee binary compatibility! */ -#define UCA_PROP_INVALID -1 #define UCA_PROP_NAME 0 #define UCA_PROP_WIDTH 1 #define UCA_PROP_WIDTH_MIN 2 @@ -95,31 +95,29 @@ struct uca_property_t *uca_get_full_property(int32_t property_id); #define UCA_PROP_HEIGHT_MAX 6 #define UCA_PROP_X_OFFSET 7 #define UCA_PROP_Y_OFFSET 8 -#define UCA_PROP_MAX_WIDTH 9 -#define UCA_PROP_MAX_HEIGHT 10 -#define UCA_PROP_BITDEPTH 11 -#define UCA_PROP_EXPOSURE 12 -#define UCA_PROP_EXPOSURE_MIN 13 -#define UCA_PROP_EXPOSURE_MAX 14 -#define UCA_PROP_DELAY 15 -#define UCA_PROP_DELAY_MIN 16 -#define UCA_PROP_DELAY_MAX 17 -#define UCA_PROP_FRAMERATE 18 -#define UCA_PROP_TRIGGER_MODE 19 +#define UCA_PROP_BITDEPTH 9 +#define UCA_PROP_EXPOSURE 10 +#define UCA_PROP_EXPOSURE_MIN 11 +#define UCA_PROP_EXPOSURE_MAX 12 +#define UCA_PROP_DELAY 13 +#define UCA_PROP_DELAY_MIN 14 +#define UCA_PROP_DELAY_MAX 15 +#define UCA_PROP_FRAMERATE 16 +#define UCA_PROP_TRIGGER_MODE 17 /* pco.edge specific */ -#define UCA_PROP_TIMESTAMP_MODE 20 -#define UCA_PROP_SCAN_MODE 21 +#define UCA_PROP_TIMESTAMP_MODE 18 +#define UCA_PROP_SCAN_MODE 19 /* IPE camera specific */ -#define UCA_PROP_INTERLACE_SAMPLE_RATE 22 -#define UCA_PROP_INTERLACE_PIXEL_THRESH 23 -#define UCA_PROP_INTERLACE_ROW_THRESH 24 +#define UCA_PROP_INTERLACE_SAMPLE_RATE 20 +#define UCA_PROP_INTERLACE_PIXEL_THRESH 21 +#define UCA_PROP_INTERLACE_ROW_THRESH 22 /* Photon Focus specific */ -#define UCA_PROP_CORRECTION_MODE 25 +#define UCA_PROP_CORRECTION_MODE 23 -#define UCA_PROP_LAST 26 +#define UCA_PROP_LAST 24 /* Possible timestamp modes for UCA_PROP_TIMESTAMP_MODE */ #define UCA_TIMESTAMP_ASCII 0x01 @@ -156,18 +154,24 @@ struct uca_property_t { } type; }; -struct uca_t { +struct uca_camera_t { + struct uca_camera_t *next; + /* Function pointers to camera-specific methods */ - uca_cam_set_property cam_set_property; - uca_cam_get_property cam_get_property; - uca_cam_acquire_image cam_acquire_image; - uca_cam_alloc cam_alloc; + uca_cam_set_property set_property; + uca_cam_get_property get_property; + uca_cam_acquire_image acquire_image; + uca_cam_alloc alloc; /* Private */ - uca_cam_destroy cam_destroy; + uca_cam_destroy destroy; void *user; /**< private user data to be used by the camera driver */ }; +struct uca_t { + struct uca_camera_t *cameras; +}; + #endif diff --git a/test/test.c b/test/test.c index 0f5b6fe..e3d07ff 100644 --- a/test/test.c +++ b/test/test.c @@ -26,44 +26,50 @@ int main(int argc, char *argv[]) return 1; } + /* take first camera */ + struct uca_camera_t *cam = uca->cameras; + char string_value[256]; uint32_t uint32_value; uint8_t uint8_value; const char *unit_map[] = { - "px", - "bits", - "ns", - "µs", - "ms", - "s", - "rows", - "" + "px", "bits", + "ns", "µs", "ms", "s", + "rows", "" }; - for (int i = 0; i < UCA_PROP_LAST-2; i++) { - struct uca_property_t *prop = uca_get_full_property(i); - switch (prop->type) { - case uca_string: - if (uca->cam_get_property(uca, i, string_value) != UCA_PROP_INVALID) { - print_level(count_dots(prop->name)); - printf("%s = %s %s ", prop->name, string_value, unit_map[prop->unit]); - } - break; - case uca_uint32t: - if (uca->cam_get_property(uca, i, &uint32_value) != UCA_PROP_INVALID) { - print_level(count_dots(prop->name)); - printf("%s = %i %s ", prop->name, uint32_value, unit_map[prop->unit]); - } - break; - case uca_uint8t: - if (uca->cam_get_property(uca, i, &uint8_value) != UCA_PROP_INVALID) { - print_level(count_dots(prop->name)); - printf("%s = %i %s ", prop->name, uint8_value, unit_map[prop->unit]); - } - break; + while (cam != NULL) { + for (int i = 0; i < UCA_PROP_LAST; i++) { + struct uca_property_t *prop = uca_get_full_property(i); + print_level(count_dots(prop->name)); + printf("%s = ", prop->name); + switch (prop->type) { + case uca_string: + if (cam->get_property(cam, i, string_value) != UCA_ERR_PROP_INVALID) { + printf("%s ", string_value); + } + else + printf("n/a"); + break; + case uca_uint32t: + if (cam->get_property(cam, i, &uint32_value) != UCA_ERR_PROP_INVALID) { + printf("%i %s", uint32_value, unit_map[prop->unit]); + } + else + printf("n/a"); + break; + case uca_uint8t: + if (cam->get_property(cam, i, &uint8_value) != UCA_ERR_PROP_INVALID) { + printf("%i %s", uint8_value, unit_map[prop->unit]); + } + else + printf("n/a"); + break; + } + printf("\n"); } - printf("\n"); + cam = cam->next; } uca_destroy(uca); -- cgit v1.2.3