diff options
| -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;  | 
