diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-02-22 23:27:15 +0100 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-04-16 23:40:56 +0200 |
commit | 211507d598b67e6e274275ab472d5e81ec1afcec (patch) | |
tree | 47d4ba219c740b85dd563e312083f2787016d0ec | |
parent | 4dd4dcb4f594c872df222390031975d06adc7e71 (diff) |
Factor event handling code out into events.c
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | events.c | 175 | ||||
-rw-r--r-- | events.h | 50 | ||||
-rw-r--r-- | live.c | 154 | ||||
-rw-r--r-- | snapshot.c | 153 |
5 files changed, 263 insertions, 273 deletions
@@ -6,8 +6,8 @@ CFLAGS := -O2 -W -Wall -I$(KDIR)/usr/include LDFLAGS := -Lisp LIBS := -lomap3isp -lrt -OBJ_LIVE := live.o videoout.o -OBJ_SNAP := snapshot.o +OBJ_LIVE := live.o events.o videoout.o +OBJ_SNAP := snapshot.o events.o %.o : %.c $(CC) $(CFLAGS) -c -o $@ $< diff --git a/events.c b/events.c new file mode 100644 index 0000000..461e641 --- /dev/null +++ b/events.c @@ -0,0 +1,175 @@ +/* + * OMAP3 generic events handling + * + * Copyright (C) 2010-2012 Ideas on board SPRL + * + * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _BSD_SOURCE +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/select.h> + +#include "isp/list.h" +#include "isp/omap3isp.h" +#include "isp/tools.h" + +#include "events.h" + +#define SELECT_TIMEOUT 2000 /* in milliseconds */ + +struct event_fd { + struct list_entry list; + + int fd; + enum omap3_isp_event_type type; + void (*callback)(void *priv); + void *priv; +}; + +void events_watch_fd(struct events *events, int fd, + enum omap3_isp_event_type type, + void(*callback)(void *), void *priv) +{ + struct event_fd *event; + + event = malloc(sizeof *event); + if (event == NULL) + return; + + event->fd = fd; + event->type = type; + event->callback = callback; + event->priv = priv; + + switch (event->type) { + case OMAP3_ISP_EVENT_READ: + FD_SET(fd, &events->rfds); + break; + case OMAP3_ISP_EVENT_WRITE: + FD_SET(fd, &events->wfds); + break; + } + + events->maxfd = max(events->maxfd, fd); + + list_append(&event->list, &events->events); +} + +void events_unwatch_fd(struct events *events, int fd) +{ + struct event_fd *event = NULL; + struct event_fd *entry; + int maxfd = 0; + + list_for_each_entry(entry, &events->events, list) { + if (entry->fd == fd) + event = entry; + else + maxfd = max(maxfd, entry->fd); + } + + if (event == NULL) + return; + + switch (event->type) { + case OMAP3_ISP_EVENT_READ: + FD_CLR(fd, &events->rfds); + break; + case OMAP3_ISP_EVENT_WRITE: + FD_CLR(fd, &events->wfds); + break; + } + + events->maxfd = maxfd; + + list_remove(&event->list); + free(event); +} + +static void events_dispatch(struct events *events, const fd_set *rfds, + const fd_set *wfds) +{ + struct event_fd *event; + + list_for_each_entry(event, &events->events, list) { + if (event->type == OMAP3_ISP_EVENT_READ && + FD_ISSET(event->fd, rfds)) + event->callback(event->priv); + if (event->type == OMAP3_ISP_EVENT_WRITE && + FD_ISSET(event->fd, wfds)) + event->callback(event->priv); + } +} + +bool events_loop(struct events *events) +{ + while (!events->done) { + struct timeval timeout; + fd_set rfds; + fd_set wfds; + int ret; + + timeout.tv_sec = SELECT_TIMEOUT / 1000; + timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000; + rfds = events->rfds; + wfds = events->wfds; + + ret = select(events->maxfd + 1, &rfds, &wfds, NULL, &timeout); + if (ret < 0) { + /* EINTR means that a signal has been received, continue + * to the next iteration in that case. + */ + if (errno == EINTR) + continue; + + printf("error: select failed with %d\n", errno); + break; + } + if (ret == 0) { + /* select() should never time out as the ISP is supposed + * to capture images continuously. A timeout is thus + * considered as a fatal error. + */ + printf("error: select timeout\n"); + break; + } + + events_dispatch(events, &rfds, &wfds); + } + + return !events->done; +} + +void events_stop(struct events *events) +{ + events->done = true; +} + +void events_init(struct events *events) +{ + memset(events, 0, sizeof *events); + + FD_ZERO(&events->rfds); + FD_ZERO(&events->wfds); + events->maxfd = 0; + list_init(&events->events); +} diff --git a/events.h b/events.h new file mode 100644 index 0000000..00a14bf --- /dev/null +++ b/events.h @@ -0,0 +1,50 @@ +/* + * OMAP3 generic events handling + * + * Copyright (C) 2010-2012 Ideas on board SPRL + * + * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EVENTS_H__ +#define __EVENTS_H__ + +#include <stdbool.h> +#include <sys/select.h> + +#include "isp/list.h" + +struct events { + struct list_entry events; + bool done; + + int maxfd; + fd_set rfds; + fd_set wfds; +}; + +void events_watch_fd(struct events *events, int fd, + enum omap3_isp_event_type type, + void(*callback)(void *), void *priv); +void events_unwatch_fd(struct events *events, int fd); + +bool events_loop(struct events *events); +void events_stop(struct events *events); + +void events_init(struct events *events); + +#endif @@ -37,7 +37,6 @@ #include <sys/ioctl.h> #include <sys/mman.h> -#include <sys/select.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> @@ -51,11 +50,11 @@ #include "isp/v4l2.h" #include "isp/v4l2-pool.h" +#include "events.h" #include "videoout.h" #define MEDIA_DEVICE "/dev/media0" #define VIDEOOUT_DEVICE "/dev/video0" -#define SELECT_TIMEOUT 2000 /* in milliseconds */ static struct timespec fps_ts = { 0, 0 }; static unsigned int fps_last = 0; @@ -67,99 +66,21 @@ static unsigned int frame_skip = 0; static struct omap3_isp_device *isp = NULL; static struct videoout *vo = NULL; -static bool done = false; +static struct events events; /* ----------------------------------------------------------------------------- * Events */ -struct event_fd { - struct list_entry list; - - int fd; - bool write; - void (*callback)(void *priv); - void *priv; -}; - -static struct { - struct list_entry events; - - int maxfd; - fd_set rfds; - fd_set wfds; -} events; - -static void events_watch_fd(int fd, bool write, void(*callback)(void *), void *priv) -{ - struct event_fd *event; - - event = malloc(sizeof *event); - if (event == NULL) - return; - - event->fd = fd; - event->write = write; - event->callback = callback; - event->priv = priv; - - if (write) - FD_SET(fd, &events.wfds); - else - FD_SET(fd, &events.rfds); - - events.maxfd = max(events.maxfd, fd); - - list_append(&event->list, &events.events); -} - -static void events_unwatch_fd(int fd) -{ - struct event_fd *event = NULL; - struct event_fd *entry; - int maxfd = 0; - - list_for_each_entry(entry, &events.events, list) { - if (entry->fd == fd) - event = entry; - else - maxfd = max(maxfd, entry->fd); - } - - if (event == NULL) - return; - - if (event->write) - FD_CLR(fd, &events.wfds); - else - FD_CLR(fd, &events.rfds); - - events.maxfd = maxfd; - - list_remove(&event->list); - free(event); -} - -static void events_init(void) +static void __events_watch_fd(int fd, enum omap3_isp_event_type type, + void(*callback)(void *), void *priv) { - memset(&events, 0, sizeof events); - - FD_ZERO(&events.rfds); - FD_ZERO(&events.wfds); - events.maxfd = 0; - list_init(&events.events); + events_watch_fd(&events, fd, type, callback, priv); } -static void events_dispatch(const fd_set *rfds, const fd_set *wfds) +static void __events_unwatch_fd(int fd) { - struct event_fd *event; - - list_for_each_entry(event, &events.events, list) { - if (!event->write && FD_ISSET(event->fd, rfds)) - event->callback(event->priv); - if (event->write && FD_ISSET(event->fd, wfds)) - event->callback(event->priv); - } + events_unwatch_fd(&events, fd); } /* ----------------------------------------------------------------------------- @@ -210,17 +131,10 @@ static void viewfinder_process(struct omap3_isp_device *isp __attribute__((__unu strerror(-ret), ret); } - -static void events_watch_fd_isp(int fd, enum omap3_isp_event_type type, - void (*callback)(void *priv), void *priv) -{ - events_watch_fd(fd, type == OMAP3_ISP_EVENT_WRITE, callback, priv); -} - static struct omap3_isp_operations isp_ops = { .viewfinder_ready = viewfinder_process, - .watch_fd = events_watch_fd_isp, - .unwatch_fd = events_unwatch_fd, + .watch_fd = __events_watch_fd, + .unwatch_fd = __events_unwatch_fd, }; /* ----------------------------------------------------------------------------- @@ -247,12 +161,12 @@ static void video_out_process(void *priv __attribute__((__unused__))) static void events_watch_fd_vo(int fd) { - events_watch_fd(fd, true, video_out_process, NULL); + events_watch_fd(&events, fd, OMAP3_ISP_EVENT_WRITE, video_out_process, NULL); } static struct video_out_operations vo_ops = { .watch_fd = events_watch_fd_vo, - .unwatch_fd = events_unwatch_fd, + .unwatch_fd = __events_unwatch_fd, }; static const char *video_out_find(void) @@ -386,10 +300,8 @@ done: static void sigint_handler(int signal __attribute__((__unused__))) { - /* Set the done flag to true when the user presses CTRL-C to interrupt - * the main loop. - */ - done = true; + /* Stop the main loop when the user presses CTRL-C. */ + events_stop(&events); } static void usage(const char *argv0) @@ -439,7 +351,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu } } - events_init(); + events_init(&events); memset(&rect, 0, sizeof rect); ret = fb_init(&rect); @@ -514,41 +426,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu clock_gettime(CLOCK_MONOTONIC, &start); - /* Main capture loop. Wait for a video buffer using select() and process - * it. - */ - while (!done) { - struct timeval timeout; - fd_set rfds; - fd_set wfds; - - timeout.tv_sec = SELECT_TIMEOUT / 1000; - timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000; - rfds = events.rfds; - wfds = events.wfds; - - ret = select(events.maxfd + 1, &rfds, &wfds, NULL, &timeout); - if (ret < 0) { - /* EINTR means that a signal has been received, continue - * to the next iteration in that case. - */ - if (errno == EINTR) - continue; - - printf("error: select failed with %d\n", errno); - goto cleanup; - } - if (ret == 0) { - /* select() should never time out as the ISP is supposed - * to capture images continuously. A timeout is thus - * considered as a fatal error. - */ - printf("error: select timeout\n"); - goto cleanup; - } - - events_dispatch(&rfds, &wfds); - } + /* Main capture loop. */ + if (events_loop(&events)) + goto cleanup; clock_gettime(CLOCK_MONOTONIC, &end); @@ -46,8 +46,9 @@ #include "isp/v4l2.h" #include "isp/v4l2-pool.h" +#include "events.h" + #define MEDIA_DEVICE "/dev/media0" -#define SELECT_TIMEOUT 2000 /* in milliseconds */ #define VIEWFINDER_WIDTH 1024 #define VIEWFINDER_HEIGHT 768 @@ -55,115 +56,33 @@ #define SNAPSHOT_HEIGHT 1536 static unsigned int frame_count = 0; -static bool done = false; static unsigned int snapshot_interval = 20; static struct timespec snapshot_time; +static struct events events; + /* ----------------------------------------------------------------------------- * Events */ -struct event_fd { - struct list_entry list; - - int fd; - enum omap3_isp_event_type type; - void (*callback)(void *priv); - void *priv; -}; - -static struct { - struct list_entry events; - - int maxfd; - fd_set rfds; - fd_set wfds; -} events; - -static void events_watch_fd(int fd, enum omap3_isp_event_type type, - void(*callback)(void *), void *priv) -{ - struct event_fd *event; - - event = malloc(sizeof *event); - if (event == NULL) - return; - - event->fd = fd; - event->type = type; - event->callback = callback; - event->priv = priv; - - if (event->type == OMAP3_ISP_EVENT_READ) - FD_SET(fd, &events.rfds); - else - FD_SET(fd, &events.wfds); - - events.maxfd = max(events.maxfd, fd); - - list_append(&event->list, &events.events); -} - -static void events_unwatch_fd(int fd) -{ - struct event_fd *event = NULL; - struct event_fd *entry; - int maxfd = 0; - - list_for_each_entry(entry, &events.events, list) { - if (entry->fd == fd) - event = entry; - else - maxfd = max(maxfd, entry->fd); - } - - if (event == NULL) - return; - - if (event->type == OMAP3_ISP_EVENT_READ) - FD_CLR(fd, &events.rfds); - else - FD_CLR(fd, &events.wfds); - - events.maxfd = maxfd; - - list_remove(&event->list); - free(event); -} - -static void events_init(void) +static void __events_watch_fd(int fd, enum omap3_isp_event_type type, + void(*callback)(void *), void *priv) { - memset(&events, 0, sizeof events); - - FD_ZERO(&events.rfds); - FD_ZERO(&events.wfds); - events.maxfd = 0; - list_init(&events.events); + events_watch_fd(&events, fd, type, callback, priv); } -static void events_dispatch(const fd_set *rfds, const fd_set *wfds) +static void __events_unwatch_fd(int fd) { - struct event_fd *event; - - list_for_each_entry(event, &events.events, list) { - if (event->type == OMAP3_ISP_EVENT_READ && - FD_ISSET(event->fd, rfds)) - event->callback(event->priv); - if (event->type == OMAP3_ISP_EVENT_WRITE && - FD_ISSET(event->fd, wfds)) - event->callback(event->priv); - } + events_unwatch_fd(&events, fd); } /* -------------------------------------------------------------------------- */ static void sigint_handler(int signal __attribute__((__unused__))) { - /* Set the done flag to true when the user presses CTRL-C to interrupt - * the main loop. - */ - done = true; + /* Stop the main loop when the user presses CTRL-C. */ + events_stop(&events); } static void snapshot_process(struct omap3_isp_device *isp, @@ -284,7 +203,6 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu struct omap3_isp_device *isp = NULL; struct omap3_isp_operations ops; struct timespec start, end; - unsigned int count = 0; int exit_code = EXIT_FAILURE; float fps; int ret; @@ -316,7 +234,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu } } - events_init(); + events_init(&events); /* Register a signal handler for SIGINT, received when the user presses * CTRL-C. This will allow the main loop to be interrupted, and resources @@ -328,8 +246,8 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu memset(&ops, 0, sizeof ops); ops.viewfinder_ready = viewfinder_process; ops.snapshot_ready = snapshot_process; - ops.watch_fd = events_watch_fd; - ops.unwatch_fd = events_unwatch_fd; + ops.watch_fd = __events_watch_fd; + ops.unwatch_fd = __events_unwatch_fd; isp = omap3_isp_open(MEDIA_DEVICE, &ops); if (isp == NULL) { @@ -391,42 +309,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu clock_gettime(CLOCK_MONOTONIC, &start); - /* Main capture loop. Wait for a video buffer using select() and process - * it. - */ - while (!done) { - struct timeval timeout; - fd_set rfds; - fd_set wfds; - - timeout.tv_sec = SELECT_TIMEOUT / 1000; - timeout.tv_usec = (SELECT_TIMEOUT % 1000) * 1000; - rfds = events.rfds; - wfds = events.wfds; - - ret = select(events.maxfd + 1, &rfds, &wfds, NULL, &timeout); - if (ret < 0) { - /* EINTR means that a signal has been received, continue - * to the next iteration in that case. - */ - if (errno == EINTR) - continue; - - printf("error: select failed with %d\n", errno); - goto cleanup; - } - if (ret == 0) { - /* select() should never time out as the ISP is supposed - * to capture images continuously. A timeout is thus - * considered as a fatal error. - */ - printf("error: select timeout\n"); - goto cleanup; - } - - events_dispatch(&rfds, &wfds); - count++; - } + /* Main capture loop. */ + if (events_loop(&events)) + goto cleanup; clock_gettime(CLOCK_MONOTONIC, &end); @@ -441,9 +326,9 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu end.tv_nsec += 1000000000; } - fps = count / (end.tv_sec + end.tv_nsec / 1000000000.0); + fps = frame_count / (end.tv_sec + end.tv_nsec / 1000000000.0); - printf("%u images processed in %lu.%06lu seconds (%f fps)\n", count, + printf("%u images processed in %lu.%06lu seconds (%f fps)\n", frame_count, end.tv_sec, end.tv_nsec / 1000, fps); exit_code = EXIT_SUCCESS; |