linux中一个视频采集程序
大家好,现在做设计遇到一个问题,就是用在网上找的V4L程序采集图像只能采集到一张,但是我们想连续采集到多张,就设置了一个定时,但是还是只能采集到一张JPG图片,程序我会贴出来,请大家帮忙解决。我个人感觉应该是连续采集到的图像覆盖到了一个地址问题,但是个人的C语言学得不好。其他情况是,ubuntu10.10的系统,ZC301的摄像头,目前还只是在PC机上实现功能。希望各位高手能帮我看一下该怎么修改,因为快要答辩了,所以情况比较着急。。。
#include <unistd.h>
#include "v4l.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <error.h>
#include <sys/types.h>
#include <linux/videodev.h>
#define norm VIDEO_MODE_NTSC
#define DEFAULT_FILE_NAME "picture"
#define DEFAULT_DEVICE "/dev/video0"
int v4l_open(char *dev,v4ldevice *vd)
{
if (!dev)
dev = DEFAULT_DEVICE;
if((vd->fd=open(dev,O_RDWR | O_NONBLOCK,10705))<0) //非阻塞方式打开
{
return -1;
}else{
printf("open success!!!!\n");
}
if(v4l_get_capability(vd)<0)
{return -1;}else{
printf("\n===========Get struct video_capability==============\n");
printf(vd->capability.name);printf(", Type:%d\n",vd->capability.type);
printf("Maxwidth:%d,Maxheight:%d\n",vd->capability.maxwidth ,vd->capability.maxheight);
printf("Minwidth:%d,Minheight:%d\n",vd->capability.minwidth,vd->capability.minheight);
printf("Channels:%d,Audios:%d\n",vd->capability.channels,vd->capability.audios);}
if(v4l_get_picture(vd)<0)
{return -1;}else{
printf("\n==============Get struct video_picture1===============\n"); //修改前获得的图像信息
printf("Brightness:%d,Hue:%d,Colour:%d\n",vd->picture.brightness,vd->picture.hue,vd->picture.colour);
printf("Contrast:%d,Whiteness:%d(Black and white only)\n",
vd->picture.contrast,vd->picture.whiteness);
printf("Capture depth:%d,Palette:%d\n",vd->picture.depth,vd->picture.palette);
}
//return 0;gcc版本: 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
printf("\n===============Set vpic.palette to VIDEO_PALETTE_YUV420P,and picture.depth to 16.========\n");
vd->picture.palette=VIDEO_PALETTE_YUV420P; // 设置调色板 设置图像格式 对应 videodev.h 中107行
vd->picture.depth=14; // 设置象素深度
//vd->picture.hue = 25854 ; // 色调
// vd->picture.colour= 25854 ; //
//vd->picture.brightness = 22869 ; //亮度
// vd->picture.contrast = 22768 ; //对比度
// vd->picture.whiteness= 29321 ; //色度
if(ioctl(vd->fd, VIDIOCSPICT, &vd->picture)==-1) // 设置图像特性
{ fprintf(stderr, "Unable to find a supported capture format.\n");
close(vd->fd);
exit(1);
}else{
printf("\n==============Get struct video_picture2===============\n");//修改后获得的信息
printf("Brightness:%d,Hue:%d,Colour:%d\n",vd->picture.brightness,vd->picture.hue,vd->picture.colour);
printf("Contrast:%d,Whiteness:%d(Black and white only)\n",
vd->picture.contrast,vd->picture.whiteness);
printf("Capture depth:%d,Palette:%d\n",vd->picture.depth,vd->picture.palette);
}
return 0;
}
int v4l_get_capability(v4ldevice *vd)
{
if(ioctl(vd->fd,VIDIOCGCAP,&(vd->capability))<0)
{
perror("v4l_get_capability:");
return -1;
}
return 0;
}
int v4l_get_picture(v4ldevice *vd)
{
if(ioctl(vd->fd,VIDIOCGPICT,&(vd->picture))<0) //获取图像特征数据结构
{
perror("v4l_get_picture");
return -1;
}
return 0;
}
/*int v4l_set_norm(v4ldevice *vd, int norm) //我的设备获取的信息就一个channel 备注了此段
{
int i;
for (i = 0; i < vd->capability.channels; i++) {
vd->channel[i].norm = norm;}
return 0;
}*/
int v4l_grab_init(v4ldevice *vd,int width,int height) //初始化
{
vd->mmap.width=width;
vd->mmap.height=height;
vd->mmap.format=vd->picture.palette;
vd->frame=0;
vd->framestat[0]=0;
vd->framestat[1]=0;
return 0;
}
int v4l_mmap_init(v4ldevice *vd)
{
if(v4l_get_mbuf(vd)<0)
return -1;
if((vd->map=mmap(0,vd->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,vd->fd,0))<0)
{
return -1;
}
return 0;
}
int v4l_get_mbuf(v4ldevice *vd)//查询实际可用的缓存数
{
if(ioctl(vd->fd,VIDIOCGMBUF,&(vd->mbuf))<0)
{
perror("v4l_get_mbuf:");
return -1;
}
printf("size=%d\n",vd->mbuf.size);
return 0;
}
int v4l_grab_start(v4ldevice *vd,int frame) //开始
{
vd->mmap.frame=frame;
if(ioctl(vd->fd,VIDIOCMCAPTURE,&(vd->mmap))<0)
{
exit(-1);
return -1;
}
vd->framestat[frame]=1;
return 0;
}
int v4l_grab_sync(v4ldevice *vd,int frame)
{
if(ioctl(vd->fd,VIDIOCSYNC,&frame)<0)
{
return -1;
}
vd->framestat[frame]=0;
return 0;
}
unsigned char * v4l_get_address(v4ldevice *vd)
{
return (vd->map+vd->mbuf.offsets[vd->frame]);
}
int v4l_close(v4ldevice *vd)
{
close(vd->fd);
return 0;
}
int main()
{
char *buffer=NULL;
v4ldevice VD;
v4ldevice *vd=&VD;
int frame=0;
int f_d;
int loop_count = 100;
int sleep_time_milsec = 1000;//睡1秒
char file_name[100];
if(0==v4l_open("/dev/video0",vd)) //打开设备
printf("open success!\n");
else
printf("open failure\n");
// set (vd);
/* if(0==v4l_set_norm(vd,norm))
printf("set_norm success\n");
else
printf("set_norm failure\n"); */
if(0==v4l_grab_init(vd,CIF_WIDTH,CIF_HEIGHT))//初始化设备,定义获取图像的大小
printf("init success!\n");
else
printf("init failure\n");
if(0==v4l_mmap_init(vd))//内存映射
printf("memory map success!\n");
else
printf("memory map failure\n");
while (loop_count)
{
if(0==v4l_grab_start(vd,frame))//开始获取图像
printf("get picture success!\n");
else
{
printf("get picture failure\n");
break;
}
v4l_grab_sync(vd,frame);//等待传完一帧
buffer=(char *)v4l_get_address(vd);//得到这一帧的地址
printf("img address %p\n",buffer);
sprintf(file_name, "%s - %d", DEFAULT_FILE_NAME, frame);
f_d=open(file_name,O_RDWR|O_CREAT,0666);//获取文件的描述符 打开piture 文件 返回其描述符 DEFAULT_FILE_NAME 在前面开始定义
write(f_d,buffer,CIF_WIDTH*3*CIF_HEIGHT);//保存到文件中 写入piture 文件中
close(f_d);
sleep(sleep_time_milsec);
loop_count--;
frame++;
}
v4l_close(vd);
return 0;
}
菜鸟在线急等。。。。