在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例Android手机应用开发 → Linux平台上USB摄像头的测试和开发

Linux平台上USB摄像头的测试和开发

Android手机应用开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:0.02M
  • 下载次数:32
  • 浏览次数:564
  • 发布时间:2015-11-23
  • 实例类别:Android手机应用开发
  • 发 布 人:小马哥
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 摄像头 linux 测试 开发

实例介绍

【实例简介】
【实例截图】

【核心代码】

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>     
#include <fcntl.h>      
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <asm/types.h>       
#include <linux/videodev2.h>
#include "simplified_jpeg_encoder.h"   
#include "v4l2_head.h"
#define FRAME_NUM 100
#define MAXSIZE 1024
#define BACKLOG 10
#define MAX_CONNECTED_NO 10
#define SERVPORT 3333
#define ERR_EXIT(m) \	
	do  \	
	{ 	\		
		perror(m); \		
		exit(EXIT_FAILURE); \	
	} while(0)

static struct vdIn *videoIn;
/*       #define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y', 'U', 'Y', 'V') //16  YUV 4:2:2     
#define v4l2_fourcc(a, b, c, d)\
	((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))

 */
int main(int argc, char **argv)
{
    char  *dev = "/dev/video2";
    int  width = 320, height = 240, fps = 5;
	int format = V4L2_PIX_FMT_YUYV; 	/*jpeg 只支持YUV颜色模式的数据结构,而不支持RGB图像数据结构*/
    int psize;
    unsigned char *pic_buf;
	int server_sockfd, client_sockfd;
	int server_len, client_len;
	int opt = 1;
	//unsigned int len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;

/***************图像采集**************/
    videoIn = malloc(sizeof(struct vdIn));
    if (videoIn == NULL)
		ERR_EXIT("not enough memory for videoIn\n");
    memset(videoIn, 0, sizeof(struct vdIn));

    printf("Using V4L2 device.: %s\n", dev);
    printf("Desired Resolution: %i x %i\n", width, height);
    printf("Frames Per Second.: %i\n", fps);
	
    /* 打开视频设备, 设定属性及采集方式 */
    if (init_videoIn(videoIn, dev, width, height, fps, format, 1) < 0)
        ERR_EXIT("init_VideoIn failed\n");	
    if (v4l2_Grab(videoIn) < 0)
        ERR_EXIT("Error grabbing frames\n");
	printf("All init is Ok... \n");
	//if (v4l2_get_framerate(videoIn) < 0)
	//	ERR_EXIT("Get_framerate failure\n");	
    /* 将videoIn里面的数据缓存framebuffer转化为jpg格式 并暂存在pic_buf中  */
	pic_buf=(unsigned char *) calloc(1, (videoIn->width * videoIn->height) << 1); //videoIn->width   videoIn->height
	/* s_encode_image(input_ptr, output_ptr, quality_factor, image_format, width, height,output_buffer_size) */	
	psize = s_encode_image(videoIn->framebuffer, pic_buf, 1024, FORMAT_CbCr422, videoIn->width, videoIn->height, videoIn->framesizeIn);

/*****************************socket配置****************************************/
	server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(server_sockfd < 0)
		ERR_EXIT("Creating socket error!\n");
	bzero(&server_address, sizeof(struct sockaddr_in));
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = htonl(INADDR_ANY);
	server_address.sin_port = htons(3333);
	
	setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	
	server_len = sizeof(server_address);
    if(bind(server_sockfd, (struct sockaddr *)&server_address, server_len) < 0)
		ERR_EXIT("Bind error...");
	printf("Bind success!\n");	
    if(listen(server_sockfd, BACKLOG) == -1)
		ERR_EXIT("listen error!\n");
	printf("listen success!\n");
	
	int SIZE = 0;
	int i , j = 0;
	int num = 0, val;
	char buff[1024];
	char size_buff[255*1024];
	char r_val[0], count;
	char recv_buff[12];
	char send_buff[1034];
	struct timeval tv;
	fd_set readfd;
	
	tv.tv_sec  = 10;
	tv.tv_usec = 0;
	FD_ZERO(&readfd);
	FD_SET(server_sockfd, &readfd);
	
	client_len = sizeof(client_address);
	client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

	write(client_sockfd, pic_buf, psize);
	
    /* 接下来将数据存到文件中  */
	//process_image(buf, psize);
    close_v4l2(videoIn);
	return 0;
}

int init_videoIn(struct vdIn *vd, char *device, int width, int height, int fps, int format, int grabmethod)
{
    if (vd == NULL || device == NULL)
        return -1;
    if (width == 0 || height == 0)
        return -1;
    if (grabmethod < 0 || grabmethod > 1)
        grabmethod = 1;		
    vd->videodevice = NULL;
    vd->status = NULL;
    vd->pictName = NULL;
    vd->videodevice = (char *) calloc (1, 16 * sizeof (char));
    vd->status = (char *) calloc (1, 100 * sizeof (char));
    vd->pictName = (char *) calloc (1, 80 * sizeof (char));
    snprintf (vd->videodevice, 12, "%s", device);
    vd->width = width;
    vd->height = height;
    vd->fps = fps;
    vd->formatIn = format;  		/* 视频数据存储类型 */
    vd->grabmethod = grabmethod;    /* 视频采集方式   */
	
    if (init_v4l2 (vd) < 0)
        ERR_EXIT(" Init v4L2 failed !! exit fatal \n");
	
    vd->framesizeIn = (vd->width * vd->height << 1);
	vd->framebuffer =(unsigned char *) calloc(1, (size_t) vd->framesizeIn);
    if (!vd->framebuffer)
        goto error;
    return 0;
error:
    free(vd->videodevice);
    free(vd->status);
    free(vd->pictName);
    close(vd->fd);
    return -1;
}
/******************************************************************************************/
int init_v4l2(struct vdIn *vd)
{
    int i;
    int ret = 0;
    if ((vd->fd = open(vd->videodevice, O_RDWR)) == -1)
        ERR_EXIT("ERROR opening V4L interface \n");
	if(Debug){	
		printf("\nBefore set_format......\n");	
		if (v4l2_get_format(vd) < 0)
			exit(1);
	} 	
   /* 检测设备功能*/
    memset(&vd->cap, 0, sizeof(struct v4l2_capability));
    ret = ioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
    if (ret < 0)
        ERR_EXIT("Error opening device  : unable to query device.\n");

    if ((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0)
        ERR_EXIT("Error opening device : video capture not supported.\n");

   /*   三种视频采集方式:使用read、write方式、 内存映射方式和用户指针模式。
    *	数据采集方式 ,这里选择streaming :  V4L2_CAP_STREAMING -> V4L2_MEMORY_MMAP  
    */
    if (vd->grabmethod)
    {
        if (!(vd->cap.capabilities & V4L2_CAP_STREAMING))
            ERR_EXIT("Does not support streaming i/o\n");
    }
    else
    {
        if (!(vd->cap.capabilities & V4L2_CAP_READWRITE))
            ERR_EXIT("Does not support read i/o\n"); 
    }
    /*
     * 设置 视频捕获格式
     */
	ret = v4l2_set_foramt(vd);
    if (ret < 0)    
		ERR_EXIT("Set format err!\n"); 
    /*
     * 设置 framerate
     */
	 if(v4l2_set_framerate(vd) < 0)
		perror("v4l2_set_framerate failure\n");
    /*
     * 分配 buffers
     */
    memset(&vd->rb, 0, sizeof(struct v4l2_requestbuffers));
    vd->rb.count = NB_BUFFER;                    /* 缓存数量,也就是说在缓存队列里保持多少张照片 */
    vd->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   /* 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE */
    vd->rb.memory = V4L2_MEMORY_MMAP;            /* 采集方式为mmap*/

    if (ioctl(vd->fd, VIDIOC_REQBUFS, &vd->rb) < 0)
        ERR_EXIT("Unable to allocate buffers");
    /*    
	 * 使用VIDIOC_REQBUFS, 获取了rb.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令
	 * 来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列 	
     */
    for (i = 0; i < NB_BUFFER; i  )
    {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index  = i;
        vd->buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
		/*  VIDIOC_REQBUFS 获取这些缓存的地址 */
        ret = ioctl(vd->fd, VIDIOC_QUERYBUF, &vd->buf);
        if (ret < 0)
            ERR_EXIT("Unable to query buffer");    
		/* 转换成绝对地址 */
        vd->mem[i] = mmap(0, vd->buf.length, PROT_READ, MAP_SHARED, vd->fd,vd->buf.m.offset);
        if (vd->mem[i] == MAP_FAILED)
            ERR_EXIT("Unable to map buffer");
		ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);   /*  放入缓存队列 */
    }
    /*    放入缓存队列
     */ 
    /*for (i = 0; i < NB_BUFFER;   i)
    {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
        if (ret < 0)
            ERR_EXIT("Unable to queue buffer");
    }*/
	return 0;
}

/*************************************************************/
int v4l2_Grab(struct vdIn *vd)
{
    int ret;
    memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
    vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->buf.memory = V4L2_MEMORY_MMAP;
    ret = ioctl(vd->fd, VIDIOC_STREAMON, &vd->buf.type); /* 开始视频显示函数  */
    if (ret < 0)
        ERR_EXIT("Unable to start capture");
    /*  把数据从缓存中读取出来   */ 
    ret = ioctl(vd->fd, VIDIOC_DQBUF, &vd->buf);
    if (ret < 0)
        ERR_EXIT("Unable to dequeue buffer");
    /* 把数据复制到 framebuffer 中 */
    if (vd->buf.bytesused > vd->framesizeIn)
        memcpy (vd->framebuffer, vd->mem[vd->buf.index], (size_t) vd->framesizeIn);
    else
        memcpy (vd->framebuffer, vd->mem[vd->buf.index], (size_t) vd->buf.bytesused);
    /*   把数据放回缓存队列 ,这样可以循环采集 */
    ret = ioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
    if (ret < 0)
        ERR_EXIT("Unable to requeue buffer");
	if ( ioctl(vd->fd, VIDIOC_STREAMOFF, &vd->buf.type) == -1 )
		ERR_EXIT("VIDIOC_STREAMOFF\n");
    return 0;
}
int checkframer(struct vdIn*vd)
{
	struct timeval old_tvl, tvl;	
	double time;
	unsigned int i, fps;
	
	gettimeofday(&old_tvl, NULL);
	for (i = 0; i < FRAME_NUM; i  )
	{
		read_frame(vd);
	}
	gettimeofday(&tvl, NULL);
	time = ((tvl.tv_sec   tvl.tv_usec * 0.000001) -
		    	(old_tvl.tv_sec   old_tvl.tv_usec * 0.000001));
	fps = FRAME_NUM / time;
	printf(" fps is %d\n", fps);
	return 0;
}
void read_frame(struct vdIn*vd)
{
	memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
    vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->buf.memory = V4L2_MEMORY_MMAP;
	
	if (ioctl(vd->fd, VIDIOC_DQBUF, &vd->buf) == -1 )
			ERR_EXIT ("VIDIOC_DQBUF");
	if (ioctl(vd->fd, VIDIOC_QBUF, &vd->buf) < 0)
			ERR_EXIT ("VIDIOC_QBUF");
}
int v4l2_get_format(struct vdIn* vd)
{
	int width, height, formatIn;
	printf("v4l2_get_format...\n");
    memset(&vd->fmt, 0, sizeof(struct v4l2_format));
    vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(vd->fd, VIDIOC_G_FMT, &(vd->fmt)) == -1)
        perror("can not get format");

    formatIn = vd->fmt.fmt.pix.pixelformat;
    printf("format(num):%d\n",formatIn);

    char code[5];
    int i=0;
    for (i=0; i<4; i  )
        code[i] = (formatIn & (0xff<<i*8)) >> i*8;
    code[4] = 0;
    printf("fomat(human readable):%s\n",code);

    width 		= vd->fmt.fmt.pix.width;
    height 		= vd->fmt.fmt.pix.height;

    printf("width:%d\n", width);
    printf("height:%d\n", height);   
    printf("get fomat OK!\n");
    printf("===============================\n");
    return 0;
}
int v4l2_set_foramt(struct vdIn* vd)
{
	int ret;
	printf("v4l2_set_foramt...\n");
    memset(&vd->fmt, 0, sizeof(struct v4l2_format));
    vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;     /* 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE */
    vd->fmt.fmt.pix.width = vd->width;
    vd->fmt.fmt.pix.height = vd->height;
    vd->fmt.fmt.pix.pixelformat = vd->formatIn;     /* 原始数据格式为: V4L2_PIX_FMT_YUYV */
    vd->fmt.fmt.pix.field = V4L2_FIELD_ANY;
    ret = ioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt);
    if (ret < 0)
        ERR_EXIT("Unable to set format \n");
	
    if ((vd->fmt.fmt.pix.width != vd->width) || (vd->fmt.fmt.pix.height != vd->height))
    {
        fprintf(stderr, " format asked failure get width %d height %d \n", vd->fmt.fmt.pix.width, vd->fmt.fmt.pix.height);
        vd->width = vd->fmt.fmt.pix.width;
        vd->height = vd->fmt.fmt.pix.height;
    }
	
    if (vd->fmt.fmt.pix.pixelformat!= vd->formatIn)
    {
        char fourcc1[5]={0,0,0,0,0};
        char fourcc2[5]={0,0,0,0,0};
        memmove(fourcc1, (char*)&vd->formatIn, 4);
        memmove(fourcc2, (char*)&vd->fmt.fmt.pix.pixelformat, 4);
        fprintf(stderr, " requested %s but got %s format \n", fourcc1, fourcc2);
        vd->formatIn = vd->fmt.fmt.pix.pixelformat;
    }
	printf("v4l2_set_foramt  is ok...\n");
	return 0;
}
int v4l2_set_framerate(struct vdIn* vd)
{
    //vd->setfps = (struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
    memset(&vd->setfps, 0, sizeof(struct v4l2_streamparm));
    vd->setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->setfps.parm.capture.timeperframe.numerator = 1;  		/*  分子 */
    vd->setfps.parm.capture.timeperframe.denominator = vd->fps; /*  分母 */
    if( ioctl(vd->fd, VIDIOC_S_PARM, &vd->setfps) < 0)
		ERR_EXIT("VIDIOC_S_PARM failure \n");
	return 0;
}
int v4l2_get_framerate(struct vdIn* vd)
{
	int a = 0 ,b = 0;
	printf("v4l2_get_framerate:\n");
	//memset(&vd->setfps, 0, sizeof(struct v4l2_streamparm));
		
	if(ioctl(videoIn->fd, VIDIOC_G_PARM, &videoIn->setfps) == -1)
		ERR_EXIT("VIDIOC_S_PARM failure \n");
    a = vd->setfps.parm.capture.timeperframe.numerator ;
    b = vd->setfps.parm.capture.timeperframe.denominator ;
	
	printf("timeperframe.numerator: %d\n", a);
	printf("timeperframe.denominator: %d\n", b);
	return 0;
}

/******************************************************************/
void process_image(const void *p, ssize_t size)
{
    unsigned char *bbuf=(unsigned char *)p;
    static int no_image = 0;
    char filename[1024];
    int fd;
    ssize_t written = 0;
    int ret;
    snprintf(filename, sizeof(filename), "usbcam-%d.%s", no_image  , "jpg");
    fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (fd < 0)
		perror("open filename error\n");
    do{
        ret = write(fd, bbuf   written, size - written);
        if (ret < 0)
			perror("write error\n");
        written  = ret;
    }while (written < size);
    close(fd);
}

/********************************************/
void close_v4l2(struct vdIn *vd)
{
    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    int ret;

    ret = ioctl(vd->fd, VIDIOC_STREAMOFF, &type);
    if (vd->tmpbuffer)
        free(vd->tmpbuffer);
    vd->tmpbuffer = NULL;
    free(vd->framebuffer);
    vd->framebuffer = NULL;
    free(vd->videodevice);
    free(vd->status);
    free(vd->pictName);
    vd->videodevice = NULL;
    vd->status = NULL;
    vd->pictName = NULL;
    if (videoIn->tmpbuffer != NULL) free(videoIn->tmpbuffer);
    if (videoIn != NULL) free(videoIn);
}

实例下载地址

Linux平台上USB摄像头的测试和开发

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警