Last active
February 6, 2020 11:02
-
-
Save Hermann-SW/ec6a2070935f69d999ad9b860d6b140f to your computer and use it in GitHub Desktop.
High framerate drawing stream of RGB frames on Raspberry framebuffer (https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=264109)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <linux/fb.h> | |
#include <sys/mman.h> | |
#include <sys/ioctl.h> | |
int align_up(int x, int y) { return ((x-1)|((1<<y)-1))+1; } | |
#include <time.h> | |
long prev_us = 0, delta_us = 0, base_sec = 0; | |
#define _ {long a=prev_us;struct timespec t;clock_gettime(CLOCK_REALTIME,&t);\ | |
if (!base_sec) { base_sec = t.tv_sec; }\ | |
prev_us=1000000*(t.tv_sec-base_sec)+t.tv_nsec/1000; delta_us = prev_us - a;} | |
#define __ _ fprintf(stderr, "%ld\n", delta_us); | |
#define ___(n, blk) for(int i=0; i<n; ++i) { blk } | |
void FillArea32(char *buf, unsigned nStride3, unsigned *fbp, unsigned lStride, | |
int xres, int yres, int x1, int y1, int x2, int y2, int cmask) | |
{ | |
fbp += (y1 * lStride + x1); | |
for(int y = y1; y < y2; y++, fbp += lStride, buf += nStride3 - 3 * (x2 - x1)) | |
{ | |
if (y < 0) { buf += nStride3; continue; } | |
if (y >= yres) { break; } | |
char *p = (char*)fbp; | |
for(int x = x1; x < x2; x++, p+=4) | |
{ | |
if ((x < 0) || (x >= xres)) { buf += 3; continue; } | |
p[2] = cmask & 0x04 ? *buf++ : (buf++,0); | |
p[1] = cmask & 0x02 ? *buf++ : (buf++,0); | |
p[0] = cmask & 0x01 ? *buf++ : (buf++,0); | |
p[3] = 0; | |
} | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
unsigned width, height, nStride, nSliceHeight, nLen, cmask; | |
char *buf; | |
int fbfd = 0; | |
struct fb_var_screeninfo vinfo; | |
struct fb_fix_screeninfo finfo; | |
unsigned *fbp = NULL; | |
assert((argc+1)/2==2 || !"Format: rgb2fb width height [dmask]"); | |
// memory mapped framebuffer | |
assert(-1 != (fbfd = open("/dev/fb0", O_RDWR))); | |
assert(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) != -1); | |
assert(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) != -1); | |
assert(vinfo.xoffset == 0); | |
assert(vinfo.yoffset == 0); | |
assert(vinfo.bits_per_pixel == 32); | |
fbp = mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); | |
assert(fbp != (void*)-1); | |
for(volatile unsigned *p = fbp; p < fbp + finfo.smem_len/4; ++p) | |
*p = *p; | |
msync(fbp, finfo.smem_len, MS_SYNC); | |
// init rgb stdin related variables | |
width = atoi(argv[1]); nStride = align_up(width, 5); | |
height = atoi(argv[2]); nSliceHeight = align_up(height, 4); | |
nLen = nStride * nSliceHeight * 3; | |
assert( (buf = malloc(nLen)) ); | |
cmask = (argc == 3) ? 'F' : argv[3][0]; | |
cmask -= (cmask > '9') ? '7' : '0'; | |
// take rgb frames from stdin and display on framebuffer | |
// | |
fread(buf, nLen, 1, stdin); | |
_ // do not profile 1st fread | |
while (!feof(stdin)) | |
{ | |
__ int colmask[4] = {0x07, 0x01, 0x02, 0x04}; | |
_ for(int i=3; i>=0; --i) | |
if (cmask & (1<<i)) | |
{ | |
int x = vinfo.xres / 2 - (1 - i%2) * width; | |
int y = vinfo.yres / 2 - (1 - i/2) * height; | |
FillArea32(buf, nStride * 3, fbp, finfo.line_length/4, | |
vinfo.xres, vinfo.yres, x, y, x + width, y + height, colmask[i]); | |
} | |
if (cmask == 0) | |
{ | |
int x = (vinfo.xres - width) / 2; | |
int y = (vinfo.yres - height) / 2; | |
FillArea32(buf, nStride * 3, fbp, finfo.line_length/4, | |
vinfo.xres, vinfo.yres, x, y, x + width, y + height, 0x07); | |
} | |
__ | |
msync(fbp, finfo.smem_len, MS_SYNC); | |
_ | |
int ret = fread(buf, nLen, 1, stdin); | |
assert(feof(stdin) || (1 == ret)); | |
} | |
free(buf); | |
munmap(fbp, finfo.smem_len); | |
close(fbfd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment