#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.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>
#include <linux/videodev2.h>
#include <time.h>
#include <strings.h>
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_BUFFER_COUNT 4
#define TEST_COUNT 20
void get_info(int fd)
{
printf("【**********************所有支持的格式及分辨率:****************************】\n");
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
struct v4l2_fmtdesc fmt_1;
struct v4l2_frmsizeenum frmsize;
struct v4l2_frmivalenum frmival;
fmt_1.index = 0;
fmt_1.type = type;
while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt_1) >= 0) {
printf("%d.%s\n",fmt_1.index+1,fmt_1.description);
frmsize.pixel_format = fmt_1.pixelformat;
frmsize.index = 0;
while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0){
if(frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE){
printf("\t%d.%dx%d\n",frmsize.index+1,frmsize.discrete.width, frmsize.discrete.height);
}
frmsize.index++;
}
fmt_1.index++;
}
printf("\n");
printf("【***********************获取帧率信息**************************】\n");
struct v4l2_streamparm Stream_Parm;
Stream_Parm.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_G_PARM,&Stream_Parm)==-1)
{
perror("ioctl");
exit(EXIT_FAILURE);
}
printf("Frame rate: %u/%u\n",
Stream_Parm.parm.capture.timeperframe.numerator,
Stream_Parm.parm.capture.timeperframe.denominator);
printf("\n");
}
void set_format(int fd)
{
printf("【***********************设置默认配置**************************>】\n");
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = DEFAULT_WIDTH; //宽度
fmt.fmt.pix.height =DEFAULT_HEIGHT; //高度
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //像素格式
// V4L2_PIX_FMT_YUYV
fmt.fmt.pix.field = V4L2_FIELD_ANY;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
{
printf("set format error\n");
close(fd);
exit(0);
}
printf("set defualt format successfuly\n");
if(ioctl(fd,VIDIOC_G_FMT,&fmt)<0)
{
printf("get format error\n");
close(fd);
exit(0);
}
printf("Current format:\n");
if(fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG )
{
printf("MJPEG:");
}
else if(fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
{
printf("YUYV:");
}
else
printf("unknown format:");
printf("%dx%d\n",fmt.fmt.pix.width,fmt.fmt.pix.height);
}
unsigned char * bufs[DEFAULT_BUFFER_COUNT]={0};
int i=0;
void unmap(int length)
{
int a ;
for(a=0;a< i ; a++)
munmap(bufs[i],length);
;
}
void video_test(int fd)
{
printf("【***********************测试**************************>】\n");
printf("共拍摄%d张图片\n",TEST_COUNT);
printf("一轮拍摄%d张图片\n",DEFAULT_BUFFER_COUNT);
int test_count = TEST_COUNT-DEFAULT_BUFFER_COUNT;
static int again =0;
struct v4l2_requestbuffers req;
req.count = DEFAULT_BUFFER_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(!again)
{
//申请缓冲,count是申请的数量
if(ioctl (fd, VIDIOC_REQBUFS, &req) < 0)
{
printf("failture VIDIOC_REQBUFS\n");
close(fd);
exit(0);
}
if (req.count < 2)
{
printf("req bufs error \n");
exit(-1);
}
}
int len ;
for (i = 0; i < req.count;i++)
{
struct v4l2_buffer buf;
bzero(&buf,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i ;
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)) //映射用户空间
{
printf ("VIDIOC_QUERYBUF error\n");
close(fd);
exit(0);
}
bufs[i] = mmap (NULL ,
buf.length,
PROT_READ ,
MAP_SHARED ,
fd,
buf.m.offset);
if (MAP_FAILED == bufs[i])
{
printf ("mmap failed\n");
goto err;
}
len=buf.length;
}
/*注意是先开启再QBUF*/
int on ;
on=V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd,VIDIOC_STREAMON,&on)<0)
{
perror("on");
return;
}
clock_t start,end;
int a =0;
FILE * fl=NULL;
fl=fopen("./test.jpg","w+");
start=clock();
while(test_count >0)
{
for(a=0;a<req.count;a++)
{
struct v4l2_buffer buf;
bzero(&buf,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = a;
if(ioctl(fd,VIDIOC_QBUF,&buf)<0)
{
printf("QBUF error\n");
goto err ;
}
}
for(a=0;a<req.count;a++)
{
struct v4l2_buffer dbuf;
bzero(&dbuf,sizeof(dbuf));
dbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
dbuf.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd,VIDIOC_DQBUF,&dbuf)<0)
{
printf("DQBUF error \n");
goto err ;
}
fwrite(bufs[a],1,dbuf.bytesused,fl);
fflush(fl);
}
printf("test_count = %d\n",test_count);
test_count -=req.count;
}
end=clock();
fclose(fl);
unmap(len);
double seconds =(double)(end - start)/CLOCKS_PER_SEC;
printf("end \n");
printf("use time %1.8f\n",seconds);
again= 1 ;
return ;
err:
unmap(len);
close(fd);
exit(0);
}
void main(int argc ,char * argv[])
{
if(argc != 2)
{
printf("usage: video_test /dev/video0\n");
exit(0);
}
int fd = open(argv[1],O_RDWR);
if(fd < 0)
{
printf("open video device error\n");
exit(0);
}
char select[30] = {0};
int result = 0;
retry:
printf("Welcome to video test\n");
printf("select:\n");
printf("1.get video message\n");
printf("2.set video message\n");
printf("3.video_test\n");
printf("4.exit\n");
printf("your select:");
scanf("%s",select);
result = strlen(select);
if(result != 1)
goto retry ;
if(select[0] > '4' || select[0] < '1')
goto retry ;
switch(select[0])
{
case '1':get_info(fd);
break;
case '2':
set_format(fd);
break;
case '3':
video_test(fd);
break;
case '4':
close(fd);
exit(0);
break;
}
goto retry ;
}