videograb : first step
This commit is contained in:
parent
f0f8daa0fb
commit
c054054ee5
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,6 +9,8 @@ gmon.out
|
||||
*.fimg
|
||||
essai
|
||||
|
||||
*/*.ps
|
||||
|
||||
v4l2/t
|
||||
v4l2/capture
|
||||
v4l2/*.o
|
||||
|
@ -3,13 +3,14 @@
|
||||
COPT = -Wall -fpic -g -DDEBUG_LEVEL=1
|
||||
DEPS = ../floatimg.h ../libfloatimg.a Makefile
|
||||
|
||||
funcs.o: funcs.c funcs.h Makefile
|
||||
gcc ${COPT} -c $<
|
||||
|
||||
t: t.c Makefile ${DEPS} funcs.o
|
||||
gcc ${COPT} $< funcs.o ../libfloatimg.a -o $@
|
||||
|
||||
t: t.c Makefile ${DEPS}
|
||||
gcc ${COPT} $< ../libfloatimg.a -o $@
|
||||
|
||||
# --------
|
||||
# extern things
|
||||
# ---------------
|
||||
# external things
|
||||
|
||||
capture: capture.c Makefile
|
||||
gcc -Wall $< -o $@
|
||||
|
317
v4l2/funcs.c
Normal file
317
v4l2/funcs.c
Normal file
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* V4L2 functions - ugly source code
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fcntl.h> /* low-level i/o */
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
enum io_method {
|
||||
IO_METHOD_READ,
|
||||
IO_METHOD_MMAP,
|
||||
IO_METHOD_USERPTR,
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
void *start;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
static char *dev_name;
|
||||
static enum io_method io = IO_METHOD_MMAP;
|
||||
static int fd = -1;
|
||||
struct buffer *buffers;
|
||||
static unsigned int n_buffers;
|
||||
static int out_buf;
|
||||
static int force_format;
|
||||
static int frame_count = 70;
|
||||
|
||||
static void errno_exit(const char *s)
|
||||
{
|
||||
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
static int xioctl(int fh, int request, void *arg)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
r = ioctl(fh, request, arg);
|
||||
} while (-1 == r && EINTR == errno);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/*
|
||||
*
|
||||
*/
|
||||
int open_device(char *device)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (-1 == stat(device, &st)) {
|
||||
fprintf(stderr, "Cannot identify '%s': %d, %s\n",
|
||||
device, errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
fprintf(stderr, "%s is no device\n", device);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fd = open(device, O_RDWR /* required */ | O_NONBLOCK, 0);
|
||||
|
||||
if (-1 == fd) {
|
||||
fprintf(stderr, "Cannot open '%s': %d, %s\n",
|
||||
device, errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dev_name = strdup(device); /* XXX */
|
||||
|
||||
return fd;
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
||||
static void init_read(unsigned int buffer_size)
|
||||
{
|
||||
buffers = calloc(1, sizeof(*buffers));
|
||||
|
||||
if (!buffers) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffers[0].length = buffer_size;
|
||||
buffers[0].start = malloc(buffer_size);
|
||||
|
||||
if (!buffers[0].start) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_mmap(void)
|
||||
{
|
||||
struct v4l2_requestbuffers req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.count = 4;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_MMAP;
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
|
||||
if (EINVAL == errno) {
|
||||
fprintf(stderr, "%s does not support "
|
||||
"memory mapping\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
errno_exit("VIDIOC_REQBUFS");
|
||||
}
|
||||
}
|
||||
|
||||
if (req.count < 2) {
|
||||
fprintf(stderr, "Insufficient buffer memory on %s\n",
|
||||
dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffers = calloc(req.count, sizeof(*buffers));
|
||||
|
||||
if (!buffers) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.memory = V4L2_MEMORY_MMAP;
|
||||
buf.index = n_buffers;
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf))
|
||||
errno_exit("VIDIOC_QUERYBUF");
|
||||
|
||||
buffers[n_buffers].length = buf.length;
|
||||
buffers[n_buffers].start =
|
||||
mmap(NULL /* start anywhere */,
|
||||
buf.length,
|
||||
PROT_READ | PROT_WRITE /* required */,
|
||||
MAP_SHARED /* recommended */,
|
||||
fd, buf.m.offset);
|
||||
|
||||
if (MAP_FAILED == buffers[n_buffers].start)
|
||||
errno_exit("mmap");
|
||||
}
|
||||
}
|
||||
|
||||
static void init_userp(unsigned int buffer_size)
|
||||
{
|
||||
struct v4l2_requestbuffers req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
req.count = 4;
|
||||
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
req.memory = V4L2_MEMORY_USERPTR;
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
|
||||
if (EINVAL == errno) {
|
||||
fprintf(stderr, "%s does not support "
|
||||
"user pointer i/o\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
errno_exit("VIDIOC_REQBUFS");
|
||||
}
|
||||
}
|
||||
|
||||
buffers = calloc(4, sizeof(*buffers));
|
||||
|
||||
if (!buffers) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
|
||||
buffers[n_buffers].length = buffer_size;
|
||||
buffers[n_buffers].start = malloc(buffer_size);
|
||||
|
||||
if (!buffers[n_buffers].start) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
||||
int init_device(int notused)
|
||||
{
|
||||
struct v4l2_capability cap;
|
||||
struct v4l2_cropcap cropcap;
|
||||
struct v4l2_crop crop;
|
||||
struct v4l2_format fmt;
|
||||
unsigned int min;
|
||||
|
||||
#if DEBUG_LEVEL
|
||||
fprintf(stderr, ">>> %s ( %d )\n", __func__, notused);
|
||||
#endif
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
|
||||
if (EINVAL == errno) {
|
||||
fprintf(stderr, "%s is no V4L2 device\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
errno_exit("VIDIOC_QUERYCAP");
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
|
||||
fprintf(stderr, "%s is no video capture device\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
switch (io) {
|
||||
case IO_METHOD_READ:
|
||||
if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
|
||||
fprintf(stderr, "%s do not support read i/o\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (verbosity) fprintf(stderr, "%s io method read OK\n", __func__);
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
case IO_METHOD_USERPTR:
|
||||
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
|
||||
fprintf(stderr, "%s do not support streaming i/o\n", dev_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (verbosity) fprintf(stderr, "%s io mmap/userptr OK\n", __func__);
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
/* Select video input, video standard and tune here. */
|
||||
|
||||
|
||||
memset(&cropcap, 0, sizeof(cropcap));
|
||||
|
||||
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) {
|
||||
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
crop.c = cropcap.defrect; /* reset to default */
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) {
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
/* Cropping not supported. */
|
||||
break;
|
||||
default:
|
||||
/* Errors ignored. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Errors ignored. */
|
||||
}
|
||||
|
||||
|
||||
memset(&fmt, 0, sizeof(fmt)); // CLEAR(fmt);
|
||||
|
||||
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
if (force_format) {
|
||||
fmt.fmt.pix.width = 640;
|
||||
fmt.fmt.pix.height = 480;
|
||||
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
|
||||
|
||||
if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
|
||||
errno_exit("VIDIOC_S_FMT");
|
||||
|
||||
/* Note VIDIOC_S_FMT may change width and height. */
|
||||
} else {
|
||||
/* Preserve original settings as set by v4l2-ctl for example */
|
||||
if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
|
||||
errno_exit("VIDIOC_G_FMT");
|
||||
}
|
||||
|
||||
/* Buggy driver paranoia. */
|
||||
min = fmt.fmt.pix.width * 2;
|
||||
if (fmt.fmt.pix.bytesperline < min)
|
||||
fmt.fmt.pix.bytesperline = min;
|
||||
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
|
||||
if (fmt.fmt.pix.sizeimage < min)
|
||||
fmt.fmt.pix.sizeimage = min;
|
||||
|
||||
switch (io) {
|
||||
case IO_METHOD_READ:
|
||||
init_read(fmt.fmt.pix.sizeimage);
|
||||
break;
|
||||
|
||||
case IO_METHOD_MMAP:
|
||||
init_mmap();
|
||||
break;
|
||||
|
||||
case IO_METHOD_USERPTR:
|
||||
init_userp(fmt.fmt.pix.sizeimage);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
7
v4l2/funcs.h
Normal file
7
v4l2/funcs.h
Normal file
@ -0,0 +1,7 @@
|
||||
/*
|
||||
* V4L2 functions - header file
|
||||
*/
|
||||
|
||||
int open_device(char *dev_name);
|
||||
|
||||
int init_device(int notused);
|
27
v4l2/t.c
27
v4l2/t.c
@ -8,10 +8,26 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "funcs.h"
|
||||
#include "floatimg.h"
|
||||
|
||||
int verbosity;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
int essai(char *dev, int k)
|
||||
{
|
||||
int vfd, foo;
|
||||
|
||||
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, dev, k);
|
||||
|
||||
vfd = open_device(dev);
|
||||
fprintf(stderr, "\topen %s -> %d\n", dev, vfd);
|
||||
|
||||
foo = init_device(0);
|
||||
fprintf(stderr, "\tinit -> %d\n", foo);
|
||||
|
||||
return k;
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
||||
void help(int k)
|
||||
{
|
||||
@ -23,16 +39,16 @@ puts("\t-v\tincrease verbosity");
|
||||
exit(0);
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int foo, opt;
|
||||
int W = 800, H = 600;
|
||||
double tb;
|
||||
|
||||
char *device = "/dev/video0";
|
||||
int K = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "hK:v")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "d:hK:v")) != -1) {
|
||||
switch(opt) {
|
||||
case 'd': device = optarg; break;
|
||||
case 'h': help(0); break;
|
||||
case 'K': K = atol(optarg); break;
|
||||
case 'v': verbosity++; break;
|
||||
@ -41,6 +57,9 @@ while ((opt = getopt(argc, argv, "hK:v")) != -1) {
|
||||
|
||||
if (verbosity) fimg_print_version(0);
|
||||
|
||||
foo = essai(device, K);
|
||||
fprintf(stderr, "\tessai -> %d\n", foo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
Loading…
Reference in New Issue
Block a user