嵌入式linux中V4L2应用程序开发

嵌入式linux中有标准的V4L2协议,很多摄像头驱动和应用都是基于V4L2来进行的,一般情况下,摄像头的设备号为/dev/video0

#define DEVICE_NAME /dev/video0

一 、 打开设备

int fd;

<pre name="code" class="cpp">void open_device(void)
{
    fd = open(DEVICE_NAME, O_RDWR /*| O_NONBLOCK */, 0);
}


 二 、 ioctl命令控制函数 

void v4l2_ioctl(int  fd,  int  request, void * arg)
{
	int r;
	 r = ioctl (fd, request, arg);
}

三 、 参数初始化

int v4l2_setpara(void)
{
	struct v4l2_capability  cap;
	struct v4l2_cropcap cropcap;
	struct v4l2_streamparm parm = {0};
	struct v4l2_streamparm parm2 = {0};
	struct v4l2_crop crop;
	struct v4l2_format fmt;
	unsigned int min;
	
	if (-1 == v4l2_ioctl (fd, VIDIOC_QUERYCAP, &cap)) 				// 查询v4l2驱动功能
	{
	    if (EINVAL == errno)   //如果v4l2设备与内核驱动不兼容,则errno为EINVAL
		{
	        printf("fd is no V4L2 device\n");
	        return -1;
	    } 
		else return -2;
	}
	if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) 
	{
		printf("fd is no video capture device\n");
		return -3;
	}
    if (!(cap.capabilities & V4L2_CAP_STREAMING)) //判断设备是否支持视频流方式
	{
        printf ("fd does not support streaming i/o\n");
        return -4;
	}
    /* Select video input, video standard and tune here. */
	memset(&cropcap,0,sizeof(cropcap));
    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (0 == v4l2_ioctl (fd, VIDIOC_CROPCAP, &cropcap)) 	// 查询裁剪能力,驱动会填充cropcap的其它成员
	{
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        crop.c = cropcap.defrect; 									    // 恢复成默认值
        if (-1 == v4l2_ioctl (fd, VIDIOC_S_CROP, &crop))    //重新设置裁剪参数
		{
            switch (errno) 
			{
                case EINVAL:
                    /* Cropping not supported. */
                    break;
                default:
                    /* Errors ignored. */
                    break;
            }
        }
    } 
	memset(&fmt,0,sizeof(fmt));
    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width       = v4l2cappara.width;
    fmt.fmt.pix.height      = v4l2cappara.height;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; //这种图像格式两个像素占四个字节,其中每Y分量占两个字节,即一个像素。每Cb,Cr分别占一个字节
    fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
    if (-1 == xioctl (v4l2cappara.v4l2fd, VIDIOC_S_FMT, &fmt))    //设置视频捕获格式
	{
        perror("VIDIOC_S_FMT:");
	    return -5;
	}

    /* Note VIDIOC_S_FMT may change width and height. */
    /* Buggy driver paranoia. */
    min = fmt.fmt.pix.width * 2;				// 是16位色的????????????????????
    if (fmt.fmt.pix.bytesperline < min)fmt.fmt.pix.bytesperline = min;
    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
    if (fmt.fmt.pix.sizeimage < min)fmt.fmt.pix.sizeimage = min;

/*	parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (xioctl(v4l2cappara.v4l2fd, VIDIOC_G_PARM, &parm) == -1) 
	{
		printf("set frame rate failed\n");
	}
	printf("frame time1: %d/%d  capturemode = %d  capability = %d\n",parm.parm.capture.timeperframe.numerator
		,parm.parm.capture.timeperframe.denominator,parm.parm.capture.capturemode,parm.parm.capture.capability);

	parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	parm.parm.capture.timeperframe.numerator = 1001;
	parm.parm.capture.timeperframe.denominator = 20000;
	if (xioctl(v4l2cappara.v4l2fd, VIDIOC_S_PARM, &parm) == -1) 
	{
		printf("set frame rate failed\n");
	}*/
	return 1;
}

四 、 内存初始化

int v4l2_meminit(void)
{
	struct v4l2_requestbuffers req;
	int count,count_max;
	memset(&req,0,sizeof(req));
    req.count               = 2;
    req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory              = V4L2_MEMORY_MMAP;
    if (-1 == v4l2_ioctl (fd, VIDIOC_REQBUFS, &req))	// 向驱动申请分配缓冲区
	{
        if (EINVAL == errno) 
		{
            printf ("fd does not support memory mapping\n");
          	return -5;
        } 
		else return -6;
    }
    if (req.count < 2) 
	{
        printf ("Insufficient buffer memory on fd\n");
        return -7;
    }
	count_max = req.count;
	if(req.count > V4L2BUFNUM)count_max = V4L2BUFNUM;
    for (count = 0; count < count_max; ++count) 
	{
        struct v4l2_buffer buf;
		memset(&buf,0,sizeof(buf));
        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = count;
        if (-1 == v4l2_ioctl (fd, VIDIOC_QUERYBUF, &buf))
		{
			printf("fd VIDIOC_QUERYBUF error\n");	// 得到物理内存位置
			return -9;
        }
        v4l2cappara.v4l2capturebuf[count].length = buf.length;
        v4l2cappara.v4l2capturebuf[count].start =  mmap (NULL /* start anywhere */,buf.length, PROT_READ | PROT_WRITE /* required */,
                      MAP_SHARED /* recommended */,v4l2cappara.v4l2fd, buf.m.offset);						// 关联到用户空间
        if (MAP_FAILED == v4l2cappara.v4l2capturebuf[count].start)
		{
			printf("encaputre fd init error mmap\n");
			return -10;
		}
    }
	v4l2cappara.bufcount = count_max;

	int i;
	for (i = 0; i < v4l2cappara.bufcount; ++i) 
    {
        struct v4l2_buffer buf;
		memset(&buf,0,sizeof(buf));
        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory      = V4L2_MEMORY_MMAP;
        buf.index       = i;
        if (-1 == v4l2_ioctl (fd, VIDIOC_QBUF, &buf))  //将申请到的帧缓冲入队列,以便存放采集到的数据
		{
			printf("encapture error VIDIOC_QBUF\n");
			return -1;
		}
    }
	return 1;
}

五 、 开始获取视频

int v4l2_startcapturing(void)
{
    enum v4l2_buf_type type;
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (-1 == v4l2_ioctl (fd, VIDIOC_STREAMON, &type))  //开始视频采集
	{
		printf("encapture error VIDIOC_STREAMON\n");
		return -2;
    }
	return 1;
}

六、 结束获取视频

void v4l2_stop_capturing(void)
{
	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	v4l2_ioctl(fd, VIDIOC_STREAMOFF, &type);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值