77 lines
2.7 KiB
C
77 lines
2.7 KiB
C
|
|
/**
|
|||
|
|
* slot.h — Framecache shared memory slot definitions.
|
|||
|
|
*
|
|||
|
|
* Layout per slot (/dev/shm/framecache/<slot_id>):
|
|||
|
|
* [fc_header_t — 4KB aligned]
|
|||
|
|
* [fc_frame_t × ring_depth — each FC_FRAME_HDR_SIZE + frame_size bytes]
|
|||
|
|
*
|
|||
|
|
* Writer advances write_cursor atomically and posts the named semaphore.
|
|||
|
|
* Each consumer tracks its own read_cursor independently — writer never blocks.
|
|||
|
|
*/
|
|||
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include <stdint.h>
|
|||
|
|
#include <stdatomic.h>
|
|||
|
|
#include <semaphore.h>
|
|||
|
|
|
|||
|
|
#define FC_MAGIC 0x46524D43u /* "FRMC" */
|
|||
|
|
#define FC_VERSION 1u
|
|||
|
|
#define FC_RING_DEPTH 120u /* ~2s at 59.94fps */
|
|||
|
|
#define FC_HEADER_SIZE 4096u /* 4KB header block */
|
|||
|
|
#define FC_FRAME_HDR_SIZE 24u /* pts_us(8) + wall_us(8) + size(4) + pad(4) */
|
|||
|
|
#define FC_MAX_SLOT_ID 64u
|
|||
|
|
|
|||
|
|
/* Pixel format codes */
|
|||
|
|
#define FC_PIX_UYVY422 0u
|
|||
|
|
|
|||
|
|
typedef struct {
|
|||
|
|
uint32_t magic; /* FC_MAGIC */
|
|||
|
|
uint32_t version; /* FC_VERSION */
|
|||
|
|
uint32_t width;
|
|||
|
|
uint32_t height;
|
|||
|
|
uint32_t fps_num;
|
|||
|
|
uint32_t fps_den;
|
|||
|
|
uint32_t pixel_format; /* FC_PIX_UYVY422 */
|
|||
|
|
uint32_t frame_size; /* width * height * 2 */
|
|||
|
|
uint32_t ring_depth; /* FC_RING_DEPTH */
|
|||
|
|
uint32_t _reserved;
|
|||
|
|
_Atomic uint64_t write_cursor; /* monotonically increasing frame index */
|
|||
|
|
_Atomic uint64_t dropped_frames;
|
|||
|
|
char source_type[32]; /* "deltacast" | "blackmagic" | "srt" | "rtmp" */
|
|||
|
|
char slot_id[FC_MAX_SLOT_ID];
|
|||
|
|
uint8_t _pad[FC_HEADER_SIZE - 112];
|
|||
|
|
} fc_header_t;
|
|||
|
|
|
|||
|
|
/* Per-frame metadata + data (variable length — use fc_frame_at() accessor) */
|
|||
|
|
typedef struct {
|
|||
|
|
uint64_t pts_us;
|
|||
|
|
uint64_t wall_us;
|
|||
|
|
uint32_t size;
|
|||
|
|
uint32_t _pad;
|
|||
|
|
uint8_t data[]; /* frame_size bytes */
|
|||
|
|
} fc_frame_t;
|
|||
|
|
|
|||
|
|
/* Compile-time size check */
|
|||
|
|
_Static_assert(sizeof(fc_header_t) == FC_HEADER_SIZE,
|
|||
|
|
"fc_header_t must be exactly FC_HEADER_SIZE bytes");
|
|||
|
|
_Static_assert(sizeof(fc_frame_t) == FC_FRAME_HDR_SIZE,
|
|||
|
|
"fc_frame_t header must be exactly FC_FRAME_HDR_SIZE bytes");
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Compute total shm size for a slot given frame_size.
|
|||
|
|
* = FC_HEADER_SIZE + ring_depth * (FC_FRAME_HDR_SIZE + frame_size)
|
|||
|
|
*/
|
|||
|
|
static inline size_t fc_slot_shm_size(uint32_t frame_size) {
|
|||
|
|
return (size_t)FC_HEADER_SIZE
|
|||
|
|
+ (size_t)FC_RING_DEPTH * ((size_t)FC_FRAME_HDR_SIZE + frame_size);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Return pointer to frame at ring index idx within a mapped shm base.
|
|||
|
|
*/
|
|||
|
|
static inline fc_frame_t *fc_frame_at(void *base, uint32_t frame_size, uint64_t idx) {
|
|||
|
|
uint8_t *frames = (uint8_t *)base + FC_HEADER_SIZE;
|
|||
|
|
return (fc_frame_t *)(frames + (idx % FC_RING_DEPTH)
|
|||
|
|
* ((size_t)FC_FRAME_HDR_SIZE + frame_size));
|
|||
|
|
}
|