基本信息
源码名称: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);
}