Add reconciler and ingest modules with CLI driver
reconciler: generic resource state machine — BFS pathfinding from current to wanted state, dependency constraints, event/periodic tick model. reconciler_cli exercises it with simulated device/transport/stream resources. ingest: V4L2 capture module — open device, negotiate MJPEG format, MMAP buffer pool, capture thread with on_frame callback. start/stop lifecycle designed for reconciler management. Transport-agnostic: caller wires on_frame to proto_write_video_frame. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
66
include/ingest.h
Normal file
66
include/ingest.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
|
||||
typedef struct Ingest_Handle Ingest_Handle;
|
||||
|
||||
/*
|
||||
* Called from the capture thread for each dequeued frame.
|
||||
* data points into the mmap'd buffer — valid only for the duration of the call.
|
||||
* Do not free data; copy if you need to retain it beyond the callback.
|
||||
*/
|
||||
typedef void (*Ingest_Frame_Fn)(
|
||||
const uint8_t *data, uint32_t len,
|
||||
int width, int height, uint32_t pixfmt,
|
||||
void *userdata);
|
||||
|
||||
/*
|
||||
* Called from the capture thread when a fatal error terminates the capture loop.
|
||||
* After this callback returns, the thread exits and the handle is in a stopped
|
||||
* state (equivalent to after ingest_stop). msg is a static string.
|
||||
*/
|
||||
typedef void (*Ingest_Error_Fn)(const char *msg, void *userdata);
|
||||
|
||||
struct Ingest_Config {
|
||||
const char *device; /* e.g. "/dev/video0" */
|
||||
uint32_t pixfmt; /* V4L2_PIX_FMT_MJPEG etc.; 0 = auto (best MJPEG) */
|
||||
int width; /* 0 = auto */
|
||||
int height; /* 0 = auto */
|
||||
Ingest_Frame_Fn on_frame;
|
||||
Ingest_Error_Fn on_error; /* may be NULL */
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
/*
|
||||
* Open the V4L2 device, negotiate format, allocate MMAP buffers.
|
||||
* Does NOT start streaming. on_frame must not be NULL.
|
||||
*/
|
||||
struct App_Error ingest_open(const struct Ingest_Config *cfg, Ingest_Handle **out);
|
||||
|
||||
/*
|
||||
* Enable streaming and start the capture thread.
|
||||
* Must be called on a handle in the OPEN (not streaming) state.
|
||||
*/
|
||||
struct App_Error ingest_start(Ingest_Handle *h);
|
||||
|
||||
/*
|
||||
* Signal the capture thread to stop and block until it exits.
|
||||
* Disables streaming. The handle returns to the OPEN state and can be
|
||||
* restarted with ingest_start or released with ingest_close.
|
||||
*/
|
||||
struct App_Error ingest_stop(Ingest_Handle *h);
|
||||
|
||||
/*
|
||||
* Release MMAP buffers and close the device fd.
|
||||
* Must be called only when the handle is not streaming (before ingest_start
|
||||
* or after ingest_stop).
|
||||
*/
|
||||
void ingest_close(Ingest_Handle *h);
|
||||
|
||||
/* Query the negotiated format — valid after a successful ingest_open. */
|
||||
int ingest_width(const Ingest_Handle *h);
|
||||
int ingest_height(const Ingest_Handle *h);
|
||||
uint32_t ingest_pixfmt(const Ingest_Handle *h);
|
||||
int ingest_fps_n(const Ingest_Handle *h);
|
||||
int ingest_fps_d(const Ingest_Handle *h);
|
||||
Reference in New Issue
Block a user