linux 下V4L的使用例子

来源:互联网 发布:网页机器人源码 编辑:程序博客网 时间:2024/05/20 01:37

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/videodev.h>
#include<sys/types.h>
#define VIDEO_PALETTE_RAW_JPEG 20
#define VIDEO_PALETTE_JPEG 21

#ifdef ANDROID_ENV
#define LOG LOGV
#else
#define LOG printf
#endif


#define CAPTURE_FILE "/tmp/catchpic.jpg"

typedef struct _v4ldevice
{int fd;//设备号
struct video_capability capability;
struct video_channel channel[10];
struct video_picture picture;
struct video_clip clip;
struct video_window window;
struct video_capture capture;
struct video_buffer buffer;
struct video_mmap mmap;
struct video_mbuf mbuf;
struct video_unit unit;
unsigned char *map;//mmap方式获取数据时,数据的首地址
pthread_mutex_t mutex;
int frame;
int framestat[2];
int overlay;
}v4ldevice;


int v4lgetcapability(v4ldevice *vd)
{
if(ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)) < 0) {
LOG("an error happen when get capability");
return -1;
}

// Print capability infomations
LOG("Capability Informations:/n");
LOG(" name: %s/n", vd->capability.name);
LOG(" type: %d/n", vd->capability.type);
// LOG(" channel: %d/n", vd->capability.channel);
LOG(" maxwidth: %d/n", vd->capability.maxwidth);
LOG(" maxheight: %08X/n", vd->capability.maxheight);
LOG(" minwidth: %d/n", vd->capability.minwidth);
LOG(" minheight: %08X/n", vd->capability.minheight);
return 0;
}


int v4lgetmbuf(v4ldevice *vd)
{
if(ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf))<0) {
LOG("v4lgetmbuf:VIDIOCGMBUF");
return -1;
}
return 0;
}


unsigned char *v4lgetaddress(v4ldevice *vd)
{
return (vd->map + vd->mbuf.offsets[vd->frame]);
}

int v4lopen(char *name, v4ldevice *vd)
{
int i;
if((vd->fd = open(name,O_RDWR)) < 0) {
return -1;
}
if(v4lgetcapability(vd))
return -1;
}


int v4lgrabinit(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 v4lmmap(v4ldevice *vd)
{
if(v4lgetmbuf(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 v4lgrabstart(v4ldevice *vd, int frame)
{
vd->mmap.frame = frame;
if(ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) < 0) {
return -1;
}
vd->framestat[frame] = 1;
return 0;
}


int v4lsync(v4ldevice *vd, int frame)
{
if(ioctl(vd->fd, VIDIOCSYNC, &frame) < 0) {
return -1;
}
vd->framestat[frame] = 0;
return 0;
}


int v4lcapture(v4ldevice *vd, int frame)
{
vd->mmap.frame = frame;
if(ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) < 0) {
return -1;
}
vd->framestat[frame] = 1;
}

//static void dump_to_file(const char *fname, char *buf, int *size){

//};


static void dump_to_file(const char *fname, char *buf, long int size)
{
int nw, cnt = 0;
int written = 0;

LOG("/n=========opening file [%s]+++++++++++/n", fname);
int fd = open(fname, O_RDWR | O_CREAT);
if (fd < 0) {
LOG("failed to create file [%s]: %s", fname, strerror(errno));
return;
}

LOG("/n=============writing %d bytes to file [%s]/n++++++++++++", size, fname);
while (written < size) {
nw = write(fd,
buf + written,
size - written);
if (nw < 0) {
LOG("failed to write to file [%s]: %s",
fname, strerror(errno));
break;
}
written += nw;
cnt++;
}
LOG("done writing %d bytes to file [%s] in %d passes/n",
size, fname, cnt);
close(fd);
}

 

int main(){
char* devicename="/dev/video0";
char* buffer;
v4ldevice device;
int width = 640;
int height = 480;
int frame = 0;
v4lopen("/dev/video0",&device);//打开设备

//v4lgetcapability(&device);

int ret;
// read information in video_picture
memset(&(device.picture),0,sizeof(device.picture));
ret=ioctl(device.fd, VIDIOCGPICT, &(device.picture));
if (ret < 0) {
LOG("VIDIOCGPICT failed (%d)/n", ret);
return ret;
}
LOG("/n jaylin add original picture Informations:/n");
LOG(" depth: %d/n", device.picture.depth);
LOG(" palette: %d/n", device.picture.palette);


//set capture attributes
device.picture.palette = VIDEO_PALETTE_JPEG;//different camera has different palette
device.picture.depth = 8;
if(ioctl(device.fd,VIDIOCSPICT,&(device.picture)) == -1)
{
LOG("Cann't set the picture attributes!");
close(device.fd);
exit(6);
}

//read information in video_picture
ioctl(device.fd, VIDIOCGPICT, &(device.picture));
if (ret < 0) {
LOG("VIDIOCGPICT failed (%d)/n", ret);
return ret;
}
LOG("/n jaylin add after set pictures attributes Informations:/n");
LOG(" depth: %d/n", device.picture.depth);
LOG(" palette: %d/n", device.picture.palette);


v4lgrabinit(&device,width,height);//初始化设备,定义获取的影像的大小
v4lmmap(&device);//内存映射
v4lgrabstart(&device,frame);//开始获取影像
//while(1){
v4lsync(&device,frame);//等待传完一帧
frame = (frame+1)%2;//下一帧的frame
v4lcapture(&device,frame);//获取下一帧
buffer = (char*)v4lgetaddress(&device);//得到这一帧的地址
//buffer给出了图像的首地址,你可以选择将图像显示或保存......
//图像的大小为 width*height*2
long int size = 640*480*1;
dump_to_file(CAPTURE_FILE,buffer,size);
munmap(device.map, device.mbuf.size);
//}
}

 

原创粉丝点击