|
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define VIDEO_PALETTE_RAW_JPEG 20
#define VIDEO_PALETTE_JPEG 21
#define USB_VIDEO_DEV "/dev/v4l/video0"
#define FILE_NAME "/tmp/1.jpg"
#define STILL_IMAGE -1
#define VIDEO_START 0
#define VIDEO_STOP 1
static int debug = 1;
int get_jpegsize(unsigned char *buf, int size)
{
int i;
for(i = 1024; i < size; i++)
{
if ( (buf == 0xFF)&&(buf[i+1] == 0xD9)) return i+2;//jpeg文件格式中是以0xFF 0xD9结尾的,
//以此判断文件大小
}
return -1;
}
int main(int argc, char *argv[])
{
int usb_camera_fd = -1,framesize=0,jpegsize=0;
char *usb_video_dev = USB_VIDEO_DEV;
char *filename = FILE_NAME;
FILE *fp;
struct video_capability video_caps;
struct video_channel video_chan;
struct video_picture video_pic;
struct video_mbuf video_mbuffer;
struct video_mmap vid_mmap;
unsigned char *mapaddr=NULL,*framebuffer=NULL,*destbuffer=NULL;
usb_camera_fd = open(usb_video_dev,O_RDWR);//打开设备,可读写
if (usb_camera_fd == -1)
{
fprintf(stderr,"Can't open device %s",usb_video_dev);
return 1;
}
/**********************video_capability**************/
if (ioctl(usb_camera_fd,VIDIOCGCAP,&video_caps) == -1)//get videodevice capability 获取设备基本信息
{
perror("Couldn't get videodevice capability");
return -1;
}
if (debug)
{
printf("video name : %s\n",video_caps.name);
printf("video_caps.channels :%d\n",video_caps.channels);
printf("video_caps.type : 0x%x\n",video_caps.type);
printf("video maxwidth : %d\n",video_caps.maxwidth);
printf("video maxheight : %d\n",video_caps.maxheight);
printf("video minwidth : %d\n",video_caps.minwidth);
printf("video minheight : %d\n",video_caps.minheight);
}
/************************video_channel****************/
/*video_chan.channel = video_caps.channels;
if (ioctl(usb_camera_fd,VIDIOCGCHAN,&video_chan) == -1)//获取信号源的属性
{
perror("ioctl (VIDIOCGCAP)");
return -1;
}
if (debug)
{
printf("video channel: %d\n",video_chan.channel);
printf("video channel name: %s\n",video_chan.name);
printf("video channel type: %d\n",video_chan.type);
}*/
/*************************video_picture****************/
if (ioctl(usb_camera_fd,VIDIOCGPICT,&video_pic) == -1)//获取设备采集的图象的各种属性
{
perror("ioctl (VIDIOCGPICT)");
return -1;
}
/*video_pic.palette = VIDEO_PALETTE_JPEG;
video_pic.depth = 8;
video_pic.hue = 50110;
video_pic.whiteness = 41380;
if (ioctl(usb_camera_fd,VIDIOCSPICT,&video_pic) == -1)//设置设备采集的图象的属性
{
perror("ioctl (VIDIOCSPICT)");
//return -1;
}*/
if (debug)
{
printf("video_pic.brightness : %d\n",video_pic.brightness);
printf("video_pic.colour : %d\n",video_pic.colour);
printf("video_pic.contrast : %d\n",video_pic.contrast);
printf("video_pic.depth : %d\n",video_pic.depth);
printf("video_pic.hue : %d\n",video_pic.hue);
printf("video_pic.whiteness : %d\n",video_pic.whiteness);
printf("video_pic.palette : %d\n",video_pic.palette);
}
/************************video_mbuf**********************/
memset(&video_mbuffer,0,sizeof(video_mbuffer));
//初始化video_mbuf,以得到所映射的buffer的信息
if (ioctl(usb_camera_fd,VIDIOCGMBUF,&video_mbuffer) == -1)//video_mbuf
{
perror("ioctl (VIDIOCGMBUF)");
return -1;
}
if (debug)
{
printf("video_mbuffer.frames : %d\n",video_mbuffer.frames);
printf("video_mbuffer.offsets[0] : %d\nvideo_mbuffer.offsets[1] :%d\n",video_mbuffer.offsets [0],video_mbuffer.offsets[1]);
printf("video_mbuffer.size : %d\n",video_mbuffer.size);
}
//将mmap与video_mbuf绑定
mapaddr=(unsigned char *)mmap(0,video_mbuffer.size,PROT_READ,MAP_SHARED,usb_camera_fd, 0);
if (mapaddr < 0)
{
perror("v4l mmap");
return -1;
}
/********************video_mmap*************************/
vid_mmap.width = 320;
vid_mmap.height = 240;
vid_mmap.frame = 0;//单帧采集
vid_mmap.format = VIDEO_PALETTE_JPEG;
/**********************start capture********************///Mmap方式下真正开始视频截取
//若调用成功,开始一帧的截取,是非阻塞的 是否截取完毕留给VIDIOCSYNC来判断
if (ioctl(usb_camera_fd,VIDIOCCAPTURE,VIDEO_START) == -1)
{
perror("ioctl (VIDIOCCAPTURE)");
return -1;
}
/***********************wait for ready*******************///调用VIDIOCSYNC等待一帧截取结束
//若成功,表明一帧截取已完成。可以开始做下一次 VIDIOCMCAPTURE
//frame是当前截取的帧的序号
/*if (ioctl(usb_camera_fd, VIDIOCSYNC, &vid_mmap.frame) == -1)
{
perror("ioctl (VIDIOCSYNC)");
//return -1;
}*/
framesize=320*240>>2;//实际采集到的jpeg图像的大小最多也就十几KB
//获取刚刚采集到的图像数据帧的地址
framebuffer = mapaddr + video_mbuffer.offsets[vid_mmap.frame];
//获取图像的大小
//jpegsize = get_jpegsize(framebuffer, framesize);
if (jpegsize < 0)
{
printf("Can't get size of jpeg picture\n");
return 1;
}
//分配空间,准备将destbuffer 缓冲区中的图像数据写入文件
destbuffer = (unsigned char *)malloc(video_mbuffer.size);
if ( destbuffer == NULL)
{
printf("malloc memory for destbuffer error\n");
return -1;
}
memcpy(destbuffer,framebuffer,video_mbuffer.size);
fp = fopen(filename,"wb");//打开文件
if (!fp)
{
printf("Can't open file %s",filename);
//return -1;
}
fwrite(destbuffer,video_mbuffer.size,1,fp);//写入文件
fclose(fp);//关闭文件
free(destbuffer);//释放空间
munmap(mapaddr,video_mbuffer.size);//取消绑定
close(usb_camera_fd);
return 1;
}
open: fd = open("/dev/v4l/video0", O_RDONLY);
fd为文件句柄,失败时返回负值。
read: i = read(fd, buf, image_width*image_height*2);
成功时返回读取的字节数,失败时返回负值。
mmap: buf = (__u8 *)mmap(0, vm.size, PROT_READ, MAP_SHARED, fd, 0);
失败时返回-1。vm为video_mbuf结构体,通过调用ioctl的VIDIOCGMBUF获得vm.size
ioctl: ioctl(fd, VIDIOCCAPTURE, VIDEO_START);
成功时返回0;失败时返回负值。
ioctl函数支持的命令如下:(定义位于/include/linux/videodev.h)
Opcode Input type Description
VIDIOCGCAP struct video_capability 可获得当前摄像头支持的采集图像的最大值以及最小值
VIDIOCGWIN struct video_window 获得捕获源的大小
VIDIOCSWIN struct video_window 设置捕获源的大小
一般为640*480
VIDIOCGCAPTURE struct video_capture 获得目标图像大小
VIDIOCSCAPTURE struct video_capture 设置目标图像大小
(不得超过源大小)
VIDIOCGPICT struct video_picture 获得采集图像的颜色模式
VIDIOCSPICT struct video_picture 设置采集图像的颜色模式,
VIDIOCCAPTURE STILL_IMAGE
VIDEO_START
VIDEO_STOP 开始/停止捕获。这三个宏需要自己定义,其值分别为:-1,0,1
STILL_IMAGE:捕获一帧后停止
VIDIOCGMBUF struct video_mbuf 获得缓冲区的大小,用于mmap
注:采集参数的设置要在VIDEO_START之前执行,即执行VIDIOCCAPTURE时参数为VIDEO_START(或者STILL_IMAGE)时,才会检查更新硬件寄存器的设置。
上面是我的源码。下面是驱动开发接口
但是运行后怎么都得不到图片啊。
各位大侠帮小弟看看吧。。
|
|