V4L2应用程序详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*
* V4L2 video capture example
*
* This program can be used and distributed without restrictions.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CLEAR(x) memset(&(x), 0, sizeof (x))
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 io_method io = IO_METHOD_MMAP; static int fd = -1;
struct buffer * buffers = NULL;
static unsigned int n_buffers = 0;
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;
}
static void process_image(const void *p)
{
FILE* fp;
fp = fopen("test","w+"); //w+:打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
fputs(p, fp); //成功,返回一个非负整数;出错,返回EOF。fputs(const char *s,FILE *stream)作用:向指定文件写入一个字符串,缓冲区S中保存的是以‘/0’结尾的字符串,fputs将该字符串写入stream,但不写入结尾的’/0’。
fclose(fp);
// fflush(stdout); // fflush(stdout):清空输出缓冲区,并把缓冲区内容输出
}
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: //当使用不可阻断(O_NONBLOCK)打开文件后,read呼叫无可读取的数据
return 0;
case EIO: //设备文件读取文件时发生输出输入错误
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("read");
}
}
process_image(buffers[0].start); //保存读到的数据
break;
/* V4L2有一个数据缓存,存放req.count数量的缓存数据。数据缓存采用FIFO的方式,当应用程序调用缓存数据时,缓存队列将最先采集到的视频数据缓存送出,并重新采集一张视频数据。这个过程需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF*/ case IO_METHOD_MMAP:
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
/*出队列以取得采集数据的帧缓冲,取得原始的采集数据*/
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); //assert的作用是计算括号内的表达式,如果其值为0,就先向stderr打印一条出错信息,然后通过abort来终止程序运行
process_image(buffers[buf.index].start);
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)