I have a Linux system (Raspberry Pi 4 with DietPi) which controls some RGB LED Matrix panels, by transmitting buffers of RGB pixels.
I want to display the content of a virtual frame buffer on the LED matrix, so the LED matrix essentially acts like an extra display. I have already made the code for streaming pixel buffers to the LED matrix, but I need to capture all frames from the virtual frame buffer in some way.
I have managed to open the /tmp/Xvfb_screen0
, read a single frame and do the xwd decoding and save the image. But I want to continously receive all frames from that screen, and not only the present frame at the moment where I run my code that reads from the virtual frame buffer.
In my current code I have to completely open a new file from /tmp/Xvfb_screen0
for reading, every single time I want a snapshot of the frame buffer. That does not seem like a proper solution.
So how do I capture the virtual frame buffer continously? I can see that ffmpeg can record video from a virtual frame buffer, so I guess it's possible, with the right method?
Here's what I tried so far:
# Create virtual frame buffer
sudo Xvfb :1 -fbdir /tmp/ -screen 0 512x256x24
#Start a chromium on that frame buffer
chromium-browser --window-position=0,0 --window-size=512,256 --kiosk http://esben.vonbuchwald.dk/sandbox/res-time/
package main
import (
"bufio"
"fmt"
"image/png"
"os"
"time"
"github.com/sugyan/ttygif/image/xwd"
)
const frameBuffer = "/tmp/Xvfb_screen0"
func main() {
var count int = 1
ticker := time.NewTicker(250 * time.Millisecond)
for range ticker.C {
f, err := os.Open(frameBuffer)
if err != nil {
fmt.println(err)
}
r := bufio.NewReader(f)
img, err := xwd.Decode(r)
if err != nil {
fmt.println(err)
}
if img == nil {
// If I open the frameBuffer outside of this loop, the img will be nil on second run, as no data is returned from the Reader after the first xwd decoding.
fmt.Println("image is nil")
continue
}
width := img.Bounds().Size().X
height := img.Bounds().Size().Y
fmt.Printf("w %d height %d\n\n\n", width, height)
out, err := os.Create(fmt.Sprintf("./output%d.png", count))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = png.Encode(out, img)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("Generated image to output.png \n")
count++
}
}
(I'm new to the Go language so my code might be a bit messy :) )
EDIT: I also tried this tool: https://github.com/Merovius/srvfb but without luck... It seems like it can do only "real" framebuffers like /dev/fb0
and not the ones created by Xfvb
.
dietpi@DietPi:~/srvfb$ sudo ./srvfb -device /tmp/Xvfb_screen0 -listen :8045
2022/10/19 12:07:19 FBIOGET_FSCREENINFO: inappropriate ioctl for device