现在的位置: 首页 > 综合 > 正文

V4L图像采集总结

2018年01月16日 ⁄ 综合 ⁄ 共 4956字 ⁄ 字号 评论关闭
 

采用中星微ZC301摄像头的V4L图像采集

/**********v4l.h*******************

/*name :v4l.h

  date:2009-5-20

  author:kevin

  copyright:all is reserved

**************************/

#ifndef _V4L_H_
#define _V4L_H_

#include <linux/videodev.h>
#include <sys/types.h>
//PAL CIF NTSC tuner mode
#define PAL_WIDTH 768 

#define PAL_HEIGHT 576

#define CIF_WIDTH 352

#define CIF_HEIGHT 288

#define NTSC_WIDTH 80  //设置获取图像的大小

#define NTSC_HEIGHT 60

#define DEFAULT_PALETTE VIDEO_PALETTE_RGB32

struct _v4l_device
{
    int fd;//设备号
    struct video_capability capability;//摄像头属性
    struct video_picture picture;//图像的属性,亮度、色度、对比度、灰度、编码属性
    struct video_window window;//包含capture area 的信息
    struct video_channel channel[8];//采集的通道
    struct video_mbuf mbuf;//利用mmap映射得侦信息
    struct video_capture capture;
    struct video_buffer buffer;
    struct video_mmap mmap;
    unsigned char *map;
    int frame;
    int framestat[2];
};
typedef struct _v4l_device v4ldevice;

extern int v4l_open(char *,v4ldevice *);
extern int v4l_set_norm(v4ldevice *, int);
extern int v4l_get_capability(v4ldevice *);
extern int v4l_get_window(v4ldevice *);
extern int v4l_set_window(v4ldevice *);
extern int v4l_get_picture(v4ldevice *);
extern int v4l_mmap_init(v4ldevice *);
extern int v4l_grab_init(v4ldevice *,int ,int);
extern int v4l_grab_start(v4ldevice *,int );
extern int v4l_grab_sync(v4ldevice *,int);
extern int v4l_get_capture(v4ldevice *);//,int);
extern int v4l_set_capture(v4ldevice *);//,int);
extern unsigned char *v4l_get_address(v4ldevice *);
extern int v4l_close(v4ldevice *);
extern void set(v4ldevice *);
#endif

/***********************v4l.c****************************/

/*name :v4l.c

  date:2009-5-20

  author:kevin

  copyright:all is reserved

************************************************/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <error.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/videodev.h>
#include "v4l.h"
#define DEFAULT_DEVICE "/dev/video0"
int v4l_open(char *dev,v4ldevice *vd)
{
    if (!dev)

              dev = DEFAULT_DEVICE;

    if((vd->fd=open(dev,O_RDWR,10705))<0)
    {
        return -1;
    };
    if(v4l_get_capability(vd)<0)
        return -1;
    if(v4l_get_picture(vd)<0)
        return -1;
    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)
{
   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;
}

/*************************************************************/

/******************main.c************************/

/*name :main.c

  date:2009-5-20

  author:kevin

  copyright:all is reserved

************************************/

 

#include "v4l.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#define norm VIDEO_MODE_NTSC
#define DEFAULT_FILE_NAME "picture"
int main()
{

    char *buffer=NULL;
    v4ldevice VD;
    v4ldevice *vd=&VD;

    int frame=0;
    int f_d;

    f_d=open(DEFAULT_FILE_NAME,O_RDWR|O_CREAT,0666);//获取文件的描述符
   
    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,NTSC_WIDTH,NTSC_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");
    if(0==v4l_grab_start(vd,frame))//开始获取图像
        printf("get picture success!/n");
    else
        printf("get picture failure/n");     

   v4l_grab_sync(vd,frame);//等待传完一帧
       
        buffer=(char *)v4l_get_address(vd);//得到这一帧的地址
        printf("img address %p/n",buffer);

    write(f_d,buffer,NTSC_WIDTH*3*NTSC_HEIGHT);//报存到文件中   

    v4l_close(vd);
    return 0;
   
}

抱歉!评论已关闭.