linux 摄像头拍照例程

/*
* 这段代码的功能是使用Linux下的库函数拍一张照片,并且保存起来
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include "jpeg_enc.h"

#define     VW             320
#define     VH             240

#define     SER_PORT       4455
#define     BUF_SIZE       1024

int main(int argc,char *argv[])
{
	int devFd,ret;
	if(argc!=2)
    {
       fprintf(stderr,"use:[%s][DEV]\n",argv[0]);
       return 1;
    }

	/******************* open device *********************/
	
    devFd=open(argv[1],O_RDWR);
	if(devFd==-1)
    {
        perror(argv[1]);
        return -1;
    }
	/**************** 查询当前设备支持什么格式 *********************/
	
    struct v4l2_fmtdesc fmtdc;
    fmtdc.index=0;
    fmtdc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

    ret=ioctl(devFd,VIDIOC_ENUM_FMT,&fmtdc);
    if(ret==-1)
    {
       perror("ENUM FMT");
       close(devFd);
       return -2;
    }
    printf("idx:%d flags:%d  fmtName:%s\n",fmtdc.index,fmtdc.flags,fmtdc.description);
    
	//set fmt
    struct v4l2_format  fmt;
    fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;//流式数据
    fmt.fmt.pix.width =VW;
    fmt.fmt.pix.height=VH;
    fmt.fmt.pix.pixelformat=fmtdc.pixelformat;
    ret=ioctl(devFd,VIDIOC_S_FMT,&fmt);
    if(ret==-1)
    {
        perror("set fmt");
        return -4;
    }
	 printf("idx:%d flags:%d  fmtName:%s\n",fmtdc.index,fmtdc.flags,fmtdc.description);
	 if(fmtdc.pixelformat!=V4L2_PIX_FMT_YUYV)
	{
		printf("format is not YUYV\n");
		return ;
	}

	/***************** 申请采集图形的缓存与映射缓存到用户空间 ******************************/
	//用于申请缓存的结构体
    struct v4l2_requestbuffers  buffers;
    buffers.type     =V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffers.memory   =V4L2_MEMORY_MMAP;
    buffers.count    =1;
    ret=ioctl(devFd,VIDIOC_REQBUFS,&buffers);
    if(ret==-1)
    {
        perror("request buffers");
        close(devFd);
        return;
    }
	
	//将申请到的缓存映射到用户空间,这里的摄像头驱动应该是标准驱动
	//用于配置缓存信息的结构体 struct v4l2_buffer - video buffer info
	struct v4l2_buffer   buf;
	memset(&buf,0,sizeof(buf));
	buf.index     =0;
    buf.type      =V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory=V4L2_MEMORY_MMAP;
	//请求一帧缓存
    ret=ioctl(devFd,VIDIOC_QUERYBUF,&buf);
    if(ret==-1)
    {
         perror("query buffer");
         close(devFd);
         return -5;
    }

	//把缓存空间映射到用户空间的mapAddr
	//通过mapAddr访问图像数据
	void *mapAddr = NULL;
	int mapAddrLen;
	mapAddr = mmap(NULL,buf.length,PROT_READ,MAP_SHARED,devFd,buf.m.offset);
	if(mapAddr==MAP_FAILED)
        {
            perror("mmap mem");
            close(devFd);
            return -6;
        }
	mapAddrLen = buf.length;
	
	//将其放入采集队列
	ret=ioctl(devFd,VIDIOC_QBUF,&buf);
        if(ret==-1)
        {
            munmap(mapAddr,mapAddrLen);
            perror("buffer in queue");
            close(devFd);
            return -7;
        }

	//打开摄像头
    enum v4l2_buf_type  type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret=ioctl(devFd,VIDIOC_STREAMON,&type);
    if(ret==-1)
    {
        munmap(mapAddr,mapAddrLen);
        perror("start video");
        close(devFd);
        return -8;
    }

	printf("camera starts successfully...\n");
	printf("snap...\n");

	/*******************采集图像数据**************************************/
	
	buf.type      =V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory=V4L2_MEMORY_MMAP;
	//out queue <如果没采集好 则阻塞>
    ret=ioctl(devFd,VIDIOC_DQBUF,&buf);
    if(ret==-1)
    {
        perror("get yuv data");
        return 0;
    }

	char picData[(VW)*(VH)*4];
	if(buf.length < (VW)*(VH)*4)
	{
		memcpy(picData,mapAddr,buf.length);
		printf("buf.legth = %d\n",buf.length);
	}
	else
	{
		perror("picData[] is too smallto recv data\n");
		printf("buf.legth = %d\n",buf.length);
		return -9;
	}

	char jpegData[(VW)*(VH)*4];
	int jpegLen = encode_image(mapAddr,jpegData,20,VW,VH);

	int jFd = open("j.jpeg",O_RDWR,O_CREAT|O_TRUNC);
	if(jFd < 0)
	{
		perror("open j.jpeg");
		close(devFd);
		munmap(mapAddr,mapAddrLen);
		return -10;
	}

	ret = write(jFd,jpegData,jpegLen);

	close(jFd);
	close(devFd);
	munmap(mapAddr,mapAddrLen);
	return 0;
}





  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值