summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-02-22 23:27:15 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-16 23:40:56 +0200
commit211507d598b67e6e274275ab472d5e81ec1afcec (patch)
tree47d4ba219c740b85dd563e312083f2787016d0ec
parent4dd4dcb4f594c872df222390031975d06adc7e71 (diff)
Factor event handling code out into events.c
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--Makefile4
-rw-r--r--events.c175
-rw-r--r--events.h50
-rw-r--r--live.c154
-rw-r--r--snapshot.c153
5 files changed, 263 insertions, 273 deletions
diff --git a/Makefile b/Makefile
index 849e367..cb7d846 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/live.c b/live.c
index 70e4db5..c4d5ffd 100644
--- a/live.c
+++ b/live.c
@@ -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);
diff --git a/snapshot.c b/snapshot.c
index bc2b7da..da63b36 100644
--- a/snapshot.c
+++ b/snapshot.c
@@ -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;