31 const size_t frame_size = (size_t)2 * 1024 * 1024;
79 log_debug(
"Created video frame buffer for client %u with double buffering", client_id);
141 if (drops == 1 || drops % 100 == 0) {
142 log_debug(
"Dropping frame for client %u (reader too slow, total drops: %llu)", vfb->
client_id,
143 (
unsigned long long)drops);
177 if (!vfb || !stats) {
198 const size_t frame_size = (size_t)2 * 1024 * 1024;
229 if (size <= (
size_t)2 * 1024 * 1024) {
231 write_frame->
size = size;
⚠️‼️ Error and/or exit() when things go bad.
🗃️ Lock-Free Unified Memory Buffer Pool with Lazy Allocation
buffer_pool_t * buffer_pool_get_global(void)
void buffer_pool_free(buffer_pool_t *pool, void *data, size_t size)
Free a buffer back to the pool (lock-free)
void * buffer_pool_alloc(buffer_pool_t *pool, size_t size)
Allocate a buffer from the pool (lock-free fast path)
#define SAFE_MALLOC_ALIGNED(size, alignment, cast)
#define SAFE_MALLOC(size, cast)
#define SAFE_CALLOC(count, size, cast)
unsigned long long uint64_t
#define SAFE_MEMCPY(dest, dest_size, src, count)
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
#define log_debug(...)
Log a DEBUG message.
void video_frame_buffer_destroy(video_frame_buffer_t *vfb)
Destroy frame buffer and free all resources.
video_frame_buffer_t * video_frame_buffer_create(uint32_t client_id)
Create a double-buffered video frame manager.
video_frame_t * video_frame_begin_write(video_frame_buffer_t *vfb)
Writer API: Start writing a new frame.
const video_frame_t * simple_frame_swap_get(simple_frame_swap_t *sfs)
Get current frame from simple frame swap.
simple_frame_swap_t * simple_frame_swap_create(void)
Create a simple atomic frame swap.
void video_frame_commit(video_frame_buffer_t *vfb)
Writer API: Commit the frame and swap buffers.
const video_frame_t * video_frame_get_latest(video_frame_buffer_t *vfb)
Reader API: Get latest frame if available.
void video_frame_get_stats(video_frame_buffer_t *vfb, video_frame_stats_t *stats)
Get frame statistics for quality monitoring.
void simple_frame_swap_update(simple_frame_swap_t *sfs, const void *data, size_t size)
Update frame data in simple frame swap.
void simple_frame_swap_destroy(simple_frame_swap_t *sfs)
Destroy simple frame swap and free resources.
Unified buffer pool with lock-free fast path.
Simple atomic frame swap structure.
atomic_uintptr_t current_frame
Atomic pointer to current frame.
video_frame_t frame_b
Second pre-allocated frame.
video_frame_t frame_a
First pre-allocated frame.
atomic_bool use_frame_a
Atomic flag: true = use frame_a next, false = use frame_b.
Video frame buffer manager.
bool active
True if buffer is active (receiving frames)
mutex_t swap_mutex
Brief mutex for pointer swap only.
video_frame_t * back_buffer
Currently written frame (writer owns)
atomic_uint avg_render_time_us
Average render time in microseconds (atomic)
atomic_ullong total_frames_received
Total frames received (atomic counter)
video_frame_t frames[2]
Pre-allocated frame structures (reused forever)
size_t allocated_buffer_size
Size of allocated data buffers (for cleanup)
atomic_ullong last_frame_sequence
Last frame sequence number (atomic)
atomic_uint avg_decode_time_us
Average decode time in microseconds (atomic)
video_frame_t * front_buffer
Currently displayed frame (reader owns)
uint32_t client_id
Client ID this buffer belongs to.
atomic_bool new_frame_available
Atomic flag: true when new frame available.
atomic_ullong total_frames_dropped
Total frames dropped (atomic counter)
Frame statistics structure.
uint64_t dropped_frames
Total frames dropped (due to buffer full or errors)
uint64_t total_frames
Total frames received since creation.
uint32_t avg_render_time_us
Average frame render time in microseconds.
float drop_rate
Frame drop rate (dropped_frames / total_frames, 0.0-1.0)
uint32_t avg_decode_time_us
Average frame decode time in microseconds.
uint64_t capture_timestamp_us
Timestamp when frame was captured (microseconds)
size_t size
Size of frame data in bytes.
void * data
Frame data pointer (points to pre-allocated buffer)