linux v4l2 视频,V4L2框架下的视频采集

该代码展示了如何在Linux环境下使用V4L2(Video for Linux Two)框架来实现从摄像头采集视频,并将每一帧图片保存到本地,模拟动态视频效果。首先打开设备节点/dev/video0,然后设置视频格式,分配缓冲区,进行内存映射,最后通过循环读取帧数据并保存为图片文件。
摘要由CSDN通过智能技术生成

本代码主要是配合自己搭建的网络服务器,在做视频采集时通过在发送本地拍摄10张图片。并依次的轮流刷新这10张图片。已达到动态的视频效果。其这段代码的主要功能是拍摄10张图片并保存于本地。框架是基于linux下的V4L2框架的。

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include

#include

#include

#include

#include

#define BUFFER_COUNT 4

#define CLEAR(x) memset (&(x), 0, sizeof (x))

FILE *file_fd; const char *file_name[] ={"1.jpg", "2.jpg", "3.jpg", "4.jpg",

"5.jpg","6.jpg", "7.jpg", "8.jpg", "9.jpg", "10.jpg"};

int file_index =0;

typedef struct VideoBuffer

{

void *start;

size_t length;

}VideoBuffer;

typedef __u64 v4l2_std_id;

static void errno_exit(

const char *

s)

{ fprintf(stderr, "%s error %d, %s\n" , s, errno,

strerror(errno)); exit(EXIT_FAILURE); }

int main(int argc, char* argv[])

{

int cameraFd,ret,numBufs;

cameraFd = open("/dev/video0", O_RDWR, 0);

//设备节点由具体设备改变/dev/xxxxx 非阻塞方式打开

printf("The cameraFd is %d \n",cameraFd);

struct v4l2_capability cap;

ret = ioctl(cameraFd, VIDIOC_QUERYCAP, &cap);

//VIDIOC_QUERYCAP:查询驱动功能

if (ret < 0)

{

printf("VIDIOC_QUERYCAP failed

(%d)\n", ret);

return ret;

} struct v4l2_format fmt;

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

fmt.fmt.pix.width = 320; //640

fmt.fmt.pix.height = 240; //480

fmt.fmt.pix.pixelformat =

V4L2_PIX_FMT_MJPEG;

fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

ret = ioctl(cameraFd, VIDIOC_S_FMT,

&fmt);

if (ret < 0) //VIDIOC_S_FMT:设置当前驱动的频捕获格式

{

printf("VIDIOC_S_FMT failed

(%d)\n", ret);

return ret;

}

struct v4l2_requestbuffers reqbuf; reqbuf.count =

BUFFER_COUNT;

reqbuf.type =

V4L2_BUF_TYPE_VIDEO_CAPTURE;

reqbuf.memory =

V4L2_MEMORY_MMAP;

printf("The requestbuffers size is %d

\n",sizeof(reqbuf));

if (ioctl(cameraFd, VIDIOC_REQBUFS, &reqbuf) == -1)

{

printf("Rquestbuffers

fail..\n");

return ret;

}

VideoBuffer* buffers = calloc(

reqbuf.count, sizeof(*buffers) );//在内存中分配4个Buffer

struct

v4l2_buffer buf;

printf("\n");

printf("The buffers addres = 0x%x\n", (unsigned

int )&buf);

printf("The

buf.length = %d \n", buf.length);

printf("\n");

for (numBufs = 0; numBufs < reqbuf.count;

numBufs++)

{

buf.type =

V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory =

V4L2_MEMORY_MMAP;

buf.index =

numBufs; //索引分配的buffers个数在以后的运算中有用

// 读取缓存

ret = ioctl(cameraFd,

VIDIOC_QUERYBUF, &buf);

if (ret < 0)

{

printf("VIDIOC_REQBUFS

fail ..\n");

return

ret;

}

buffers[numBufs].start = (char

*)mmap(0, buf.length, PROT_READ | PROT_WRITE,

MAP_SHARED,cameraFd,

buf.m.offset);

printf("The buf.length = %d \n", buf.length);

if (buffers[numBufs].start == MAP_FAILED)

{

return

-1;

}

// 放入缓存队列

ret = ioctl(cameraFd,

VIDIOC_QBUF, &buf);

if(ret < 0)

{

printf("VIDIOC_QBUF failed (%d)\n",ret);

return

ret;

}

printf("buffers[%d].start =

0x%x, length=%d\n", numBufs, (unsigned int)buffers[numBufs].start,

sizeof(buffers[numBufs]));

printf("The buf.index = %d

\n",buf.index);

}

//获取数据到文件

enum v4l2_buf_type type =

V4L2_BUF_TYPE_VIDEO_CAPTURE;

ret = ioctl(cameraFd, VIDIOC_STREAMON,

&type);

if(ret < 0)

{

printf("VIDIOC_STREAMON failed

(%d)\n", ret);

return 0;

}

int num = 0;

char pic_buf[100*1024] ={'0'};

while(1)

{

int r,read_ret;;

// CLEAR (buf);

buf.type =

V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory =

V4L2_MEMORY_MMAP; do r =

ioctl(cameraFd, VIDIOC_DQBUF, &buf); while (-1 == r

&& EINTR == errno); if ((ret ==

ioctl(cameraFd, VIDIOC_DQBUF, &buf)) < 0)

{ switch (errno)

{ case EAGAIN: return 0; case EIO: default

: printf("VIDIOC_DQBUF

failed (%d)\n", ret); } } assert(buf.index <

numBufs); if(file_index == 10)

{

file_index

= 0;

printf("you

got 10 pic file_index = %d \n", file_index);

}

FILE *fp = fopen(file_name[file_index++], "wb");

fputc('#' , stdout);

if(buf.length > 0)

{

fputc('#' ,

stdout);

fwrite(buffers[buf.index].start,

1, buf.length/6, fp);

}

fflush(stdout);

fclose(fp);

ret = ioctl(cameraFd, VIDIOC_QBUF, &buf);

if (ret < 0)

{

printf("VIDIOC_QBUF

failed (%d)\n", ret);

return

ret;

}

} // 释放内存 清空buffer区

for (numBufs=0; numBufs< reqbuf.count;

numBufs++)

{

munmap(buffers[numBufs].start,

buffers[numBufs].length);

}

close(cameraFd);

printf("The camera is close \n");

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值