openFrameworks addon for delayed raw-frame disk-ring playback
README
ofxRawFrameDiskRing
ofxRawFrameDiskRing is an openFrameworks addon for recording raw video frames into a disk-backed ring buffer and reading delayed frames back as an ofTexture. It includes an openFrameworks wrapper around a header-only RawFrameDiskRing core plus asynchronous FBO/PBO readback helpers for high-resolution capture workflows.Acknowledgements
This addon is built for openFrameworks and uses OpenGL FBO/PBO readback APIs through the openFrameworks GL stack.
Features
- Disk-backed fixed-size raw frame ring buffer.
- Asynchronous writer and reader threads.
ofFbo,ofTexture, andofPixelssubmission helpers.- Optional internal capture FBO ring via
beginCapture()/endCaptureAndSubmit(). - PBO-based asynchronous FBO readback path.
- Delayed-frame lookup by seconds from the latest written frame.
- Runtime counters for PBO, write-queue, and dropped-frame diagnostics.
Requirements
- openFrameworks 0.12.x or compatible.
- C++17 or newer. The current sample project uses C++23.
- Desktop OpenGL support with PBO APIs.
- Sufficient disk throughput and free disk space for the selected resolution, pixel format, frame rate, and history duration.
Installation
Add this addon to an openFrameworks project as a local addon or submodule:
mkdir -p local_addons
git submodule add <repo-url> local_addons/ofxRawFrameDiskRingThen add the addon path to
addons.make:./local_addons/ofxRawFrameDiskRingIf you use the openFrameworks project generator, regenerate the project after adding the addon.
Example app
A minimal openFrameworks example is included in
exampleApp/. It uses 720p / 30fps defaults and a short 10 second buffer to avoid creating a huge ring file on first run.Build it from the example directory:
cd exampleApp
make ReleaseMinimal usage
#include "ofxRawFrameDiskRing.h"
ofxRawFrameDiskRing ring;
ofVideoGrabber grabber;
void ofApp::setup() {
ofxRawFrameDiskRing::Settings settings;
settings.width = 3840;
settings.height = 2160;
settings.pixelFormat = OF_PIXELS_BGRA;
settings.fps = 30.0f;
settings.bufferDuration = 130.0f;
settings.useAsyncPboReadbackForFbo = true;
settings.pboCount = 8;
settings.captureFboCount = 3;
settings.writerQueueMax = 8;
settings.writerBufferPoolMax = 12;
ring.setup(settings);
grabber.setDesiredFrameRate(30);
grabber.setup(settings.width, settings.height);
}
void ofApp::update() {
grabber.update();
if (grabber.isFrameNew() && ring.beginCapture()) {
ofClear(0, 0, 0, 255);
grabber.draw(0, 0, ring.getWidth(), ring.getHeight());
ring.endCaptureAndSubmit();
}
ring.setOffsetFromNow(3.0);
ring.update();
}
void ofApp::draw() {
if (ring.hasFrame()) {
ring.getTexture().draw(0, 0, 640, 360);
}
}
void ofApp::exit() {
ring.close(true);
}Minimal API guide
ofxRawFrameDiskRing::Settings
| Field | Purpose |
|---|---|
width, height | Frame dimensions in pixels. |
pixelFormat | OF_PIXELS_RGB, OF_PIXELS_RGBA, or OF_PIXELS_BGRA. |
path | Ring-buffer file path relative to bin/data when used through openFrameworks. |
fps | Nominal frame rate used for delay-to-frame conversion. |
bufferDuration | History duration in seconds. |
writerQueueMax | Maximum queued frames waiting for disk writes. |
writerBufferPoolMax | Reusable large buffer pool limit; 0 means an internal default. |
readerBufferPoolMax | Reusable large buffer pool limit for asynchronous disk reads; 0 disables read buffer pooling. |
useAsyncPboReadbackForFbo | Enables asynchronous PBO readback for FBO submission. |
orphanPboBeforeReadback | Optionally orphan PBO storage before readback. |
pboCount | Number of PBOs in the readback ring. |
captureFboCount | Number of internal capture FBOs. |
Main methods
| Method | Purpose |
|---|---|
setup(settings) | Opens the disk ring and allocates textures/FBOs/PBOs. |
beginCapture() / endCaptureAndSubmit() | Draw into the internal capture FBO and submit it to the ring. |
addFrame(fbo) / addFrame(texture) / addFrame(pixels) | Submit an externally owned frame. |
setOffsetFromNow(seconds) | Selects the delayed frame to request during update(). |
update() | Consumes ready PBOs, requests delayed reads, and uploads read results. |
hasFrame() / getTexture() | Access the latest delayed frame texture. |
getPbo*Count() / getDroppedWriteCount() | Runtime diagnostics. |
close(drainPendingWrites) | Stops worker threads and closes the ring file. |
Performance notes
Raw 4K frames are large. 3840 x 2160 x 4 bytes is about 33 MB per frame. At 30 fps, writing and reading delayed raw frames can require multiple GB/s of combined memory, GPU, and disk bandwidth. Use Release builds for performance testing and monitor dropped-frame counters.
Dependency and license disclosure
| Dependency | Purpose | License |
|---|---|---|
| openFrameworks | Application framework, GL/FBO/texture abstractions | MIT-style / openFrameworks license; verify in your installed OF distribution |
| C++ standard library | Threads, filesystem, containers, atomics | Provided by the compiler/toolchain |
| OpenGL | FBO/PBO readback and texture upload | Platform API; license varies by implementation |
License
MIT License. See LICENSE.
ofxAddons