我试图反复从Linux帧缓冲区中抓取一个帧,但它每帧占用一秒钟。
虽然我没有预期60FPS,但我希望超过60FPM。这是正常的吗?我使用的是开源视频驱动程序;我的GPU是AMD 280X,我的CPU是AMD 8320 @ 4.4GHz。
我的代码看起来像这样:
static uint8_t *previous_buffer;
static uint8_t *fbp;
static long int location = 0;
long int screensize = 0;
int sf = open("/dev/fb0",O_RDWR);
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
ioctl(sf, FBIOGET_FSCREENINFO, &finfo);
ioctl(sf, FBIOGET_VSCREENINFO, &vinfo);
screensize = finfo.smem_len;
fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, sf, (off_t)0);
previous_buffer = malloc(screensize);
bytespp = (vinfo.bits_per_pixel / 8);
for(int x = 0; x < vinfo->xres * bytespp; x+=bytespp)
for(int y = 0; y < vinfo->yres * finfo->line_length; y+=finfo->line_length){
//printf("xoff: %d yoff:%d x:%d y:%d\n", xoff, yoff, x, y);
location = x + y + off;
//printf("Location: %lu\n", location);
if(*((uint32_t*)(fbp+location)) != *((uint32_t*)(previous_buffer+location))){
memcpy((fbp+location), (previous_buffer+location), 4); // sizeof(uint32_t)
d1++;
}
}
我的完整代码可用here,但我认为循环是重要的部分。
此外,我尝试从this website运行一个程序,将每个像素设置为粉红色,而循环本身只需要7毫秒(即使它在每次循环中执行乘法和除法):
#include <linux/fb.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
inline uint32_t pixel_color(uint8_t r, uint8_t g, uint8_t b, struct fb_var_screeninfo *vinfo)
{
return (r<<vinfo->red.offset) | (g<<vinfo->green.offset) | (b<<vinfo->blue.offset);
}
int main()
{
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
int fb_fd = open("/dev/fb0",O_RDWR);
//Get variable screen information
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
vinfo.grayscale=0;
vinfo.bits_per_pixel=32;
ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);
ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
long screensize = vinfo.yres_virtual * finfo.line_length;
uint8_t *fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, (off_t)0);
int x,y;
for (x=0;x<vinfo.xres;x++)
for (y=0;y<vinfo.yres;y++)
{
long location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) * finfo.line_length;
*((uint32_t*)(fbp + location)) = pixel_color(0xFF,0x00,0xFF, &vinfo);
}
return 0;
}
写入帧缓冲区真的比读取它快得多吗?
答案 0 :(得分:1)
我对循环的未经测试的建议:
void const *start = (fbp + vinfo->yoffset * finfo->line_length +
vinfo->xoffset * bytespp);
void *out = previous_buffer;
size_t xres_bytes = vinfo->xres * bytespp;
size_t d_stride = finfo->line_length - xres_bytes;
if (d_stride == 0 && allow_memcpy) {
memcpy(out, start, finfo->line_length * vinfo->yres);
} else {
for (int y = 0; y < vinfo->yres_virtual; ++y) {
start += d_stride;
if (allow_memcpy) {
out = mempcpy(out, start, xres_bytes);
start += xres_bytes;
} else {
/* or do the #include thing below here */
for (int x = 0; x < vinfo->xres_virtual; ++x) {
switch (bytesbpp) {
case 1: out = mempcpy(out, start, 1); break;
case 2: out = mempcpy(out, start, 2); break;
case 3: out = mempcpy(out, start, 3); break;
case 4: out = mempcpy(out, start, 4); break;
default: out = mempcpy(out, start, bytesbpp); break;
}
start += bytesbpp;
}
}
}
}
如果您想进一步优化它,可以将内部x
循环放入一个额外的文件(例如inner-x-loop.inc.h
)并将其包含在
if (bytesbpp == 1) {
#include "inner-x-loop.inc.h"
} else if (bytesbpp == 2) {
#include "inner-x-loop.inc.h"
} else if (bytesbpp == 3) {
#include "inner-x-loop.inc.h"
} else if (bytesbpp == 4) {
#include "inner-x-loop.inc.h"
} else
#include "inner-x-loop.inc.h"
}
枚举bytesbpp
允许编译器内联mempcpy()
。