Skip to content

Instantly share code, notes, and snippets.

@notogawa
Created March 13, 2020 06:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save notogawa/c8cdb1e05845ece2d5fa0c3be0e2df6f to your computer and use it in GitHub Desktop.
Save notogawa/c8cdb1e05845ece2d5fa0c3be0e2df6f to your computer and use it in GitHub Desktop.
// 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