Created
March 13, 2020 06:03
-
-
Save notogawa/c8cdb1e05845ece2d5fa0c3be0e2df6f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gcc -o main main.c -lv4l2 | |
#include <stdio.h> | |
#include <errno.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <libv4l2.h> | |
#include <linux/videodev2.h> | |
int fd = -1; | |
int set_format(uint32_t width, uint32_t height, uint32_t format) { | |
struct v4l2_format fmt; | |
memset(&fmt, 0, sizeof(fmt)); | |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
fmt.fmt.pix.width = width; | |
fmt.fmt.pix.height = height; | |
fmt.fmt.pix.pixelformat = format; | |
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; | |
int res = v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
// puts("[format]"); | |
// printf("width : %u\n", fmt.fmt.pix.width); | |
// printf("height : %u\n", fmt.fmt.pix.height); | |
// printf("bytesperline : %u\n", fmt.fmt.pix.bytesperline); | |
// printf("sizeimage : %u\n", fmt.fmt.pix.sizeimage); | |
// printf("bytesperline * height: %u\n", fmt.fmt.pix.bytesperline * fmt.fmt.pix.height); | |
return res; | |
} | |
int main(int argc, char* argv[]) { | |
char* device = "/dev/video0"; | |
bool internal = false; | |
int opt = 0; | |
while ((opt = getopt(argc, argv, "d:i")) != -1) { | |
switch (opt) { | |
case 'd': { device = optarg; } break; | |
case 'i': { internal = true; } break; | |
default: { fprintf(stderr, "error: \'%c\' \'%c\'\n", opt, optopt); return 1;} | |
} | |
} | |
fd = v4l2_open(device, O_RDWR|O_NONBLOCK); | |
if (fd < 0) { | |
perror("error: v4l2_open"); | |
return 1; | |
} | |
set_format(32, 32, V4L2_PIX_FMT_RGB24); | |
if (internal) { // internal set format | |
set_format(64, 64, V4L2_PIX_FMT_RGB24); | |
} | |
set_format(800, 800, V4L2_PIX_FMT_RGB24); | |
struct v4l2_requestbuffers reqbufs; | |
struct v4l2_buffer buf[4]; | |
memset(&reqbufs, 0, sizeof(reqbufs)); | |
reqbufs.count = sizeof(buf)/sizeof(buf[0]); | |
reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
reqbufs.memory = V4L2_MEMORY_MMAP; | |
{ | |
int res = v4l2_ioctl(fd, VIDIOC_REQBUFS, &reqbufs); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
} | |
for (int i = 0; i < reqbufs.count; ++i) { | |
memset(&buf[i], 0, sizeof(buf[i])); | |
buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
buf[i].memory = V4L2_MEMORY_MMAP; | |
buf[i].index = i; | |
{ | |
int res = v4l2_ioctl(fd, VIDIOC_QUERYBUF, &(buf[i])); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
} | |
{ | |
int res = v4l2_ioctl(fd, VIDIOC_QBUF, &(buf[i])); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
} | |
} | |
{ | |
int cap = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
int res = v4l2_ioctl(fd, VIDIOC_STREAMON, &cap); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
} | |
fd_set fds; | |
FD_ZERO(&fds); | |
FD_SET(fd, &fds); | |
struct timeval timeout; | |
timeout.tv_sec = 5; | |
timeout.tv_usec = 0; | |
int result = select(fd+1, &fds, NULL, NULL, &timeout); | |
if (-1 == result) { | |
if (EINTR == errno) { | |
fprintf(stderr, "select inturrupted\n"); | |
} else { | |
perror("select"); | |
return 1; | |
} | |
} else if (0 == result) { | |
printf("error: timeout\n"); | |
return 1; | |
} | |
puts("capture done"); | |
{ | |
int cap = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
int res = v4l2_ioctl(fd, VIDIOC_STREAMOFF, &cap); | |
if (res != 0) { | |
perror("error"); | |
return res; | |
} | |
} | |
v4l2_close(fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment