1:抓取一帧图像,然后在tmp目录下有video.yuv,拷贝到windows下用yuvplayer播放,格式选择 YUY2
2: 要切换分辨率,
#define MY_WIDTH 1024
#define MY_HEIGHT 768
执行命令: ./ccccc /dev/video0
编译命令
source /opt/poky/2.1.2/environment-setup-aarch64-poky-linux
$CXX -o camera camera.c -lopencv_highgui -lopencv_imgproc -lopencv_core -lopencv_video -lavcodec -lavfilter -lavdevice -lavutil
若要只显示一摄像头,只需要:
204:
while (i_tmp < 600) {
改为while(1) {
即可
/*
* * V4L2 video capture example
* *
* * This program can be used and distributed without restrictions.
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h> /* for videodev2.h */
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <linux/kd.h>
//#include <linux/input.h>
//#include <linux/input-event-codes.h>
#define CLEAR(x) memset (&(x), 0, sizeof (x))
#define RGB(b,g,r) (unsigned char[4]){(b),(g),(r),0}
typedef enum {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
} io_method;
struct buffer {
void * start;
size_t length;
};
static char * dev_name = NULL;
static int bp=-1;
// static int key=-1;
static int tty=-1;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
// struct input_event t;
long screensize=0;
char *fbp = 0;
long location = 0;
static io_method io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
static FILE *fp=NULL;
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 fd,int request,void * arg)
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
void fb_putpixel(int x,int y,unsigned char pixel[4]){
unsigned long position=0;
position=((unsigned long)x+((unsigned long)y)*(vinfo.xres))*4ul;
lseek(bp,position,SEEK_SET);
write(bp,pixel,4);
}
static void clear(){
int x,y;
for (x=0;x<vinfo.xres;x++)
for (y=0;y<vinfo.yres;y++)
{
*(fbp+y*finfo.line_length+x*4)=0;
*(fbp+y*finfo.line_length+x*4+1)=0;
*(fbp+y*finfo.line_length+x*4+2)=0;
*(fbp+y*finfo.line_length+x*4+3)=0;
}
}
static void process_image (const void * p,size_t length){
fp=fopen("/tmp/video.yuv","a+");
if(fp == NULL){
printf("open file error!\n");
return ;
}
fwrite(p,1,length,fp);
fclose(fp);
/*
int i,j,r,g,b,y,u,v;
unsigned char *src=(unsigned char*)p;
for(i=0;i<480;i++)
{
for(j=0;j<640;j++)
{
if(j%2)
{
y=*(src+i*640*2+j*2) -16;
u=*(src+i*640*2+j*2-1) -128;
v=*(src+i*640*2+j*2+1) -128;
}else
{
y=*(src+i*640*2+j*2) -16;
u=*(src+i*640*2+j*2+1) -128;
v=*(src+i*640*2+j*2+3) -128;
}
r=(298*y+409*v+128)>>8;
g=(298*y-100*u-208*v+128)>>8;
b=(298*y+516*u+128)>>8;
b = (b > 255) ? 255 : ((b < 0) ? 0 : b);
g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
r = (r > 255) ? 255 : ((r < 0) ? 0 : r);
*(fbp+i*finfo.line_length+j*4)=b;
*(fbp+i*finfo.line_length+j*4+1)=g;
*(fbp+i*finfo.line_length+j*4+2)=r;
*(fbp+i*finfo.line_length+j*4+3)=0;
// fb_putpixel(j,i,RGB(b,g,r));
}
}
*/
// usleep(20000);
}
static int read_frame (void)
{
struct v4l2_buffer buf;
unsigned int i;
switch (io) {
case IO_METHOD_READ:
if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("read");
}
}
// process_image (buffers[0].start);
break;
case IO_METHOD_MMAP:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//DQBUF move video buffer to mmap address
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
printf("errno:%d\n",errno);
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
assert (buf.index < n_buffers);
process_image (buffers[buf.index].start,buffers[buf.index].length);
//clean video buffer
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
case IO_METHOD_USERPTR:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
for (i = 0; i < n_buffers; ++i)
if (buf.m.userptr == (unsigned long) buffers[i].start
&& buf.length == buffers[i].length)
break;
assert (i < n_buffers);
// process_image ((void *) buf.m.userptr);
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
}
return 1;
}
static void mainloop (void)
{
unsigned int count;
count = 10;
while (count-- > 0) {
// while (1) {
// CLEAR(t);
// if(read(key,&t,sizeof(t)) != sizeof(t)){
// printf("read input fail!\n");
// break;
// }
// if(t.type==EV_KEY)
// break;
//
printf("get frame \n");
if (read_frame ())
break;
sleep(1);
/* EAGAIN - continue select loop. */
}
}
static void stop_capturing (void)
{
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
errno_exit ("VIDIOC_STREAMOFF");
break;
}
}
static void start_capturing (void)
{
unsigned int i;
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
printf("cant read/write!\n");
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.m.userptr = (unsigned long) buffers[i].start;
buf.length = buffers[i].length;
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
}
}
static void uninit_device (void)
{
unsigned int i;
switch (io) {
case IO_METHOD_READ:
free (buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (buffers[i].start, buffers[i].length))
errno_exit ("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i)
free (buffers[i].start);
break;
}
free (buffers);
}
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);
}
}
/*
*
*struct v4l2_requestbuffers {
* __u32 count; //number of buff request
* __u32 type; //buf type (v4l2_format)
* __u32 memory; // set field to mmap
* __u32 reserved[2];
*};
*
* struct v4l2_buffer {
* __u32 index;
* __u32 type;
* __u32 bytesused;
* __u32 flags;
* __u32 field;
* struct timeval timestamp;
* struct v4l2_timecode timecode;
* __u32 sequence;
* __u32 memory; //memory location
* union {
* __u32 offset;
* unsigned long userptr;
* struct v4l2_plane *planes;
* __s32 fd;
* } m;
* __u32 length;
* __u32 reserved2;
* __u32 reserved;
*};
*
**/
static void init_mmap (void)
{
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = 2;
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);
}
printf("req buf count:%d\n",req.count);
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;
CLEAR (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;
CLEAR (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);
}
}
}
/*
*
*cap --->driver |name of driver
* --->card |name of device
* --->bus_info| location of the device in the system
* --->version | kernel verison
* --->capabilities| 0x00000001 support video capture interface
* | 0x00000002 support video output interface
* | 0x00000004 support store images directly in video memory
* | 0x00020000 device has audio input outputs
* | 0x01000000 support read()/write() I\O methods
* | 0x04000000 support streaming I/O methods
*
*cropcap video crop and scaling abilities
* ---> type | V4L2_BUF_TYPE_VIDEO_CAPTURE
* | V4L2_BUF_TYPE_VIDEO_OUTPUT
* | V4L2_BUF_TYPE_VIDEO_OVERLAY
* --->(v4l2_rect) bounds | Defines window
* --->(v4l2_rect) defrect| default cropping rectangel
* --->(v4l2_fract)pixelaspect| pixel aspect(y/x)
*fmt vidio format
* ---> tpye |same as above
* ---> unio( v4l2_pix_format format_mplane window vbi_format sdr_format raw_data )fmt |set format
*
* */
static void init_device (void)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
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 does not support read i/o\n",dev_name);
exit (EXIT_FAILURE);
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
fprintf (stderr, "%s does not support streaming i/o\n",dev_name);
exit (EXIT_FAILURE);
}
break;
}
/* Select video input, video standard and tune here. */
CLEAR (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;
if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop))
{
switch (errno)
{
case EINVAL:
printf("Cropping not support!\n");
break;
default:
printf("Cropping faild!\n");
break;
}
}
} else
{
printf("get cropcap error!\n");
}
*/
CLEAR (fmt);
/*
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
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. */
/* Buggy driver paranoia. */
/*set bytes per line | image size = width * height *2*/
/*min = fmt.fmt.pix.width * 2;
printf("bytes per line:%d,width*2:%d\n",fmt.fmt.pix.bytesperline,min);
if (fmt.fmt.pix.bytesperline < min)
fmt.fmt.pix.bytesperline = min;
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
printf("image size:%d,width*height*2:%d\n",fmt.fmt.pix.sizeimage,min);
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;
}
}
static void close_device (void)
{
if (-1 == close (fd))
errno_exit ("close");
}
/*
*
*
* stat --->st_dev |device num
* --->st_ino |node
* --->st_mode |file type read/write permition
* --->st_nlink |file hard link number
* --->st_uid gid|user id group ip
* --->st_size |file size byte number
* --->st_blksize|file system I/O buffer size
* --->st_blocks |block number
* --->st_atime ctime mtime |last access, last change property, last modify
*
*
* */
static void open_device (void)
{
struct stat st;
if (-1 == stat (dev_name, &st)) {
fprintf (stderr, "Cannot identify ’%s’: %d, %s\n",
dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
if (!S_ISCHR (st.st_mode)) {
fprintf (stderr, "%s is no device\n", dev_name);
exit (EXIT_FAILURE);
}
fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf (stderr, "Cannot open ’%s’: %d, %s\n",
dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
}
static void usage (FILE * fp,int argc,char ** argv)
{
fprintf (fp,
"Usage: %s [options]\n\n"
"Options:\n"
"-d | --device name Video device name [/dev/video]\n"
"-h | --help Print this message\n"
"-m | --mmap Use memory mapped buffers\n"
"-r | --read Use read() calls\n"
"-u | --userp Use application allocated buffers\n"
"",
argv[0]);
}
static const char short_options [] = "d:hmru";
static const struct option
long_options [] = {
{ "device", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "mmap", no_argument, NULL, 'm' },
{ "read", no_argument, NULL, 'r' },
{ "userp", no_argument, NULL, 'u' },
{ 0, 0, 0, 0 }
};
int main (int argc,
char ** argv)
{
dev_name = argv[1];
for (;;) {
int index;
int c;
c = getopt_long (argc, argv,
short_options, long_options,
&index);
if (-1 == c)
break;
switch (c) {
case 0: /* getopt_long() flag */
break;
case 'd':
dev_name = optarg;
break;
case 'h':
usage (stdout, argc, argv);
exit (EXIT_SUCCESS);
case 'm':
io = IO_METHOD_MMAP;
break;
case 'r':
io = IO_METHOD_READ;
break;
case 'u':
io = IO_METHOD_USERPTR;
break;
default:
usage (stderr, argc, argv);
exit (EXIT_FAILURE);
}
}
printf("open device\n");
open_device ();
printf("init device\n");
init_device ();
printf("start_capturing \n");
start_capturing ();
printf("mainloop\n");
mainloop ();
stop_capturing ();
clear();
uninit_device ();
close_device ();
exit (EXIT_SUCCESS);
return 0;
}
抓取动态图像从而显示在HDMI上,
执行命令: ./camera /dev/video0(1.2.3)
/*
* * V4L2 video capture example
* *
* * This program can be used and distributed without restrictions.
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h> /* for videodev2.h */
#include <linux/videodev2.h>
#include <linux/fb.h>
#include <linux/kd.h>
//#include <linux/input.h> /*undo press key to stop capture*/
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#define MY_WIDTH 1024
#define MY_HEIGHT 768
#define CLEAR(x) memset (&(x), 0, sizeof (x))
#define RGB(b,g,r) (unsigned char[4]){(b),(g),(r),0}
using namespace cv;
typedef enum {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
} io_method;
struct timeval tvv;
struct timeval ts;
struct buffer {
void * start;
size_t length;
};
static char dev_name[20] = {0};
static int bp=-1;
static int tty=-1;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
// struct input_event t;
long screensize=0;
char *fbp = 0;
long location = 0;
static io_method io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
// static FILE *fp=NULL;
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 fd,int request,void * arg)
{
int r;
do r = ioctl (fd, request, arg);
while (-1 == r && EINTR == errno);
return r;
}
void fb_putpixel(int x,int y,unsigned char pixel[4]){
unsigned long position=0;
position=((unsigned long)x+((unsigned long)y)*(vinfo.xres))*4ul;
lseek(bp,position,SEEK_SET);
write(bp,pixel,4);
}
static void clear(){
int x,y;
for (x=0;x<vinfo.xres;x++)
for (y=0;y<vinfo.yres;y++)
{
*(fbp+y*finfo.line_length+x*4)=0;
*(fbp+y*finfo.line_length+x*4+1)=0;
*(fbp+y*finfo.line_length+x*4+2)=0;
*(fbp+y*finfo.line_length+x*4+3)=0;
}
}
static void process_image (const void * p,size_t length){
/* fp=fopen("/tmp/video.yuv","a+");
if(fp == NULL){
printf("open file error!\n");
return ;
}
fwrite(p,1,length,fp);
fclose(fp);
*/
char *tmp=NULL;
unsigned char *tmp1=NULL;
int i = 0;
if(p == NULL || length ==0) return;
Mat out(MY_HEIGHT,MY_WIDTH,CV_8UC2),rgb;
memcpy(out.data,p,length);
cvtColor(out,rgb,COLOR_YUV2BGRA_YUY2);
tmp1 = rgb.data;
tmp = fbp;
for(i=0;i<MY_HEIGHT;i++){
memcpy(tmp,tmp1,MY_WIDTH*4);
tmp +=MY_WIDTH*4;
tmp1 +=MY_WIDTH*4;
}
}
static int read_frame (void)
{
struct v4l2_buffer buf;
unsigned int i;
switch (io) {
case IO_METHOD_READ:
if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("read");
}
}
// process_image (buffers[0].start);
break;
case IO_METHOD_MMAP:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
//DQBUF move video buffer to mmap address
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
assert (buf.index < n_buffers);
process_image (buffers[buf.index].start,buffers[buf.index].length);
//clean video buffer
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
case IO_METHOD_USERPTR:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
switch (errno) {
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit ("VIDIOC_DQBUF");
}
}
for (i = 0; i < n_buffers; ++i)
if (buf.m.userptr == (unsigned long) buffers[i].start
&& buf.length == buffers[i].length)
break;
assert (i < n_buffers);
// process_image ((void *) buf.m.userptr);
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
break;
}
return 1;
}
static void mainloop (void)
{
unsigned int count;
int i_tmp = 0;
count = 1000;
while (i_tmp < 600) {
i_tmp++;
// gettimeofday(&tvv,NULL);
for (;;) {
/*fd_set is a struct actualy a
* Long type array ,every Long type
* is a handle*/
fd_set fds;
struct timeval tv;
int r;
FD_ZERO (&fds);//turn zero to fds
FD_SET (fd, &fds);//add device handle to fds
/* Timeout. */
tv.tv_sec = 1; //second
tv.tv_usec = 0; //u second 10^-6s
//ensure video device is ready!
r = select (fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r) {
if (EINTR == errno)
continue;
errno_exit ("select");
}
if (0 == r) {
fprintf (stderr, "select timeout\n");
exit (EXIT_FAILURE);
}
if (read_frame ())
break;
/* EAGAIN - continue select loop. */
}
// gettimeofday(&ts,NULL);
// printf("timestamp: %ld ms \n", (ts.tv_sec * 1000 + ts.tv_usec / 1000) - (tvv.tv_sec * 1000 + tvv.tv_usec / 1000));
}
}
static void stop_capturing (void)
{
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
errno_exit ("VIDIOC_STREAMOFF");
break;
}
}
static void start_capturing (void)
{
unsigned int i;
enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
printf("cant read/write!\n");
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf;
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.m.userptr = (unsigned long) buffers[i].start;
buf.length = buffers[i].length;
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
errno_exit ("VIDIOC_QBUF");
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
errno_exit ("VIDIOC_STREAMON");
break;
}
}
static void uninit_device (void)
{
unsigned int i;
switch (io) {
case IO_METHOD_READ:
free (buffers[0].start);
break;
case IO_METHOD_MMAP:
for (i = 0; i < n_buffers; ++i)
if (-1 == munmap (buffers[i].start, buffers[i].length))
errno_exit ("munmap");
if (-1 == munmap (fbp, screensize))
errno_exit ("munmap");
break;
case IO_METHOD_USERPTR:
for (i = 0; i < n_buffers; ++i)
free (buffers[i].start);
break;
}
free (buffers);
}
static void init_read (unsigned int buffer_size)
{
buffers = (buffer *)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);
}
}
/*
*
*struct v4l2_requestbuffers {
* __u32 count; //number of buff request
* __u32 type; //buf type (v4l2_format)
* __u32 memory; // set field to mmap
* __u32 reserved[2];
*};
*
* struct v4l2_buffer {
* __u32 index;
* __u32 type;
* __u32 bytesused;
* __u32 flags;
* __u32 field;
* struct timeval timestamp;
* struct v4l2_timecode timecode;
* __u32 sequence;
* __u32 memory; //memory location
* union {
* __u32 offset;
* unsigned long userptr;
* struct v4l2_plane *planes;
* __s32 fd;
* } m;
* __u32 length;
* __u32 reserved2;
* __u32 reserved;
*};
*
**/
static void init_mmap (void)
{
struct v4l2_requestbuffers req;
CLEAR (req);
req.count = 6;
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);
}
printf("req buf count:%d\n",req.count);
buffers = (buffer *)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;
CLEAR (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;
CLEAR (req);
req.count = 2;
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 = (buffer *)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);
}
}
}
/*
*
*cap --->driver |name of driver
* --->card |name of device
* --->bus_info| location of the device in the system
* --->version | kernel verison
* --->capabilities| 0x00000001 support video capture interface
* | 0x00000002 support video output interface
* | 0x00000004 support store images directly in video memory
* | 0x00020000 device has audio input outputs
* | 0x01000000 support read()/write() I\O methods
* | 0x04000000 support streaming I/O methods
*
*cropcap video crop and scaling abilities
* ---> type | V4L2_BUF_TYPE_VIDEO_CAPTURE
* | V4L2_BUF_TYPE_VIDEO_OUTPUT
* | V4L2_BUF_TYPE_VIDEO_OVERLAY
* --->(v4l2_rect) bounds | Defines window
* --->(v4l2_rect) defrect| default cropping rectangel
* --->(v4l2_fract)pixelaspect| pixel aspect(y/x)
*fmt vidio format
* ---> tpye |same as above
* ---> unio( v4l2_pix_format format_mplane window vbi_format sdr_format raw_data )fmt |set format
*
* */
static void init_device (void)
{
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;
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 does not support read i/o\n",dev_name);
exit (EXIT_FAILURE);
}
break;
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if (!(cap.capabilities & V4L2_CAP_STREAMING))
{
fprintf (stderr, "%s does not support streaming i/o\n",dev_name);
exit (EXIT_FAILURE);
}
break;
}
/* Select video input, video standard and tune here. */
CLEAR (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. */
printf("Cropping not support!\n");
break;
default:
printf("Cropping faild!\n");
/* Errors ignored. */
break;
}
}
} else
{
printf("get cropcap error!\n");
/* Errors ignored. */
}
CLEAR (fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = MY_WIDTH;
fmt.fmt.pix.height = MY_HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
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. */
/* Buggy driver paranoia. */
/*set bytes per line | image size = width * height *2*/
min = fmt.fmt.pix.width * 2;
printf("bytes per line:%d,width*2:%d\n",fmt.fmt.pix.bytesperline,min);
if (fmt.fmt.pix.bytesperline < min)
fmt.fmt.pix.bytesperline = min;
min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
printf("image size:%d,width*height*2:%d\n",fmt.fmt.pix.sizeimage,min);
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;
}
}
static void close_device (void)
{
if (-1 == close (fd))
errno_exit ("close");
if (-1 == close (bp))
errno_exit ("close");
if( -1 ==close(tty))
errno_exit ("close");
}
/*
*
*
* stat --->st_dev |device num
* --->st_ino |node
* --->st_mode |file type read/write permition
* --->st_nlink |file hard link number
* --->st_uid gid|user id group ip
* --->st_size |file size byte number
* --->st_blksize|file system I/O buffer size
* --->st_blocks |block number
* --->st_atime ctime mtime |last access, last change property, last modify
*
*
* */
static void open_device (void)
{
struct stat st;
if (-1 == stat (dev_name, &st)) {
fprintf (stderr, "Cannot identify ’%s’: %d, %s\n",
dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
if (!S_ISCHR (st.st_mode)) {
fprintf (stderr, "%s is no device\n", dev_name);
exit (EXIT_FAILURE);
}
fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf (stderr, "Cannot open ’%s’: %d, %s\n",
dev_name, errno, strerror (errno));
exit (EXIT_FAILURE);
}
}
static void usage (FILE * fp,int argc,char ** argv)
{
fprintf (fp,
"Usage: %s [options]\n\n"
"Options:\n"
"-d | --device name Video device name [/dev/video]\n"
"-h | --help Print this message\n"
"-m | --mmap Use memory mapped buffers\n"
"-r | --read Use read() calls\n"
"-u | --userp Use application allocated buffers\n"
"",
argv[0]);
}
static const char short_options [] = "d:hmru";
static const struct option
long_options [] = {
{ "device", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "mmap", no_argument, NULL, 'm' },
{ "read", no_argument, NULL, 'r' },
{ "userp", no_argument, NULL, 'u' },
{ 0, 0, 0, 0 }
};
int main ()
{
int i_tmp = 0;
#if 0
char dev_0[] ="/dev/video0"
char dev_1[] ="/dev/video1"
char dev_2[] ="/dev/video2"
char dev_3[] ="/dev/video3"
#endif
while (1){
for(i_tmp = 0; i_tmp < 4; i_tmp++)
{
switch(i_tmp) {
case 0 :
strcpy(dev_name,"/dev/video0");
//dev_name = "/dev/video0";
break;
case 1 :
strcpy(dev_name,"/dev/video1");
//dev_name = "/dev/video1";
break;
case 2 :
strcpy(dev_name,"/dev/video2");
//dev_name = "/dev/video2";
break;
case 3 :
strcpy(dev_name,"/dev/video3");
//dev_name = "/dev/video3";
break;
}
bp = open ("/dev/fb0",O_RDWR);
if (bp < 0)
{
printf("Error : Can not open framebuffer device/n");
exit(1);
}
if (ioctl(bp,FBIOGET_FSCREENINFO,&finfo))
{
printf("Error reading fixed information/n");
exit(2);
}
if (ioctl(bp,FBIOGET_VSCREENINFO,&vinfo))
{
printf("Error reading variable information/n");
exit(3);
}
vinfo.xres = MY_WIDTH;
vinfo.yres = MY_HEIGHT;
if (ioctl(bp,FBIOPUT_VSCREENINFO,&vinfo))
{
printf("Error setting variable information/n");
exit(3);
}
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
fbp =(char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, bp,0);
if ( fbp == MAP_FAILED )
{
printf ("Error: failed to map framebuffer device to memory./n");
close(bp);
exit (4);
}
// graphics or text-> ioctl(tty_fd,KDSETMODE,KD_TEXT);
tty=open("/dev/tty1",O_RDWR);
ioctl(tty,KDSETMODE,KD_GRAPHICS);
/* undo press key to stop capture!!!!!!!!*/
// key = open("/dev/input/event",O_RDONLY);
open_device ();
init_device ();
start_capturing ();
mainloop ();
stop_capturing ();
clear();
uninit_device ();
close_device ();
}
}
#if 0
exit (EXIT_SUCCESS);
#endif
return 0;
}