一、基本概念
FrameBuffer:可以译作"帧缓冲、帧缓存",有时简称为 fbdrv。
这是一种独立于硬件的抽象图形设备。是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作控制fb。
对于应用层,通过操作/dev/fb*,通过ioctl来用各种命令控制fb /usr/include/linux/fb.h中查看
进入内核源码中看看<linux/fb.h>,里面定义了一些ioctl的命令
#define FBIOGET_VSCREENINFO 0x4600 //获取应用程序可改变的参数(如设定的分辨率)
#define FBIOPUT_VSCREENINFO 0x4601
#define FBIOGET_FSCREENINFO 0x4602 //获取固定的参数(如屏幕的分辨率,一般只是拿来看看)
#define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606
<linux/fb.h>中还提供了专门的结构体类型,用来存放上述两个参数,如下就是存放可变参数的结构体类型
struct fb_var_screeninfo {
__u32 xres; /* visible resolution 可视画面的x、y轴分辨率 */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible 可视画面相对于虚拟画面的x、y轴偏移量*/
__u32 yoffset; /* resolution */__u32 bits_per_pixel; /* guess what 像素深度 */
__u32 grayscale; /* != 0 Graylevels instead of colors */struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
二、函数接口
1.ioctl函数:
int ioctl(int fd, unsigned long request, ...);
octl() 函数执行成功时返回 0,失败则返回 -1 并设置全局变量 errorno 值,如下:
EBADF fd is not a valid file descriptor.
EFAULT argp references an inaccessible memory area.
EINVAL request or argp is not valid.
ENOTTY fd is not associated with a character special device.
NOTTY The specified request does not apply to the kind of object,that the file descriptor fd references.
2.mmap函数:
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
(1)功能:内存映射
(2)参数:
1)addr:欲映射内存的起始地址,NULL表示系统自动选定,映射成功后返回该地址
2)length:映射内存大小
3)prot:映射区域的保护方式(读/写/执行/不能存取)
PROT_EXEC | Pages may be executed. |
PROT_READ | Pages may be read. |
PROT_WRITE | Pages may be written. |
PROT_NONE | Pages may not be accessed. |
4)flags:影响区域映射的各种特性
MAP_SHARED:对映射区域写入的数据会复制回源文件内,而且允许其他映射该文件的进程共享
MAP_PRIVATE:对映射区域的写入操作会产生一个映射文件的复制,即对此区域的任何修改都不会写回原来的文件内
5)fd:要映射的目标文件
6)offset:文件映射的偏移量(0代表从开头开始)
(3)返回值:void * :返回映射欲映射内存的首地址
void *pmem;
struct fb_var_screeninfo vinf;
int init_fb(char *devname)
{
//1. 打开显示设备
int fd = open(devname, O_RDWR);
if (-1 == fd)
{
perror("fail open fb");
return -1;
}
//2、获取显示设备相关参数 分辨率 位深度
int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
if (-1 ==ret)
{
perror("fail ioctl");
return -1;
}
printf("xres = %d, yres = %d\n", vinf.xres, vinf.yres);
printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);
printf("bits_per_pixel : %d\n", vinf.bits_per_pixel);
size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
//3, 建立显存和用户空间的映射关系
pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if ((void *)-1 == pmem)
{
perror("fail mmap");
return -1;
}
return fd;
}
3.munmap函数:
int munmap(void *addr, size_t length);
(1)功能:解除内存映射
(2)参数:
- addr:映射内存的地址
- length:映射内存大小
void uninit_fb(int fd)
{
size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
munmap(pmem, len);
close(fd);
}
附录:
- 打开USB摄像头设备文件(需要以读写/非阻塞方式打开)
- 获取摄像头相关参数(VIDIOC_QUERYCAP);
- 设置图像帧格式(VIDIOC_S_FMT);
- 申请帧缓冲(VIDIOC_REQBUFS);
- 获取缓冲地址长度信息(VIDIOC_QUERYBUF);
- mmap把内核空间的帧缓冲映射到用户空间
- 帧缓冲入队列;
- 开始采集图像(VIDIOC_STREAMON);
- 出队缓冲帧(VIDIOC_DQBUF);
- 访问缓冲帧(读/写)