Linux Framebuffer低效的帧抓取

时间:2016-04-01 15:26:32

标签: c linux framebuffer

我试图反复从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;
}

写入帧缓冲区真的比读取它快得多吗?

1 个答案:

答案 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()