V4L2(Video For Linux Two) 是内核提供给应用程序访问音、视频驱动的统一接口。V4L2 的相关定义包含在头文件<linux/videodev2.h> 中.
基本参照:
https://blog.csdn.net/li_wen01/article/details/53557949
大部分代码搬过来用了。
在此记录下。
流程如下:
IOCTL使用的命令
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
extern int ioctl (int __fd, unsigned long int __request, …) __THROW;
__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;
__request:具体的命令标志符。
在进行V4L2开发中,一般会用到以下的命令标志符:
VIDIOC_REQBUFS:分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
VIDIOC_S_FMT:设置当前驱动的频捕获格式
VIDIOC_G_FMT:读取当前驱动的频捕获格式
VIDIOC_TRY_FMT:验证当前驱动的显示格式
VIDIOC_CROPCAP:查询驱动的修剪能力
VIDIOC_S_CROP:设置视频信号的边框
VIDIOC_G_CROP:读取视频信号的边框
VIDIOC_QBUF:把数据从缓存中读取出来
VIDIOC_DQBUF:把数据放回缓存队列
VIDIOC_STREAMON:开始视频显示函数
VIDIOC_STREAMOFF:结束视频显示函数
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
这些IO调用,有些是必须的,有些是可选择的。
我的摄像头支持的型号:
support device 1.YUV 4:2:2 (YUYV)
support device 2.MJPEG
整理代码如下:
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include <linux/videodev2.h>
#define VIDEO_NAME "/dev/video0"
#define TEST_STREAM_SAVE_PATH "/app/sd"
#define BUFFER_NUM (4)
#define V4L2_BUF_TYPE (V4L2_BUF_TYPE_VIDEO_CAPTURE)
static int g_video_fd;
typedef struct{
void *start;
int length;
}BUFTYPE;
BUFTYPE *usr_buf;
static unsigned int n_buffer = 0;
static int HI_PDT_Camera_Open(void)
{
struct v4l2_input inp;
int i = 0;
int ret = -1;
g_video_fd = open(VIDEO_NAME, O_RDWR | O_NONBLOCK,0);
if(g_video_fd < 0)
{
printf("%s open failed ! \n", VIDEO_NAME);
return ret;
};
for(i=0;i<16;i++)
{
inp.index = i;
if (-1 == ioctl (g_video_fd, VIDIOC_S_INPUT, &inp))
{
printf("VIDIOC_S_INPUT failed %d !\n",i);
}
else
{
printf("VIDIOC_S_INPUT success %d !\n",i);
ret = 0;
break;
}
}
return ret;
}
// close
void HI_PDT_Camera_Close(int video_fd)
{
unsigned int i;
for(i = 0;i < n_buffer; i++)
{
if(-1 == munmap(usr_buf[i].start,usr_buf[i].length))
{
exit