Unfortunately I do not have a camera that the tegra_multimedia_api samples work with at the moment (due to pixel format).
This is the code my program is based on:
#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
uint8_t *buffer;
static int xioctl(int fd, int request, void *arg)
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
int init_mmap(int fd)
{
struct v4l2_requestbuffers req = {0};
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req))
{
perror("Requesting Buffer");
return 1;
}
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if(-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
{
perror("Querying Buffer");
return 1;
}
buffer = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("Length: %d\nAddress: %p\n", buf.length, buffer);
printf("Image Length: %d\n", buf.bytesused);
return 0;
}
int capture_image(int fd)
{
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if(-1 == xioctl(fd, VIDIOC_QBUF, &buf))
{
perror("Query Buffer");
return 1;
}
if(-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type))
{
perror("Start Capture");
return 1;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd+1, &fds, NULL, NULL, &tv);
if(-1 == r)
{
perror("Waiting for Frame");
return 1;
}
if(-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
perror("Retrieving Frame");
return 1;
}
int outfd = open("out.img", O_RDWR);
write(outfd, buffer, buf.bytesused);
close(outfd);
return 0;
}
int main()
{
int fd;
fd = open("/dev/video0", O_RDWR);
if (fd == -1)
{
perror("Opening video device");
return 1;
}
if(init_mmap(fd))
return 1;
if(capture_image(fd))
return 1;
close(fd);
return 0;
}
It will capture a single frame from /dev/video0. On Jetpack 3.3* this program succesfully returns, but if you run it in Jetpack 4.2 it will block and never finish. Adding the O_NONBLOCK flag when opening the device on Jetpack 4.2 will prevent it from blocking, but give an error.
If you want to continuously capture frames, you just need to change
if(capture_image(fd))
return 1;
to
while(true){capture_image(fd);}
. Obviously the program will never return at this point, but it will allow you to test with varying amounts of buffers.
If there are any missing steps let me know.