折腾了好几天还是不行,只好把源代码贴上来给大家看看:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#define VIDEO_WIDTH 320
#define VIDEO_HEIGHT 240
#define CLEAR(x) memset(&(x),0,sizeof(x))
struct fimc_buffer{
int length;
void *start;
}framebuf[4];
static int read_frame(int fd)
{
struct v4l2_buffer buf;
int ret;
unsigned int i;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd,VIDIOC_DQBUF,&buf);
if(ret < 0)
{
printf("dqbuf error\n");
return -1;
}
// assert(buf.index < 4);
printf("buf.index dq is %d\n",buf.index);
FILE *fp;
fp = fopen("test.jpg","wb");
if(fp == NULL)
{
printf("open file error\n");
return -1;
}
fwrite(framebuf[buf.index].start,1,buf.length,fp);
fclose(fp);
printf("capture one frame over\n");
ret = ioctl(fd,VIDIOC_QBUF,&buf);
if(ret < 0)
{
printf("vidioc failue\n");
return -1;
}
return 1;
}
int main() {
int i,ret,fd;
printf("open video start\n");
fd = open("/dev/video0",O_RDWR,0);
if(fd < 0) {
printf("open device error\n");
return -1;
}
struct v4l2_capability cap;
ret = ioctl(fd,VIDIOC_QUERYCAP,&cap);
if(ret < 0 )
{
printf("video query failed\n");
return ret;
}
if((cap.capabilities && V4L2_CAP_VIDEO_CAPTURE) != 1)
{
printf("not support v4l2_cap_video_capture\n");
return -1;
}
if((cap.capabilities & V4L2_CAP_STREAMING) ==0)
{
printf("NOT SUPPORT V4L2_CAP_STREAM\n");
return -1;
}
printf("capability over\n");
struct v4l2_format fmt;
CLEAR(fmt);
fmt.fmt.pix.width = 480;
fmt.fmt.pix.height = 272;
fmt.fmt.pix.sizeimage = 480*272*2;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.field = V4L2_FIELD_ANY;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
ret = ioctl(fd,VIDIOC_S_FMT,&fmt);
printf("fmt.type is %d\n",fmt.type);
printf("fmt.fmt.pix.width = %d\n",fmt.fmt.pix.width);
printf("fmt.fmt.pix.heigth= %d\n",fmt.fmt.pix.height);
printf("fmt.fmt.pix.sizeimage = %d\n",fmt.fmt.pix.sizeimage);
if(ret < 0)
{
printf("vidioc_s_fmt error\n");
return -1;
}
struct v4l2_requestbuffers reqbuf;
memset(&reqbuf,0,sizeof(reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 4;
ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuf);
printf("req.type is %d\n",reqbuf.type);
printf("req.memory is %d\n",reqbuf.memory);
printf("req.count is %d\n",reqbuf.count);
printf("vidioc_reqbufs start\n");
if(ret < 0)
{
printf("vidioc_reqbufs error\n");
return -1;
}
printf("the reqbuf count is %d\n",reqbuf.count);
struct v4l2_buffer buf;
for(i = 0;i<4;++i)
{
buf.index = i;
buf.type = reqbuf.type;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd,VIDIOC_QUERYBUF,&buf);
printf("vidioc_querybuf start\n");
printf("the index is %d \n",i);
if(ret < 0){
printf("vidioc_querybuf error\n");
return -1;
}
printf("the buf length is %d\n",buf.length);
framebuf.length = buf.length;
framebuf.start = (char*)(mmap(0,buf.length,
PROT_READ|PROT_WRITE,MAP_SHARED,
fd,buf.m.offset));
if(framebuf.start == MAP_FAILED){
printf("mmap failed\n");
return -1;
}
printf("mmap over\n");
printf("queue buffer\n");
ret = ioctl(fd,VIDIOC_QBUF,&buf);
if(ret < 0){
printf("qbuf error\n");
return -1;
}
}
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd,VIDIOC_STREAMON,&type);
printf("capture start\n");
if(ret < 0)
{
printf("stream on error\n");
return -1;
}
for(;;)
{
fd_set fds;
struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
ret = select(fd+1,&fds,NULL,NULL,&tv);
if(-1 == ret )
if(EINTR == errno)
continue;
if(0 == ret){
printf("select timeout\n");
}
if(read_frame(fd) == 1)break;
}
read_frame(fd);
ret = ioctl(fd,VIDIOC_STREAMOFF,&type);
if(ret < 0)
{
printf("capture off\n");
return -1;
}
for(i = 0;i < 4;i++)
{
munmap(framebuf.start,framebuf.length);
}
close(fd);
printf("camera test done\n");
return 0;
}