您的位置:首页 > 其它

v4l2 视频采集流程程序

2013-04-24 21:09 483 查看


v4l2 视频采集流程程序

/******************v4l2.c******************/

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <linux/videodev.h>

#ifdef ANDROID_ENV

#define LOG LOGV

#else

#define LOG //

#endif

#define CAMERA_DEVICE "/dev/video0"

#define VIDEO_WIDTH 640

#define VIDEO_HEIGHT 480

#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV

#define BUFFER_COUNT 1

struct fimc_buffer {

int length;

void *start;

} framebuf[BUFFER_COUNT];

int main()

{

int i, ret;

int j,k,n,m;

char name[10]={0};

int flag=1;

int fd;

fd = open(CAMERA_DEVICE, O_RDWR, 0);//设备以非阻塞方式打开

if (fd < 0)

{

LOG("Open %s failed/n", CAMERA_DEVICE);

return -1;

}

struct v4l2_capability cap;

ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);//摄像头主要功能获取

if (ret < 0)

{

LOG("VIDIOC_QUERYCAP failed (%d)/n", ret);

return ret;

}

struct v4l2_format fmt; //设置视频制式和帧格式

memset(&fmt, 0, sizeof(fmt));

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

fmt.fmt.pix.width = VIDEO_WIDTH;

fmt.fmt.pix.height = VIDEO_HEIGHT;

fmt.fmt.pix.pixelformat = VIDEO_FORMAT;

fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

ret = ioctl(fd, VIDIOC_S_FMT, &fmt);

if (ret < 0)

{

LOG("VIDIOC_S_FMT failed (%d)/n", ret);

return ret;

}

ret = ioctl(fd, VIDIOC_G_FMT, &fmt);//获取视频制式和帧格式的实际值,看是否设置正确

if (ret < 0)

{

LOG("VIDIOC_G_FMT failed (%d)/n", ret);

return ret;

}

struct v4l2_requestbuffers reqbuf;//向驱动申请帧缓冲

reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

reqbuf.memory = V4L2_MEMORY_MMAP;

reqbuf.count = BUFFER_COUNT;

ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);

if(ret < 0)

{

LOG("VIDIOC_REQBUFS failed (%d)/n", ret);

return ret;

}

struct v4l2_buffer buf;//获取帧缓冲地址

for(i=0; i<BUFFER_COUNT; i++)

{

buf.index = i;

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory = V4L2_MEMORY_MMAP;

ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);

if(ret < 0)

{

LOG("VIDIOC_QUERYBUF (%d) failed (%d)/n", i, ret);

return ret;

}

framebuf[i].length = buf.length;

framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);//将申请到的帧缓冲映射到用户空间,就能直接操作采集的帧

if (framebuf[i].start == MAP_FAILED)

{

LOG("mmap (%d) failed: %s/n", i, strerror(errno));

return -1;

}

ret = ioctl(fd , VIDIOC_QBUF, &buf);//将申请到的帧缓冲全部入队列,以便存放数据

if (ret < 0)

{

LOG("VIDIOC_QBUF (%d) failed (%d)/n", i, ret);

return -1;

}

}

enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//开始视频采集

ret = ioctl(fd, VIDIOC_STREAMON, &type);

if (ret < 0)

{

LOG("VIDIOC_STREAMON failed (%d)/n", ret);

return ret;

}

while(1)

{

for(k=0;k<10;k++)

{

ret = ioctl(fd, VIDIOC_DQBUF, &buf);//出队列以取得已采集数据的帧缓冲,取得原始数据

if (ret < 0)

{

LOG("VIDIOC_DQBUF failed (%d)/n", ret);

return ret;

}

strcpy(name,"a.jpeg");

name[0]='a'+k;

FILE *fp = fopen(name, "wb");

if (fp < 0)

{

LOG("open frame data file failed/n");

return -1;

}

fwrite(framebuf[buf.index].start, 1, buf.length, fp);

fclose(fp);

ret = ioctl(fd, VIDIOC_QBUF, &buf);//将缓冲重新入对尾,可以循环采集

if (ret < 0)

{

LOG("VIDIOC_QBUF failed (%d)/n", ret);

return ret;

}

}

}

for (i=0; i<BUFFER_COUNT; i++)

{

munmap(framebuf[i].start, framebuf[i].length);//取消映射,释放内存

}

close(fd);

LOG("Camera test Done./n");

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: