linux中的USB摄像头驱动(应用层)(基于V4L2)

V4L2 是 Video4Linux2 的缩写,是 Linux 内核中的一个视频设备驱动接口。 

 USB-V4L2 初始化流程

1.打开设备节点 open

2.配置参数:分辨率,fps,格式 ioctl

3.请求分配帧缓存->地址映射

4.加入队列中

/********************************************************************************* @file    usbcamera.c* @author  CJ* @version V1.0* @date    2020/8* @brief******************************************************************************* @attention*******************************************************************************/#include "usbcamera.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include static UsbCameraSyspara g_cameraSyspara;bool usbCamera_init()
{/* 1、打开设备节点 */g_cameraSyspara.fd = open("/dev/video0", O_RDWR);if(g_cameraSyspara.fd < 0){printf("Camera device failed to open !\n");return false;}/* 2、定义v4l2_format结构体变量并完成赋值 */memset(&g_cameraSyspara.tV4l2Fmt, 0, sizeof(struct v4l2_format));g_cameraSyspara.tV4l2Fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	//视频捕获g_cameraSyspara.tV4l2Fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//设置输出图像尺寸g_cameraSyspara.tV4l2Fmt.fmt.pix.width  = 1280;g_cameraSyspara.tV4l2Fmt.fmt.pix.height = 720;g_cameraSyspara.tV4l2Fmt.fmt.pix.field  = V4L2_FIELD_ANY;	//驱动自行选择合适的格式(逐行、隔行)接收images/* 3、调用IOCTL完成以上参数配置 */if(ioctl(g_cameraSyspara.fd, VIDIOC_S_FMT, &g_cameraSyspara.tV4l2Fmt) != 0){printf("tV4l2Fmt failed !\n");return false;}printf("w = %d, h = %d\n", g_cameraSyspara.tV4l2Fmt.fmt.pix.width, g_cameraSyspara.tV4l2Fmt.fmt.pix.height);printf("size = %d\n", g_cameraSyspara.tV4l2Fmt.fmt.pix.sizeimage);printf("format = %x, nv12 = %x\n", g_cameraSyspara.tV4l2Fmt.fmt.pix.pixelformat, V4L2_PIX_FMT_YUYV);g_cameraSyspara.RGBData=(unsigned char*)malloc(g_cameraSyspara.tV4l2Fmt.fmt.pix.sizeimage);/* 4、定义v4l2_request结构体变量并完成赋值 */memset(&g_cameraSyspara.tV4l2ReqBuffs, 0, sizeof(struct v4l2_requestbuffers));g_cameraSyspara.tV4l2ReqBuffs.count   = 10;								//帧缓存个数g_cameraSyspara.tV4l2ReqBuffs.memory  = V4L2_MEMORY_MMAP;				//该缓存支持映射g_cameraSyspara.tV4l2ReqBuffs.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;	//视频捕获支持/* 5、调用IOCTL请求分配帧缓存 */ioctl(g_cameraSyspara.fd, VIDIOC_REQBUFS, &g_cameraSyspara.tV4l2ReqBuffs);/* 6、将帧缓存映射至进程空间 */unsigned int i;for(i = 0;i < g_cameraSyspara.tV4l2ReqBuffs.count;i++){memset(&g_cameraSyspara.tV4l2Buf, 0, sizeof(struct v4l2_buffer));g_cameraSyspara.tV4l2Buf.index = i;								//帧缓存编号g_cameraSyspara.tV4l2Buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;	//视频捕获支持g_cameraSyspara.tV4l2Buf.memory = V4L2_MEMORY_MMAP;				//内存映射支持//调用IOCTL获取每个帧缓存的相关信息,其中长度、偏移量将作为mmap的参数ioctl(g_cameraSyspara.fd, VIDIOC_QUERYBUF, &g_cameraSyspara.tV4l2Buf);//映射空间地址g_cameraSyspara.MyVideBuf[i] = (unsigned char *)mmap(0, g_cameraSyspara.tV4l2Buf.length, PROT_READ,MAP_SHARED, g_cameraSyspara.fd, g_cameraSyspara.tV4l2Buf.m.offset);}/* 7、将帧缓存加入队列循环采集 */for (i = 0; i >!!!!!!!!!!!!!!!!!!: Frame rate: %u/%u\n",ret, Stream_Parm.parm.capture.timeperframe.numerator,Stream_Parm.parm.capture.timeperframe.denominator);Stream_Parm.parm.capture.timeperframe.numerator = 1;Stream_Parm.parm.capture.timeperframe.denominator = 15;printf("ret = %d >>!!!!!!!!!!!!!!!!!!: Frame rate: %u/%u\n",ret, Stream_Parm.parm.capture.timeperframe.numerator,Stream_Parm.parm.capture.timeperframe.denominator);ret = ioctl(g_cameraSyspara.fd, VIDIOC_S_PARM, &Stream_Parm);printf("ret = %d >>!!!!!!!!!!!!!!!!!!: Frame rate: %u/%u\n",ret, Stream_Parm.parm.capture.timeperframe.numerator,Stream_Parm.parm.capture.timeperframe.denominator);return true;
}bool openUsbCamera()
{int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE;/* 启动摄像头开始采集 */if(ioctl(g_cameraSyspara.fd, VIDIOC_STREAMON, &iType) == 0){return true;}return false;
}bool clsoeUsbCamera()
{int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE;if(ioctl(g_cameraSyspara.fd, VIDIOC_STREAMOFF, &iType) == 0){return true;}return false;
}unsigned char *getUsbCameraImage(unsigned int *size)
{fd_set readfds;unsigned int ListNum;FD_ZERO(&readfds);FD_SET(g_cameraSyspara.fd,&readfds);struct timeval tv;unsigned int time1, time2;gettimeofday(&tv, NULL);time1 = tv.tv_sec*1000000+tv.tv_usec;select(g_cameraSyspara.fd+1, &readfds, NULL, NULL, NULL);gettimeofday(&tv, NULL);time2 = tv.tv_sec*1000000+tv.tv_usec;printf("time = %dms\n", (time2-time1)/1000);memset(&g_cameraSyspara.tV4l2Buf, 0, sizeof(struct v4l2_buffer));g_cameraSyspara.tV4l2Buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;g_cameraSyspara.tV4l2Buf.memory  = V4L2_MEMORY_MMAP;/* read data */ioctl(g_cameraSyspara.fd, VIDIOC_DQBUF, &g_cameraSyspara.tV4l2Buf);ListNum = g_cameraSyspara.tV4l2Buf.index;	//数据地址 MyVideBuf[ListNum]memset(&g_cameraSyspara.tV4l2Buf, 0, sizeof(struct v4l2_buffer));g_cameraSyspara.tV4l2Buf.index  = ListNum;g_cameraSyspara.tV4l2Buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;g_cameraSyspara.tV4l2Buf.memory = V4L2_MEMORY_MMAP;ioctl(g_cameraSyspara.fd, VIDIOC_QBUF, &g_cameraSyspara.tV4l2Buf);  //将缓冲区再次放入队列*size = g_cameraSyspara.tV4l2Fmt.fmt.pix.sizeimage;printf("format cnt = %d\n", ListNum);return g_cameraSyspara.MyVideBuf[ListNum];
}
/********************************************************************************* @file    usbcamera.h* @author  CJ* @version V1.0* @date    2020/8* @brief******************************************************************************* @attention*******************************************************************************/
#ifndef USB_CAMERA_H
#define USB_CAMERA_H#include "stdbool.h"
#include typedef struct _UsbCameraSyspara
{int fd;unsigned char *RGBData;              //解码struct v4l2_format  tV4l2Fmt;struct v4l2_buffer tV4l2Buf;			//缓存区的相关信息unsigned char* MyVideBuf[10];			//映射的空间地址struct v4l2_requestbuffers tV4l2ReqBuffs;
}UsbCameraSyspara;bool usbCamera_init();
bool openUsbCamera();
bool clsoeUsbCamera();
unsigned char *getUsbCameraImage(unsigned int *size);
#endif


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部