summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Vogelgesang <matthias.vogelgesang@ipe.fzk.de>2011-03-17 15:38:38 +0100
committerMatthias Vogelgesang <matthias.vogelgesang@ipe.fzk.de>2011-03-17 15:38:38 +0100
commit6de83f98c5f4d5fb696f413aa9dbe49ab4515661 (patch)
tree50095a8f5d39e6c2ad4fa91e06940873e9f1993c
parent65a2016becbb165afa4fdf16742f3586f83d0f30 (diff)
downloadlibuca-6de83f98c5f4d5fb696f413aa9dbe49ab4515661.tar.gz
libuca-6de83f98c5f4d5fb696f413aa9dbe49ab4515661.tar.bz2
libuca-6de83f98c5f4d5fb696f413aa9dbe49ab4515661.tar.xz
libuca-6de83f98c5f4d5fb696f413aa9dbe49ab4515661.zip
Expose grab-by-callback via camera and add asynchronous grabbing example
-rw-r--r--src/cameras/dummy.c248
-rw-r--r--src/uca-cam.h35
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/grab-async.c46
4 files changed, 240 insertions, 91 deletions
diff --git a/src/cameras/dummy.c b/src/cameras/dummy.c
index ba95a67..0177c6a 100644
--- a/src/cameras/dummy.c
+++ b/src/cameras/dummy.c
@@ -1,19 +1,144 @@
-
#include <stdlib.h>
#include <string.h>
+#define __USE_BSD
+#include <unistd.h>
+#undef __USE_BSD
+
+#include "config.h"
#include "uca.h"
#include "uca-cam.h"
#include "uca-grabber.h"
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+
+/**
+ * User structure for the dummy camera.
+ */
typedef struct dummy_cam {
uint32_t bitdepth;
- uint32_t framerate;
- char* buffer;
+ uint32_t frame_rate;
+#ifdef HAVE_PTHREADS
+ pthread_t grab_thread;
+ bool thread_running;
+ char *buffer;
+#endif
} dummy_cam_t;
+
+static const char digits[10][20] = {
+ /* 0 */
+ { 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00 },
+ /* 1 */
+ { 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0x00, 0xff, 0x00 },
+ /* 2 */
+ { 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff },
+ /* 3 */
+ { 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00 },
+ /* 4 */
+ { 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff },
+ /* 5 */
+ { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0x00 },
+ /* 6 */
+ { 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00 },
+ /* 7 */
+ { 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x00 },
+ /* 8 */
+ { 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0x00 },
+ /* 9 */
+ { 0x00, 0xff, 0xff, 0x00,
+ 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0x00 }
+};
+
+const int DIGIT_WIDTH = 4;
+const int DIGIT_HEIGHT = 5;
+
#define GET_DUMMY(uca) ((struct dummy_cam *)(uca->user))
#define set_void(p, type, value) { *((type *) p) = value; }
+static void uca_dummy_print_number(char *buffer, int number, int x, int y, int width)
+{
+ for (int i = 0; i < DIGIT_WIDTH; i++) {
+ for (int j = 0; j < DIGIT_HEIGHT; j++) {
+ buffer[(y+j)*width + (x+i)] = digits[number][j*DIGIT_WIDTH+i];
+ }
+ }
+}
+
+static void uca_dummy_memcpy(struct uca_camera *cam, char *buffer)
+{
+ /* print current frame number */
+ unsigned int number = cam->current_frame;
+ unsigned int divisor = 100000000;
+ int x = 10;
+ while (divisor > 1) {
+ uca_dummy_print_number(buffer, number / divisor, x, 10, cam->frame_width);
+ number = number % divisor;
+ divisor = divisor / 10;
+ x += 5;
+ }
+}
+
+static void *uca_dummy_grab_thread(void *arg)
+{
+ struct uca_camera *cam = ((struct uca_camera *) arg);
+ struct dummy_cam *dc = GET_DUMMY(cam);
+
+ const __useconds_t sleep_time = (unsigned int) 1000000.0f / dc->frame_rate;
+
+ while (dc->thread_running) {
+ uca_dummy_memcpy(cam, dc->buffer);
+ cam->callback(cam->current_frame, dc->buffer);
+ cam->current_frame++;
+ usleep(sleep_time);
+ }
+ return NULL;
+}
+
+
+/*
+ * --- interface implementations ----------------------------------------------
+ */
static uint32_t uca_dummy_set_property(struct uca_camera *cam, enum uca_property_ids property, void *data)
{
if (cam->state == UCA_CAM_RECORDING)
@@ -28,6 +153,10 @@ static uint32_t uca_dummy_set_property(struct uca_camera *cam, enum uca_property
cam->frame_height = *((uint32_t *) data);
break;
+ case UCA_PROP_FRAMERATE:
+ GET_DUMMY(cam)->frame_rate = *((uint32_t *) data);
+ break;
+
default:
return UCA_ERR_PROP_INVALID;
}
@@ -78,6 +207,15 @@ static uint32_t uca_dummy_get_property(struct uca_camera *cam, enum uca_property
uint32_t uca_dummy_start_recording(struct uca_camera *cam)
{
+ if (cam->callback != NULL) {
+#ifdef HAVE_PTHREADS
+ struct dummy_cam *dc = GET_DUMMY(cam);
+ /* FIXME: handle return value */
+ dc->thread_running = true;
+ dc->buffer = (char *) malloc(cam->frame_width * cam->frame_height);
+ pthread_create(&dc->grab_thread, NULL, &uca_dummy_grab_thread, cam);
+#endif
+ }
cam->current_frame = 0;
cam->state = UCA_CAM_RECORDING;
return UCA_NO_ERROR;
@@ -85,106 +223,37 @@ uint32_t uca_dummy_start_recording(struct uca_camera *cam)
uint32_t uca_dummy_stop_recording(struct uca_camera *cam)
{
+ if (cam->callback != NULL) {
+ GET_DUMMY(cam)->thread_running = false;
+ free(GET_DUMMY(cam)->buffer);
+ }
cam->state = UCA_CAM_ARMED;
return UCA_NO_ERROR;
}
-static const char digits[10][20] = {
- /* 0 */
- { 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0xff, 0x00, 0x00, 0xff,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0x00 },
- /* 1 */
- { 0x00, 0x00, 0xff, 0x00,
- 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0x00,
- 0x00, 0x00, 0xff, 0x00 },
- /* 2 */
- { 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0xff, 0x00,
- 0x00, 0xff, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff },
- /* 3 */
- { 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0x00 },
- /* 4 */
- { 0xff, 0x00, 0x00, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0xff },
- /* 5 */
- { 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00 },
- /* 6 */
- { 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0x00 },
- /* 7 */
- { 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0xff, 0x00,
- 0x00, 0xff, 0x00, 0x00,
- 0xff, 0x00, 0x00, 0x00 },
- /* 8 */
- { 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0x00 },
- /* 9 */
- { 0x00, 0xff, 0xff, 0x00,
- 0xff, 0x00, 0x00, 0xff,
- 0x00, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00 }
-};
-
-static void uca_dummy_print_number(struct dummy_cam *dummy, int number, int x, int y, int width)
+uint32_t uca_dummy_register_callback(struct uca_camera *cam, uca_cam_grab_callback cb)
{
- const int digit_width = 4;
- const int digit_height = 5;
- char *buffer = dummy->buffer;
- for (int i = 0; i < digit_width; i++) {
- for (int j = 0; j < digit_height; j++) {
- buffer[(y+j)*width + (x+i)] = digits[number][j*digit_width+i];
- }
- }
+ if (cam->callback == NULL)
+ cam->callback = cb;
+ else
+ return UCA_ERR_GRABBER_CALLBACK_ALREADY_REGISTERED;
+
+ return UCA_NO_ERROR;
}
uint32_t uca_dummy_grab(struct uca_camera *cam, char *buffer)
{
- struct dummy_cam *dummy = GET_DUMMY(cam);
- dummy->buffer = buffer;
+ if (cam->callback != NULL)
+ return UCA_ERR_GRABBER_CALLBACK_ALREADY_REGISTERED;
- /* print current frame number */
- unsigned int number = cam->current_frame;
- unsigned int divisor = 100000000;
- int x = 10;
- while (divisor > 1) {
- uca_dummy_print_number(dummy, number / divisor, x, 10, cam->frame_width);
- number = number % divisor;
- divisor = divisor / 10;
- x += 5;
- }
+ uca_dummy_memcpy(cam, buffer);
cam->current_frame++;
return UCA_NO_ERROR;
}
static uint32_t uca_dummy_destroy(struct uca_camera *cam)
{
+ free(GET_DUMMY(cam));
return UCA_NO_ERROR;
}
@@ -198,6 +267,8 @@ uint32_t uca_dummy_init(struct uca_camera **cam, struct uca_grabber *grabber)
uca->start_recording = &uca_dummy_start_recording;
uca->stop_recording = &uca_dummy_stop_recording;
uca->grab = &uca_dummy_grab;
+ uca->register_callback = &uca_dummy_register_callback;
+
uca->state = UCA_CAM_CONFIGURABLE;
uca->frame_width = 320;
uca->frame_height = 240;
@@ -205,8 +276,7 @@ uint32_t uca_dummy_init(struct uca_camera **cam, struct uca_grabber *grabber)
struct dummy_cam *dummy_cam = (struct dummy_cam *) malloc(sizeof(struct dummy_cam));
dummy_cam->bitdepth = 8;
- dummy_cam->framerate = 100;
- dummy_cam->buffer = NULL;
+ dummy_cam->frame_rate = 100;
uca->user = dummy_cam;
*cam = uca;
diff --git a/src/uca-cam.h b/src/uca-cam.h
index 822f011..ca80ec9 100644
--- a/src/uca-cam.h
+++ b/src/uca-cam.h
@@ -129,6 +129,28 @@ typedef uint32_t (*uca_cam_start_recording) (struct uca_camera *cam);
typedef uint32_t (*uca_cam_stop_recording) (struct uca_camera *cam);
/**
+ * Function pointer to a grab callback.
+ *
+ * Register such a callback function with uca_cam_register_callback() to
+ * receive data as soon as it is delivered.
+ *
+ * \param[in] image_number Current frame number
+ *
+ * \param[in] buffer Image data
+ */
+typedef void (*uca_cam_grab_callback) (uint32_t image_number, void *buffer);
+
+/**
+ * Register callback for given frame grabber. To actually start receiving
+ * frames, call uca_grabber_acquire().
+ *
+ * \param[in] grabber The grabber for which the callback should be installed
+ *
+ * \param[in] cb Callback function for when a frame arrived
+ */
+typedef uint32_t (*uca_cam_register_callback) (struct uca_camera *cam, uca_cam_grab_callback cb);
+
+/**
* \brief Grab one image from the camera
*
* The grabbing involves a memory copy because we might have to decode the image
@@ -182,6 +204,13 @@ typedef struct uca_camera {
*/
uca_cam_grab grab;
+ /**
+ * Method to register an frame acquisition callback.
+ *
+ * \see uca_cam_register_callback
+ */
+ uca_cam_register_callback register_callback;
+
/* Private */
/**
* Method to close the camera.
@@ -189,11 +218,13 @@ typedef struct uca_camera {
*/
uca_cam_destroy destroy;
- struct uca_grabber *grabber; /**< grabber associated with this camera */
- enum uca_cam_state state; /**< camera state */
+ /* private */
+ struct uca_grabber *grabber; /**< grabber associated with this camera */
+ enum uca_cam_state state; /**< camera state */
uint32_t frame_width; /**< current frame width */
uint32_t frame_height; /**< current frame height */
uint32_t current_frame; /**< last grabbed frame number */
+ uca_cam_grab_callback callback;
void *user; /**< private user data to be used by the camera driver */
} uca_camera_t;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3ea7414..287f9ea 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -15,9 +15,11 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/control.glade
# --- Build targets -----------------------------------------------------------
add_executable(enum enum.c)
add_executable(grab grab.c)
+add_executable(grab-async grab-async.c)
target_link_libraries(enum uca)
target_link_libraries(grab uca)
+target_link_libraries(grab-async uca)
if (GTK2_FOUND)
include_directories(${GTK2_INCLUDE_DIRS})
diff --git a/test/grab-async.c b/test/grab-async.c
new file mode 100644
index 0000000..8086d92
--- /dev/null
+++ b/test/grab-async.c
@@ -0,0 +1,46 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "uca.h"
+#include "uca-cam.h"
+
+void grab_callback(uint32_t image_number, void *buffer)
+{
+ printf("got picture number %i\n", image_number);
+}
+
+int main(int argc, char *argv[])
+{
+ struct uca *u = uca_init(NULL);
+ if (u == NULL) {
+ printf("Couldn't find a camera\n");
+ return 1;
+ }
+
+ /* take first camera */
+ struct uca_camera *cam = u->cameras;
+
+ uint32_t val = 1;
+ cam->set_property(cam, UCA_PROP_EXPOSURE, &val);
+ val = 0;
+ cam->set_property(cam, UCA_PROP_DELAY, &val);
+ val = 10;
+ cam->set_property(cam, UCA_PROP_FRAMERATE, &val);
+
+ uint32_t width, height, bits;
+ cam->get_property(cam, UCA_PROP_WIDTH, &width, 0);
+ cam->get_property(cam, UCA_PROP_HEIGHT, &height, 0);
+ cam->get_property(cam, UCA_PROP_BITDEPTH, &bits, 0);
+
+ uca_cam_alloc(cam, 10);
+
+ cam->register_callback(cam, &grab_callback);
+ cam->start_recording(cam);
+ printf("waiting for 10 seconds\n");
+ sleep(10);
+ cam->stop_recording(cam);
+
+ uca_destroy(u);
+ return 0;
+}