#ifndef __COMMON_H
#define __COMMON_H
//该头文件定义的是摄像头在屏幕上显示的宽度和高度
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include <stdint.h>

typedef unsigned char U8;
typedef unsigned int U32;
typedef unsigned short U16;

#define WIDTH  800
#define HEIGHT 600

#endif	//__COMMON_H
#ifndef __VIDEOCAPTURE_H
#define __VIDEOCAPTURE_H

#include"common.h"
#include<sys/mman.h>
#include<fcntl.h>
#include<linux/videodev2.h>

#define VIDEODEVNAME ("/dev/video0")
#define COUNT  4
//需要调用的摄像头相关的接口,包括初始化,开始,结束,采取一帧的数据并保存
int initCamera();
void unInitCamera();
int startCamera();
int stopCamera();
int getOneFrame(U8* pcYuvBuffer);

#endif	//__VIDEOCAPTURE_H
#include"videoCapture.h"

static U8* pcYuv[COUNT]={NULL};
static int vidDevFd = -1;
static int nLength = 0;
static struct v4l2_buffer dequeBuffer;
static struct v4l2_buffer queueBuffer;

//初始化摄像头程序
int initCamera()
{
	//open /dev/video*
	//open video device
	vidDevFd = open(VIDEODEVNAME, O_RDONLY);
	if (vidDevFd < 0)
	{
		fprintf(stderr, "open %s failed %s\n",VIDEODEVNAME, strerror(errno));
		return -1;
	}

	//printf("vidDevFd = %d!\n", vidDevFd);			

	//设置视频格式
	//set video device format
	struct v4l2_format vidDevFmt;
	vidDevFmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	vidDevFmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
	vidDevFmt.fmt.pix.width = WIDTH;
	vidDevFmt.fmt.pix.height = HEIGHT;

	if (0 != ioctl(vidDevFd, VIDIOC_S_FMT, &vidDevFmt))
	{
		fprintf(stderr, "VIDIOC_S_FMT failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}

	//request buffers
	//max count need to be considered
	struct v4l2_requestbuffers reqBuffer;
	reqBuffer.count = COUNT;
	reqBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	reqBuffer.memory = V4L2_MEMORY_MMAP;

	if (0 != ioctl(vidDevFd, VIDIOC_REQBUFS, &reqBuffer))
	{
		fprintf(stderr, "VIDIOC_REQBUFS failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}

	//query buffers
	int i = 0;
	struct v4l2_buffer qryBuffer;
	qryBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	qryBuffer.memory = V4L2_MEMORY_MMAP;

	for (i = 0; i < COUNT; i++)
	{
		qryBuffer.index = i;

		if (0 != ioctl(vidDevFd, VIDIOC_QUERYBUF, &qryBuffer))
		{
			fprintf(stderr, "VIDIOC_QUERYBUF failed %s\n", strerror(errno));
			unInitCamera();
			return -1;
		}

		printf("qryBuffer.m.offset=%d, qryBuffer.lenght=%d\n", qryBuffer.m.offset, qryBuffer.length);
		//mmap video device memory allocated by VIDIOC_REQBUFS
		pcYuv[i] = mmap(NULL, qryBuffer.length, PROT_READ, MAP_SHARED, vidDevFd, qryBuffer.m.offset);
		nLength = qryBuffer.length;

		//queue buffers
		struct v4l2_buffer queBuffer;
		queBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		queBuffer.memory = V4L2_MEMORY_MMAP;
		queBuffer.index = qryBuffer.index;
		if (0 != ioctl(vidDevFd, VIDIOC_QBUF, &queBuffer))
		{
			fprintf(stderr, "init VIDIOC_QBUF failed %s\n", strerror(errno));
			unInitCamera();
			return -1;
		}

	}

	dequeBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	dequeBuffer.memory = V4L2_MEMORY_MMAP;
	queueBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	queueBuffer.memory = V4L2_MEMORY_MMAP;

	return 0;
}

//取消摄像头
void unInitCamera()
{
	int i = 0;

	for (i = 0; i < COUNT; i++)
	{
		if (NULL != pcYuv[i])
		{
			if (-1 == munmap(pcYuv[i], nLength));
			{
				//fprintf(stderr,"munmap error:%s!\n",strerror(errno));
			}
			pcYuv[i] = NULL;
		}
	}

	if (vidDevFd >= 0)
		close(vidDevFd);
}
//摄像头开始
int startCamera()
{
	//start camera		

	int nArg = 1;
	if (0 != ioctl(vidDevFd, VIDIOC_STREAMON, &nArg))
	{
		fprintf(stderr, "VIDIOC_STREAMON failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}

	return 0;
}

//停止摄像头
int stopCamera()
{
	//stop camera		

	int nArg = 1;
	if (0 != ioctl(vidDevFd, VIDIOC_STREAMOFF, &nArg))
	{
		fprintf(stderr, "VIDIOC_STREAMOFF failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}

	return 0;
}

//获取Frame
int getOneFrame(unsigned char* pcYuyvBuffer)
{
	if (0 != ioctl(vidDevFd, VIDIOC_DQBUF, &dequeBuffer))
	{
		fprintf(stderr, "VIDIOC_DQBUF failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}

	//get frame
	memcpy(pcYuyvBuffer, pcYuv[dequeBuffer.index], dequeBuffer.length);
	printf("len=%d\n",dequeBuffer.length);

	//queue
	queueBuffer.index = dequeBuffer.index;
	if (0 != ioctl(vidDevFd, VIDIOC_QBUF, &queueBuffer))
	{
		fprintf(stderr, "VIDIOC_QBUF failed %s\n", strerror(errno));
		unInitCamera();
		return -1;
	}
	return 0;
}
#include"videoCapture.h"

int main(void )
{
	int nRet = 0;
	//char yuyv[WIDTH*HEIGHT*2];
	char* pcYuvBuffer = NULL; 

	if(-1 == initCamera())
	{
		printf("initCamera failed!\n");
		goto ERR;
	}

	if (-1 == startCamera())
	{
		printf("startCamera failed!\n");
		goto ERR;
	}

	pcYuvBuffer = (char*)malloc((WIDTH*HEIGHT*2)*sizeof(char));
	if (NULL == pcYuvBuffer)
	{
		printf("malloc YUYV buffer failed!\n");
		goto ERR;
	}

	int nDstFd = open("mytest.yuv", O_CREAT|O_EXCL|O_RDWR|O_TRUNC, 0777);
	if (nDstFd == -1)
	{
		fprintf(stderr, "open mytest.yuv failed:%s\n", strerror(errno));
	}

	int nFrameNum = 0;

	while(1)
	{
		if (20 == nFrameNum)
			break;

		memset(pcYuvBuffer, 0, WIDTH*HEIGHT*2);

		//if (-1 == getOneFrame(yuyv))
		if (-1 == getOneFrame(pcYuvBuffer))
		{
			printf("getOneFrame error!\n");
			goto ERR;
		}

		//if (-1 == write(nDstFd, yuyv, WIDTH*HEIGHT*2))
		if (-1 == write(nDstFd, pcYuvBuffer, WIDTH*HEIGHT*2))
		{
			fprintf(stderr, "write error:%s\n", strerror(errno));
			goto ERR;
		}

		nFrameNum++;
	}

	if (-1 == stopCamera())
	{
		printf("stopCamera error!\n");
	}

ERR:
	if (NULL != pcYuvBuffer)
	{
		free(pcYuvBuffer);
		pcYuvBuffer = NULL;
	}

	unInitCamera();

	close(nDstFd);
	nDstFd = -1;

	return 0;
}

基于V4L2摄像头采集图片程序设计的更多相关文章

  1. Linux 下V4l2摄像头采集图片,实现yuyv转RGB,RGB转BMP,RGB伸缩,jpeglib 库实现压缩RGB到内存中,JPEG经UDP发送功(转)

    ./configure CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld --host=arm-linux --prefix=/usr/loca ...

  2. 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】

    转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...

  3. 14、USB摄像头(V4L2接口)的图片采集

    参考网站http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一.一些知识 1.V4L和V4L2. V4L是 ...

  4. 基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)

            编写带界面的图像处理程序,选择opencv+mfc是一种很好的选择:在读取摄像头数据方面,网上的方法很多,其中shiqiyu的camerads的方法是较好的.       基于现有资料 ...

  5. 基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)持续更新

            编写带界面的图像处理程序,选择opencv+mfc是一种很好的选择:在读取摄像头数据方面,网上的方法很多,其中shiqiyu的camerads的方法是较好的.       基于现有资料 ...

  6. 基于视频压缩的实时监控系统-sprint1基于epoll架构的采集端程序设计

    part1:产品功能 part2:epoll机制   select与epoll区别 1.select与epoll没有太大的区别.除了select有文件描述符限制(1024个),select每次调用都需 ...

  7. V4L2视频采集原理

    一.简介 Video for Linuxtwo(Video4Linux2)简称V4L2,是V4L的改进版.V4L2是linux操作系统下用于采集图片.视频和音频数据的API接口,配合适当的视频采集设备 ...

  8. linux之V4L2摄像头应用流程【转】

    本文转载自:http://blog.csdn.net/tommy_wxie/article/details/11486907 对于v4l2,上次是在调试收音机驱动的时候用过,其他也就只是用i2c配置一 ...

  9. Linux之V4L2视频采集编程详解

     V4L2(Video For Linux Two) 是内核提供给应用程序访问音.视频驱动的统一接口. Linux系统中,视频设备被当作一个设备文件来看待,设备文件存放在 /dev目录下,完整路径的设 ...

随机推荐

  1. [BZOJ]4908: [BeiJing2017]开车

    Time Limit: 30 Sec  Memory Limit: 256 MB Description 你有n辆车,分别a1, a2, ..., an位置和n个加油站,分别在b1, b2, ... ...

  2. WiFi认证中HTTPS重定向

    问题描述 在引入WiFiDog实现上网认证功能中,有2个绕不过的问题:https重定向和Select检测问题,前者非要求用户访问80端口,后者导致效率较低下.就用户体验来说,https无法主动重定向非 ...

  3. Scrapy框架

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以 ...

  4. H3C交换机如何配置管理VLAN

    1.输入"system-view"(简写"sys"),进入系统配置模式[H3C],2.下面就可以开始取消默认管理vlan了,输入"undo inter ...

  5. Java instanceof 关键字是如何实现的?

    作者:RednaxelaFX链接:https://www.zhihu.com/question/21574535/answer/18998914来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...

  6. 我在 Ubuntu 下使用 Sublime 编写 python 代码时遇到并解决的问题

    Ubuntu 下 Sublime 无法输入中文 解决方法如下: sudo apt-get update && sudo apt-get upgrade 克隆项目到本地 : git cl ...

  7. 2. struct A 和 typedef struct A

    2. struct A 和 typedef struct A 2.1 struct A struct A{}定义一个名为struct A的结构体. 下例定义了struct A同时,声明了两个变量(注意 ...

  8. 转:rabbitMQ 安装与管理

    安装环境 虚拟机:VMware® Workstation 10.0.1 build Linux系统:CentOS6.5 官方安装:http://www.rabbitmq.com/install-rpm ...

  9. React 系列教程 1:实现 Animate.css 官网效果

    前言 这是 React 系列教程的第一篇,我们将用 React 实现 Animate.css 官网的效果.对于 Animate.css 官网效果是一个非常简单的例子,原代码使用 jQuery 编写,就 ...

  10. FJUT第四周寒假作业之第一集,临时特工?(深度优先搜索)

    原网址:http://210.34.193.66:8080/vj/Contest.jsp?cid=163#P2 第一集,临时特工? TimeLimit:1000MS  MemoryLimit:128M ...