summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Poole <netstar@gmail.com>2020-07-16 12:54:22 +0100
committerAlastair Poole <netstar@gmail.com>2020-07-16 12:54:22 +0100
commitee6cb7ffe6682ee479468ca4d81fc7bafbbcdd40 (patch)
treeb07657071d0d8cd3aec4e73f0a64a36deaa0ba40
parentfcde89b02b938b719ff973a55cab295653576e7a (diff)
cam: press any key to close the thing
-rw-r--r--cam.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/cam.c b/cam.c
index d67efe1..447db13 100644
--- a/cam.c
+++ b/cam.c
@@ -11,6 +11,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/videoio.h>
+#include <termios.h>
#include <Eina.h>
#include <Ecore.h>
@@ -70,10 +71,10 @@ YUV444toBGRA(uint8_t Y, uint8_t U, uint8_t V, uint8_t *rgb)
}
void
-yuv_convert(unsigned char *buf, char *rgb, unsigned int w, unsigned int h)
+YUV422toBGRA(unsigned char *buf, char *rgb, unsigned int w, unsigned int h)
{
for (int i = 0; i < w * h; i += 2) {
- uint8_t Y1, Y2, U, V;
+ uint8_t Y1, Y2, U, V;
Y1 = buf[2*i+0];
Y2 = buf[2*i+2];
@@ -128,7 +129,9 @@ mmap_camera(int fd, int w, int h)
struct timeval tv;
struct v4l2_buffer buf;
struct v4l2_requestbuffers req;
- int i, type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ struct termios ntio, otio;
+ time_t ts, te;
+ int i, type = V4L2_BUF_TYPE_VIDEO_CAPTURE, count = 0;
memset(&req, 0, sizeof(req));
req.count = 16;
@@ -181,15 +184,27 @@ mmap_camera(int fd, int w, int h)
borked("malloc");
}
- for (i = 0; i < 1024; i++) {
+ tcgetattr(STDIN_FILENO, &otio);
+ ntio = otio;
+ ntio.c_lflag &= (~ICANON);
+ tcsetattr(STDIN_FILENO, TCSANOW, &ntio);
+
+ ts = time(NULL);
+
+ while (1) {
FD_ZERO(&fds);
FD_SET(fd, &fds);
+ FD_SET(STDIN_FILENO, &fds);
int status = select(fd + 1, &fds, NULL, NULL, NULL);
if (status == -1 && errno == EINTR) continue;
else if (status == 0)
borked("timeout");
+ if (FD_ISSET(STDIN_FILENO, &fds)) {
+ break;
+ }
+
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
@@ -203,8 +218,9 @@ mmap_camera(int fd, int w, int h)
}
}
- yuv_convert(buffers[buf.index].start, out, w, h);
+ YUV422toBGRA(buffers[buf.index].start, out, w, h);
save_photo(out, w, h);
+ count++;
for (i = 0; i < req.count; i++) {
memset(&buf, 0, sizeof(buf));
@@ -220,6 +236,11 @@ mmap_camera(int fd, int w, int h)
free(out);
+ te = time(NULL);
+
+ printf("Saved %d frames in %lld secs (%1.1f FPS).\n", count, te - ts, (double) count / (te - ts));
+ tcsetattr(STDIN_FILENO, TCSANOW, &otio);
+
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
borked("VIDIOC_STREAMON");
@@ -238,7 +259,9 @@ read_camera(int fd, int w, int h)
char *out, *data;
fd_set fds;
struct timeval tv;
- int i, status;
+ struct termios ntio, otio;
+ time_t ts, te;
+ int status, count = 0;
out = malloc((w * h) * sizeof(uint32_t));
if (!out) {
@@ -249,8 +272,16 @@ read_camera(int fd, int w, int h)
borked("malloc()");
}
- for (i = 0; i < 128; i++) {
+ tcgetattr(STDIN_FILENO, &otio);
+ ntio = otio;
+ ntio.c_lflag &= (~ICANON);
+ tcsetattr(STDIN_FILENO, TCSANOW, &ntio);
+
+ ts = time(NULL);
+
+ while (1) {
FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds);
FD_SET(fd, &fds);
tv.tv_sec = 2;
@@ -261,21 +292,37 @@ read_camera(int fd, int w, int h)
else if (status == 0)
borked("timeout");
+ if (FD_ISSET(STDIN_FILENO, &fds)) {
+ break;
+ }
if ((read(fd, data, (w * h) * 2)) == -1) {
- printf("%s\n", strerror(errno));
+ fprintf(stderr, "read: %s\n", strerror(errno));
break;
}
- yuv_convert(data, out, w, h);
+ YUV422toBGRA(data, out, w, h);
save_photo(out, w, h);
+ count++;
}
+ te = time(NULL);
+
+ printf("Saved %d frames in %lld secs (%1.1f FPS).\n", count, te - ts, (double) count / (int) (te - ts));
+ tcsetattr(STDIN_FILENO, TCSANOW, &otio);
+
free(out);
free(data);
return 0;
}
-int main(void)
+static void
+usage(void)
+{
+ printf("Usage: ./cam <device>\n");
+ exit(0);
+}
+
+int main(int argc, char **argv)
{
struct v4l2_capability cap;
struct v4l2_format format;
@@ -284,10 +331,18 @@ int main(void)
ecore_evas_init();
- fd = open("/dev/video1", O_RDWR | O_NONBLOCK);
- if (fd == -1) return 1;
+ if (argc != 2) {
+ usage();
+ }
+
+ fd = open(argv[1], O_RDWR | O_NONBLOCK);
+ if (fd == -1) {
+ fprintf(stderr, "Unable to open %s - %s\n", argv[1], strerror(errno));
+ exit(1);
+ }
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
+ fprintf(stderr, "VIDIOC_QUERYCAP: %s\n", strerror(errno));
goto cleanup;
}
@@ -302,12 +357,12 @@ int main(void)
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
if (ioctl(fd, VIDIOC_S_FMT, &format) == -1) {
- printf("%s\n", strerror(errno));
+ fprintf(stderr, "VIDIOC_S_FMT: %s\n", strerror(errno));
goto cleanup;
}
if (ioctl(fd, VIDIOC_G_FMT, &format) == -1) {
- printf("%s\n", strerror(errno));
+ fprintf(stderr, "VIDIOC_G_FMT: %s\n", strerror(errno));
goto cleanup;
}