在linux下使用视频采集卡
int fd;
fd = open("/dev/video0",O_RDWR);
用一系列的ioctl发命令控制设备。v4l支持的ioctl命令大概有二十几个,为了尽快的编出一个
简单的图象捕捉程序,让我们先来看看几个主要的命令:
1. ioctl(fd,VIDIOCGCAP,&cap);
struct video_capability
{
char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
int maxwidth; /* Supported width */
int maxheight; /* And height */
int minwidth; /* Supported width */
int minheight; /* And height */
};
channel 指的是有几个信号输入源,例如television,composite,s-video等。
2.ioctl(fd,VIDIOCGCHAN,&vc)
3.ioctl(fd,VIDIOCSCHAN.&vc)
这两个命令用来取得和设置电视卡的channel信息,例如使用那个输入源,制式等。
vc 是一个video_channel结构,其定义为:
struct video_capability
{
char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
int maxwidth; /* Supported width */
int maxheight; /* And height */
int minwidth; /* Supported width */
int minheight; /* And height */
};
struct video_channel
{
int channel;
char name[32];
int tuners;//number of tuners for this input
__u32 flags;
__u16 type;
__u16 norm;
};
成员channel代表输入源,通常,0: television 1:composite1 2:s-video
name 表示该输入源的名称。
norm 表示制式,通常,0:pal 1:ntsc 2:secam 3:auto
4. ioctl(fd,VIDIOCGMBUF,*mbuf)
获得电视卡缓存的信息,参数mbuf是video_mbuf结构。其定义如下:
struct video_mbuf
{
int size; /* Total memory to map */
int frames; /* Frames */
int offsets[VIDEO_MAX_FRAME];
};
size是缓存的大小,frames表明该电视卡的缓存可以容纳的帧数,数组offsets则表明
对应一帧的起始位置,0帧对应offsets[0],1帧对应offsets[1]....
执行完该命令后,就可以用mmap函数将缓存映射到内存中了。大致用法可以参考以下的代
码
struct video_mbuf mbuf;
unsigned char *buf1,*buf2;
if(ioctl(fd,VIDIOCGMBUF,&mbuf)<0)
{
perror("VIDIOCGMBUF");
return -1;
}
printf("the frame number is %d/n",mbuf.frames);
buf1 = (unsigned char*)mmap(0,mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd.0);
buf1 = buf1 + mbuf.offset[0];
buf2 = buf1 + mbuf.offset[1];//当然,如果mbuf.frames=1,就不需要下面的了。
......
5. ioctl(fd.VIDIOCMCAPTURE,&mm)
启动硬件去捕捉图象,mm 是video_mmap 结构,设置捕捉图象需要设置的信息。结构体
如下定义:
struct video_mmap
{
unsigned int frame; /* Frame (0 - n) for double buffer */
int height,width;
unsigned int format; /* should be VIDEO_PALETTE_* */
};
frame :设置当前是第几帧
height,width:设置图象的高和宽。
format :颜色模式
要注意的是,该命令是非阻塞的,也就是说,它仅仅设置了硬件,而不负责是否捕捉到图象。
要确定是否捕捉到图象,要用到下一个命令。
6. ioctl(fd,VIDIOCSYNC,&frame)
等待捕捉到这一帧图象。frame 是要等待的图象,它的值应和上一个命令中设置的frame相对应。
好了,说了这么多,读者大概也对视频捕捉有了一个了解,是不是想亲自动手试一下,那就让我们
开始实际程序的编写吧。
下面我们会编一个程序,将捕捉到的图象存为jpeg文件。为此,还要向大家介绍一个函数,
int write_jpeg(char *filename,unsigned char *buf,int quality,int width, int height, int gray)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *fp;
int i;
unsigned char *line;
int line_length;
if (NULL == (fp = fopen(filename,"w")))
{
fprintf(stderr,"grab: can't open %s: %s/n",filename,strerror(errno));
return -1;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, fp);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = gray ? 1: 3;
cinfo.in_color_space = gray ? JCS_GRAYSCALE: JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE);
jpeg_start_compress(&cinfo, TRUE);
line_length = gray ? width : width * 3;
for (i = 0, line = buf; i < height; i++, line += line_length)
jpeg_write_scanlines(&cinfo, &line, 1);
jpeg_finish_compress(&(cinfo));
jpeg_destroy_compress(&(cinfo));
fclose(fp);
return 0;
}
这个函数很通用,它的作用是把buf中的数据压缩成jpeg格式。
/* 下面是一个完整的程序 test.c
* gcc test.c -o test -ljpeg
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <linux/videodev.h>
#include <jpeglib.h>
#define WIDTH 320
#define HEIGHT 240
#define V4L_DEVICE "/dev/video0"
main()
{
unsigned char* buf;
int i,j;
int fd;
int re;
struct video_capability vcap;
struct video_channel vc;
struct video_mbuf mbuf;
struct video_mmap mm;
fd = open(V4L_DEVICE, O_RDWR);
if(fd<=0)
{
perror("open");
exit(1);
}
if(ioctl(fd, VIDIOCGCAP, &vcap)<0)
{
perror("VIDIOCGCAP");
exit(1);
}
fprintf(stderr,"Video Capture Device Name : %s/n",vcap.name);
for(i=0;i<vcap.channels;i++)
{
vc.channel = i;
if(ioctl(fd, VIDIOCGCHAN, &vc)<0)
{
perror("VIDIOCGCHAN");
exit(1);
}
fprintf(stderr,"Video Source (%d) Name : %s/n",i, vc.name);
}
vc.channel =1;
vc.norm=1;
if(ioctl(fd, VIDIOCSCHAN, &vc) < 0)
{
perror("VIDIOCSCHAN");
exit(1);
}
if(ioctl(fd, VIDIOCGMBUF, &mbuf) < 0)
{
perror("VIDIOCGMBUF");
exit(1);
}
fprintf(stderr,"the frames number is %d/n",mbuf.frames);
buf = (unsigned char*)mmap(0, mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if((int)buf < 0)
{
perror("mmap");
exit(1);
}
mm.frame = 0;
mm.height = HEIGHT;
mm.width = WIDTH;
mm.format = VIDEO_PALETTE_RGB24;
if(ioctl(fd, VIDIOCMCAPTURE, &mm)<0)
{
perror("VIDIOCMCAPTURE");
exit(1);
}
if(ioctl(fd, VIDIOCSYNC, &mm.frame)<0)
{
perror("VIDIOCSYNC");
exit(1);
}
if(-1 == (write_jpeg("./pic001.jpeg",buf,75,WIDTH,HEIGHT,0)))
{
printf("write_jpeg error/n");
exit(1);
}
munmap(buf,mbuf.size);
close(fd);
}
在linux下使用视频采集卡相关推荐
- 嵌入式linux下的FFmpeg交叉编译(最全面)
FFmpeg介绍 当下直播应用很火,在音视频领域,FFmpeg相当知名.可能你用的一些视频播放器背后都有它的身影.FFmpeg是一个开源的跨平台多媒体处理工具,可以用于处理音视频流.转码.封装.解封装 ...
- 过滤Linux下不同大小的文件,linux查找当前目录下 M/G 大小的文件,删除Linux下指定大小的文件
过滤Linux下不同大小的文件,linux查找当前目录下 M/G 大小的文件,删除Linux下指定大小的文件 find ./ -type f -size +1G| xargs rm 在清理系统日志文件 ...
- Linux下创建硬链接,文件访问为空,提示:xxxx: 符号连接的层数过多
Linux下创建软链接|硬链接,文件访问为空,提示:x x x: 符号连接的层数过多. 原因:创建符号链接的时候未使用绝对路径,无论是源文件路径还是目标路径,都需要使用绝对路径. 如: ln -s / ...
- Linux下环境变量配置方法梳理(.bash_profile和.bashrc的区别)
博客园 首页 新随笔 联系 管理 订阅 <div class="blogStats"><!--done--> 随笔- 556 文章- 38 评论- 77 ...
- linux下yum错误:[Errno 14] problem making ssl connection Trying other mirror.
所有的base 都要取消注释 mirrorlist 加上注释 另外所有的enable都要设为零 目录 今天是要yum命令安装EPEL仓库后 yum install epel-release 突然发现y ...
- linux下使用source /etc/profile保存配置后,新的环境变量只能在一个终端里面有效
博客园 首页 新随笔 联系 管理 订阅 <div class="blogStats"><!--done--> 随笔- 6 文章- 2 评论- 2 < ...
- Linux下Flash-LED的处理
Linux下Flash-LED的处理 一些LED设备提供两种模式-torch和flash.在LED子系统中,LED类(参见Linux下的LED处理)和LED Flash类,分别支持这些模式.torch ...
- YOLOv4:目标检测(windows和Linux下Darknet 版本)实施
YOLOv4:目标检测(windows和Linux下Darknet 版本)实施 YOLOv4 - Neural Networks for Object Detection (Windows and L ...
- Linux下的C#连接Mysql数据库
今天在尝试在 Linux 系统下使用C#连接数据库,发现网上这方面的信息很少,所以就写一篇博客记录一下. Linux下这里使用的是mono. 首先是缺少Mysql.Data.dll这个库的,所以需要安 ...
最新文章
- MRTG—网络监控工具
- python编程if语法-Python基本语法(if判断)
- MongoDB 数据库创建、删除、表(集合) 创建删除、数据的增、删、改、查
- 王道计算机网络 数据链路层整理 超详细版
- kubernetes 学习 pod相关
- 〖Python〗-- 函数闭包的理解
- ROS下usb_cam的安装
- 射击类游戏html代码,超简单射击游戏
- Gos —— 开启保护模式
- 22. 关于定时任务指定的时间间隔内没有完成任务的处理
- 支付宝APP支付集成文档
- 1007: A+B 输入输出练习VIII
- STM32单片机开发实例 基于STM32单片机的智能行李箱
- 单片机做计算机乘法,基于单片机实现的四则运算计算器.DOC
- 《图像处理实例》 之 二值图像分割
- css3中的动画特效--跳动的篮球
- CAN接受和发送失败的原因有哪些---之前调试MCP2515驱动时,数据一直发不出去,三个发送邮箱都被占满.至今未解决,读寄存器-总线错误
- nexus在docker安装nexus与初始密码问题
- IDEA之翻译器的妙用Translation
- 163.net邮箱个人登录入口攻略,轻松助你使用邮箱客户端