Created
December 6, 2015 03:09
-
-
Save cebe/386a89b273d0389b86a9 to your computer and use it in GitHub Desktop.
Compile it with: clang -o utox -g -Wall -Wshadow -std=gnu99 ./bug.c `pkg-config --libs --cflags libv4lconvert` -fsanitize=address
This file contains hidden or 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
static int utox_v4l_fd = -1; | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <ctype.h> | |
#include <fcntl.h> | |
#include <sys/stat.h> | |
#include <sys/ioctl.h> | |
#include <pthread.h> | |
#include <unistd.h> | |
#include <locale.h> | |
#include <dlfcn.h> | |
#include <errno.h> | |
#define debug(...) printf(__VA_ARGS__) | |
#include <linux/videodev2.h> | |
#include <libv4l2.h> | |
#include <libv4lconvert.h> | |
#define CLEAR(x) memset(&(x), 0, sizeof(x)) | |
int v4l_init(char *dev_name); | |
int main() { | |
return v4l_init("/dev/video0"); | |
} | |
static int xioctl(int fh, unsigned long request, void *arg) | |
{ | |
int r; | |
do { | |
r = ioctl(fh, request, arg); | |
} while (-1 == r && EINTR == errno); | |
return r; | |
} | |
static struct v4lconvert_data *v4lconvert_data; | |
static struct v4l2_format fmt, dest_fmt = { | |
//.type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | |
.fmt = { | |
.pix = { | |
.pixelformat = V4L2_PIX_FMT_YUV420, | |
//.field = V4L2_FIELD_NONE, | |
}, | |
}, | |
}; | |
int v4l_init(char *dev_name) { | |
utox_v4l_fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); | |
if (-1 == utox_v4l_fd) { | |
debug("Cannot open '%s': %d, %s\n", dev_name, errno, strerror(errno)); | |
return 0; | |
} | |
struct v4l2_capability cap; | |
struct v4l2_cropcap cropcap; | |
struct v4l2_crop crop; | |
unsigned int min; | |
if (-1 == xioctl(utox_v4l_fd, VIDIOC_QUERYCAP, &cap)) { | |
if (EINVAL == errno) { | |
debug("%s is no V4L2 device\n", dev_name); | |
} else { | |
debug("VIDIOC_QUERYCAP error %d, %s\n", errno, strerror(errno)); | |
} | |
return 0; | |
} | |
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { | |
debug("%s is no video capture device\n", dev_name); | |
return 0; | |
} | |
if (!(cap.capabilities & V4L2_CAP_STREAMING)) { | |
debug("%s does not support streaming i/o\n", dev_name); | |
return 0; | |
} | |
/* Select video input, video standard and tune here. */ | |
CLEAR(cropcap); | |
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
if (0 == xioctl(utox_v4l_fd, VIDIOC_CROPCAP, &cropcap)) { | |
crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
crop.c = cropcap.defrect; /* reset to default */ | |
if (-1 == xioctl(utox_v4l_fd, VIDIOC_S_CROP, &crop)) { | |
switch (errno) { | |
case EINVAL: | |
/* Cropping not supported. */ | |
break; | |
default: | |
/* Errors ignored. */ | |
break; | |
} | |
} | |
} else { | |
/* Errors ignored. */ | |
} | |
v4lconvert_data = v4lconvert_create(utox_v4l_fd); | |
CLEAR(fmt); | |
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
if (-1 == xioctl(utox_v4l_fd, VIDIOC_G_FMT, &fmt)) { | |
debug("VIDIOC_S_FMT error %d, %s\n", errno, strerror(errno)); | |
return 0; | |
} | |
/*if(fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV) { | |
debug("Unsupported video format: %u %u %u %u\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.pixelformat, fmt.fmt.pix.field); | |
}*/ | |
int video_width = fmt.fmt.pix.width; | |
int video_height = fmt.fmt.pix.height; | |
dest_fmt.fmt.pix.width = fmt.fmt.pix.width; | |
dest_fmt.fmt.pix.height = fmt.fmt.pix.height; | |
debug("Video size: %u %u\n", video_width, video_height); | |
/* 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; | |
/* part 3*/ | |
//uint32_t buffer_size = fmt.fmt.pix.sizeimage; | |
struct v4l2_requestbuffers req; | |
CLEAR(req); | |
req.count = 4; | |
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
req.memory = V4L2_MEMORY_MMAP;//V4L2_MEMORY_USERPTR; | |
if (-1 == xioctl(utox_v4l_fd, VIDIOC_REQBUFS, &req)) { | |
if (EINVAL == errno) { | |
debug("%s does not support x i/o\n", dev_name); | |
} else { | |
debug("VIDIOC_REQBUFS error %d, %s\n", errno, strerror(errno)); | |
} | |
return 0; | |
} | |
debug("success\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment