Skip to content

Instantly share code, notes, and snippets.

@ndufresne
Last active August 29, 2015 14:01
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 ndufresne/5daab2e51d79b0d63519 to your computer and use it in GitHub Desktop.
Save ndufresne/5daab2e51d79b0d63519 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#define COUNT 4
#define sysfail(msg) { printf ("%s failed: %s\n", (msg), strerror (errno)); return -1; }
int
main (int argc, char **argv)
{
struct v4l2_format fmt = { 0 };
struct v4l2_requestbuffers breq = { 0 };
struct v4l2_buffer bufs[COUNT];
void *data[COUNT] = { 0 };
int fd;
int i;
fd = open (argv[1], O_RDWR);
if (fd < 0)
sysfail("open");
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
if (ioctl (fd, VIDIOC_S_FMT, &fmt) < 0)
sysfail ("S_FMT");
breq.count = COUNT;
breq.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
breq.memory = V4L2_MEMORY_MMAP;
if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
sysfail ("REQBUFS");
assert (breq.count == COUNT);
memset (bufs, 0, sizeof (bufs));
for (i = 0; i < COUNT; i++) {
int p;
bufs[i].index = i;
bufs[i].type = breq.type;
bufs[i].memory = breq.memory;
if (ioctl (fd, VIDIOC_QUERYBUF, &bufs[i]) < 0)
sysfail ("QUERYBUF");
data[i] = mmap (NULL, bufs[i].length, PROT_WRITE, MAP_SHARED, fd, bufs[i].m.offset);
if (data[i] == MAP_FAILED)
sysfail ("mmap");
for (p = 0; p < (bufs[i].bytesused >> 2); p++)
((unsigned int*)data[i])[p] = 0xFF00FF00;
}
if (ioctl (fd, VIDIOC_QBUF, &bufs[0]) < 0)
sysfail ("QBUF");
if ((bufs[0].flags & V4L2_BUF_FLAG_QUEUED) == 0) {
printf ("BUG #1: Driver should set the QUEUED flag before returning from QBUF\n");
bufs[0].flags |= V4L2_BUF_FLAG_QUEUED;
}
if (ioctl (fd, VIDIOC_STREAMON, &fmt.type) < 0)
sysfail ("STREAMON");
i = 1;
while (1) {
struct v4l2_buffer buf = { 0 };
if (ioctl (fd, VIDIOC_QBUF, &bufs[i]) < 0)
sysfail ("QBUF");
if ((bufs[i].flags & V4L2_BUF_FLAG_QUEUED) == 0) {
printf ("BUG #1: Driver should set the QUEUED flag before returning from QBUF\n");
bufs[i].flags |= V4L2_BUF_FLAG_QUEUED;
}
buf.type = breq.type;
buf.memory = breq.memory;
if (ioctl (fd, VIDIOC_DQBUF, &buf) < 0)
sysfail ("DBBUF");
i = buf.index;
if ((bufs[i].flags & V4L2_BUF_FLAG_QUEUED) == 0) {
printf ("BUG #2: Driver should not dequeue a buffer that was not intially queued\n");
}
assert (bufs[i].flags & V4L2_BUF_FLAG_QUEUED);
assert (!(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)));
bufs[i] = buf;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment