基本信息
源码名称:Linux平台上USB摄像头的测试和开发
源码大小:0.02M
文件格式:.zip
开发语言:C/C++
更新时间:2015-11-23
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
#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); }