http://www.360doc.com/content/11/0218/16/474846_94092987.shtmlVideo4linux简介Video4Linux是为市场现在常见的电视捕获卡和并口及USB口的摄像头提供统一的编程接口。同时也提供无线电通信和文字电视广播解码和垂直消隐的数据接口。本文主要针对USB摄像头设备文件/dev/video0,进行视频图像采集方面的程序设计。Video4linux编程指南1.视频编程的流程(1)打开视频设备:(2)读取设备信息(3)更改设备当前设置(可以不做)(4)进行视频采集,两种方法: a.内存映射 b.直接从设备读取(5)对采集的视频进行处理(本程序没做,下次再show给大家)(6)关闭视频设备//下面我对这些操作做了个简单的函数封装#ifndef _V4L_H#define_V4L_H#include #include #include#include #include#include #include#include #include#include #include#include/*采集的图像的最大长和宽*/#define MAX_WIDTH 400#define MAX_HEIGHT300/*设备文件*/#define DEFAULT_DEVICE “/dev/video0″/*自定义数据结构,包含v4l中用到的数据结构*/typedef struct v4l_struct{ int fd;/*设备号*/ structvideo_capability capability; //包含设备的基本信息(设备名称、支持的最大最小分辨率、信号源信息等) structvideo_channel channel[8];//信号源个数 struct video_picturepicture;//设备采集的图象的各种属性 struct video_mmap mmap;//用于mmapstruct video_mbuf mbuf;//利用mmap进行映射的帧的信息 unsigned char*buffer ;/*图像数据存放区*/ unsigned char *map;/*mmap方式获取数据时,数据的首地址*/ intframe_current; int frame_using[2]; /*这个帧的状态0表示可用,1表示不可用*/}v4l_device;/***************************************************************函数名:v4l_open* 功 能: 打开设备* 输 入: dev,vd* 输 出: 无* 返 回: -1—-失败0—-成功**************************************************************/intv4l_open( char *dev, v4l_device *vd ){ if( !dev ) {dev=DEFAULT_DEVICE ; } if( ( vd->fd = open( dev, O_RDWR ) ) { perror( “v4l_open error” ); return-1; } return 0;}/*************************************************************** 函数名:v4l_get_capability* 功 能: 获取设备属性* 输 入: vd* 输 出: 无* 返 回:-1—-失败0—-成功**************************************************************/intv4l_get_capability( v4l_device *vd ){ if( ioctl( vd->fd,VIDIOCGCAP, &( vd->capability ) ) { perror(“v4l_get_capability” ); return -1 ; } return0; }/****************************************************************函数名:v4l_get_picture* 功 能:获取图片属性* 输 入: vd* 输 出: 无* 返 回:-1—-失败0—-成功***************************************************************/intv4l_get_picture( v4l_device *vd ){ if( ioctl(vd->fd,VIDIOCGPICT,&( vd->picture ) ) {return -1; } return 0;}/*************************************************************** 函数名:v4l_set_picture* 功 能: 设置图片属性* 输 入: vd* 输 出: 无* 返 回: -1—-失败0—-成功**************************************************************/intv4l_set_picture( v4l_device *vd ) { if( ioctl( vd->fd,VIDIOCSPICT, &( vd->picture ) ) { return-1; } return 0;}/**************************************************************函数名:v4l_get_channels* 功 能:获取通道信息* 输 入: vd* 输 出: 无* 返 回:-1—-失败0—-成功*************************************************************/intv4l_get_channels( v4l_device *vd ){ int i; for( i=0;i capability.channels ; i++ ) { vd->channel[i].channel= i; //确定通道 if( ioctl( vd->fd , VIDIOCGCHAN, &(vd->channel[i] ) ) { perror(“v4l_get_channel” ); return -1; } }return 0;}/************************************************************** 函数名:v4l_get_mbuf* 功 能: 获取内存映射信息* 输 入: vd* 输 出: 无* 返 回: -1—-失败0—-成功**************************************************************/intv4l_get_mbuf( v4l_device *vd ){ if( ioctl (vd->fd,VIDIOCGMBUF,&( vd->mbuf ) ) { perror(“get_mbuf:” ); return -1; } if ( ( vd->map = (unsigned char * )mmap( 0, vd->mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED,vd->fd, 0 ) ) {perror(“v4l_mmap_init:mmap”); return -1; } return 0;}/************************************************************** 函数名:v4l_init_mbuff* 功 能: 初始化内存映射信息* 输 入: vd* 输 出: 无* 返 回:0—-成功**************************************************************/intv4l_init_mbuf(v4l_device *vd){ //vd->mmap.frame = 10 ;//不懂双帧是怎样设置的这个frame 该是当前帧的可mbuf 以又没有设置怎么确定是双帧不是单帧还是更多 vd->mmap.width =MAX_WIDTH; vd->mmap.height = MAX_HEIGHT; vd->mmap.format =vd->picture.palette; vd->frame_current = 0;vd->frame_using[0] = 0; vd->frame_using[1] = 0; return0;}/*************************************************************** 函数名:v4l_get_address* 功 能:获取数据在图像的地址***************************************************************/unsignedchar *v4l_get_address(v4l_device *vd){ return (vd->map +vd->mbuf.offsets[vd->frame_current]);}/************************************************************** 函数名:v4l_grab_frame* 功 能:捕获帧**************************************************************/intv4l_grab_frame(v4l_device *vd, int frame){ if(vd->frame_using[frame]) { fprintf(stderr,“v4l_grab_frame: frame %d is already used.\n”, frame); return-1; } vd->mmap.frame = frame; if ( ioctl(vd->fd,VIDIOCMCAPTURE, &(vd->mmap ) ) { perror(“v4l_grab_frame” ); return -1; }vd->frame_using[frame] = 1; vd->frame_current = frame;return 0; }/*************************************************************** 函数名:v4l_grab_sync* 功能:与内存映射捕获一致**************************************************************/intv4l_grab_sync(v4l_device *vd){ if (ioctl(vd->fd, VIDIOCSYNC,&(vd->frame_current)) {perror(“v4l_grab_sync”); }vd->frame_using[vd->frame_current] = 0; return 0;}/**************************************************************** 函数名:v4l_munmap* 功能:停止内存映射***************************************************************/intv4l_munmap( v4l_device *vd ){ if ( munmap( vd->map,vd->mbuf.size ) { perror( “v4lmunmap:munmap”); return -1; } return 0;}/**************************************************************** 函数名:v4l_close* 功能:关闭设备***************************************************************/intv4l_close(v4l_device *vd){ close(vd->fd); return0;}#endif //简单的封装了关于SDL的相关操作”ScreenSurface.h”#ifndefSCREEN_SURFACE_H#define SCREEN_SURFACE_H#include #include #includeclass ScreenSurface {public: ScreenSurface(); boolscreen_init(int w, int h, int b = 0, Uint32 f = 0);//初始化~ScreenSurface(); SDL_Surface* point() const; intscreen_lock(); void screen_unlock(); void screen_quit();void screen_set_caption( const char *str );//设置标题 bool flip( unsignedchar * src) ;//显示 int startTV();//开始采集private: static intscreenNum; int width; int height; int bpp; Uint32flags; SDL_Surface* pScreen;};#endif//ScreenSurface.cpp#include “ScreenSurface.h”#include“qt_v4l.h”v4l_devicev4l_dev;/***************************************************************函数名: v4l_grab_movie* 功能:捕获连续图像**************************************************************/voidv4l_grab_movie(){ v4l_grab_frame(&v4l_dev,v4l_dev.frame_current);/*获取下一 帧*/ v4l_grab_sync(&v4l_dev);/*等待传完一帧*/ v4l_dev.buffer = v4l_get_address(&v4l_dev);/*得到这一帧的地址*/v4l_dev.frame_current = (v4l_dev.frame_current+1)%2; /* 下一帧的frame*/}//构造函数。如果创建1个以上的screensurface,则会抛出异常ScreenSurface::ScreenSurface():width(640), height(480),bpp(32), flags(0){ pScreen = 0; v4l_open(DEFAULT_DEVICE,&v4l_dev);/*打开设备*/ v4l_get_capability(&v4l_dev);v4l_get_picture(&v4l_dev);v4l_init_mbuf(&v4l_dev);/*初始化设备*/v4l_get_mbuf(&v4l_dev);/*内存映射*/}bool ScreenSurface::screen_init(int w, int h, int b, Uint32 f){width = w ; height = h ; bpp = b ; flags = f; if(SDL_Init(SDL_INIT_VIDEO) {printf(“SDL_Init Failed!\n”); return false; }//设置图象模式(宽*高 位数 标志 SDL_SWSURFACE | SDL_DOUBLEBUF) pScreen =SDL_SetVideoMode(width, height, bpp, flags); if ( pScreen == 0 ){ printf(“Could’t set display mode \n”);SDL_Quit(); return false; }SDL_ShowCursor(SDL_DISABLE); return true;}//析构函数。在对象消亡时,退出SDL系统。ScreenSurface::~ScreenSurface(){ }//返回screen surface中SDL_Surface结构的指针,主要提供给SDL的函数调用SDL_Surface*ScreenSurface::point() const{ return pScreen;}int ScreenSurface::screen_lock(){ if (SDL_MUSTLOCK(pScreen)) return SDL_LockSurface(pScreen); return0;}void ScreenSurface::screen_unlock(){ if (SDL_MUSTLOCK(pScreen)) SDL_UnlockSurface(pScreen); }void ScreenSurface::screen_quit(){ SDL_Quit();v4l_munmap(&v4l_dev) ; v4l_close(&v4l_dev); }void ScreenSurface::screen_set_caption( const char *str ){SDL_WM_SetCaption( str, 0 );}//显示(弹出flip)screen surface到屏幕上bool ScreenSurface::flip( unsigned char *src ){ if ( screen_lock() return false;unsigned char *dest; dest = ( unsigned char *)pScreen->pixels; memcpy( dest , src , width * height * 4 );screen_unlock(); if ( SDL_Flip(pScreen)return false; else return true; }int ScreenSurface::startTV(){ bool bFlag = true;while(bFlag) { v4l_grab_movie(); unsigned char*buf= v4l_dev.buffer; if (buf != NULL) {flip(buf); } SDL_Event event;while(SDL_PollEvent(event)) { if (event.type ==SDL_QUIT) { //bFlag =false; screen_quit(); } }}}//main.cpp#include “ScreenSurface.h”void main(){ScreenSurface *m_pScreen; m_pScreen = new ScreenSurface( );m_pScreen->screen_init(400 , 300 , 32 , SDL_SWSURFACE |SDL_ANYFORMAT); m_pScreen->screen_set_caption(“DemoTV”);m_pScreen->startTV();}
10-25 13:48
查看更多