/* SPDX-License-Identifier: BSD-2-Clause */ /* * decoder.h — FFmpeg-driven decode helper for daedalus-v4l2 daemon. * * Encapsulates the AVCodecContext per supported codec, plus a * single shared AVPacket / AVFrame pair (we serialise decode * inside the chardev event loop; no concurrency). * * Phase 8.4 implements VP9. Phase 8.6 extends to AV1 / H.264. */ #ifndef DAEDALUS_V4L2_DECODER_H #define DAEDALUS_V4L2_DECODER_H #include #include #include "daedalus_v4l2_proto.h" #include "dmabuf_capture.h" struct ffmpeg_loader; struct AVCodecContext; struct AVPacket; struct AVFrame; /** * struct daedalus_decoder - per-daemon decoder state * @loader: borrowed FFmpeg loader (must outlive the decoder) * @ctx_vp9: lazily-opened VP9 AVCodecContext (NULL until first * VP9 REQ_DECODE) * @ctx_av1: lazily-opened AV1 AVCodecContext * @ctx_h264: lazily-opened H.264 AVCodecContext * @pkt: shared AVPacket reused across requests * @frame: shared AVFrame reused across requests */ struct daedalus_decoder { struct ffmpeg_loader *loader; struct AVCodecContext *ctx_vp9; struct AVCodecContext *ctx_av1; struct AVCodecContext *ctx_h264; struct AVPacket *pkt; struct AVFrame *frame; }; /** * daedalus_decoder_init - allocate the shared packet/frame pair * * Return: 0 on success, -ENOMEM if FFmpeg refused to allocate. * Codec contexts are opened lazily on first use. */ int daedalus_decoder_init(struct daedalus_decoder *dec, struct ffmpeg_loader *loader); /** * daedalus_decoder_cleanup - free codec contexts, packet, frame */ void daedalus_decoder_cleanup(struct daedalus_decoder *dec); /** * daedalus_decoder_run_request - decode one REQ_DECODE payload * @dec: initialised decoder * @req: REQ_DECODE prefix (from the wire) * @bitstream: bitstream blob (req->bitstream_len bytes) * @h264_meta: optional H.264 SPS/PPS metadata; non-NULL only when * codec_id == H264 and the kernel set DAEDALUS_REQ_FLAG_ * H264_META. Used to synthesise the AnnexB SPS+PPS NALs * libavcodec needs before any slice (libva-v4l2-request * passes only the slice in @bitstream per the V4L2 * stateless API contract). NULL for VP9/AV1 paths. * @resp: caller-allocated RESP_FRAME output (zeroed by callee) * @planes: mapped CAPTURE planes (Phase 8.6 dmabuf path). If * NULL or planes->nr == 0, the decoder runs but * writes no pixels — caller still gets dims + digest. * * Populates @resp with the decode outcome and writes decoded * pixels (NV12 layout: Y to plane 0, interleaved CbCr to plane * 1) directly into the mapped dmabuf planes. Always returns * 0; decode-level failures are reported via @resp->status so * the kernel sees a structured response rather than a dropped * request. */ int daedalus_decoder_run_request(struct daedalus_decoder *dec, const struct daedalus_req_decode *req, const uint8_t *bitstream, const struct daedalus_h264_meta *h264_meta, struct daedalus_resp_frame *resp, const struct daedalus_capture_planes *planes); #endif /* DAEDALUS_V4L2_DECODER_H */