565f5c0de4
Commit 3 of the upstreamable plan (upstreamable_design.md §1, §5).
Replaces the prior per-surface OUTPUT-buffer ownership model with a
small driver-wide pool sized by codec pipeline depth (4 H.264 frames
in flight), allocated unconditionally regardless of caller's
num_render_targets.
Prior art (kernel UAPI dev-stateless-decoder.rst, ffmpeg
v4l2_request.c, Chromium V4L2StatelessVideoDecoder, GStreamer
v4l2slh264dec) all decouple OUTPUT and CAPTURE pool sizing. fourier's
"output_count == surfaces_count" model was a category error: OUTPUT
buffers are request-time bitstream slots, CAPTURE buffers are
picture-time DPB slots; their lifecycles and sizing are independent.
Changes:
* NEW src/request_pool.{c,h} (~200 LoC):
- request_pool_init(): CREATE_BUFS + per-slot QUERYBUF + mmap.
- request_pool_destroy(): munmap all, idempotent.
- request_pool_acquire(): round-robin claim; returns V4L2 buffer
index of an unused slot or -1.
- request_pool_release(): mark slot free for reuse.
- request_pool_slot(): accessor for ptr/size given a buffer index.
* src/request.h: add struct request_pool output_pool to request_data.
* src/context.c::RequestCreateContext: replace the per-surface
OUTPUT loop with a single request_pool_init() call (count=4,
independent of surfaces_count). Drop the now-unused locals
(length, offset, source_data, output_buffers_count, index,
index_base, i, surface_object). DELETES patch 0002's
"output_buffers_count = ... ? ... : 4" hack inline — the pool's
own count parameter supersedes it.
* src/picture.c::RequestBeginPicture: borrow a pool slot at frame
start, write its mmap pointer/size/index into the surface's
transient source_* fields. The fields stay (still useful as
a borrow handle that the existing codec_store_buffer memcpys
target), but no longer represent surface-permanent ownership.
Reset slices_size/slices_count here too (was implicit on first
Render).
* src/surface.c::RequestSyncSurface: after VIDIOC_DQBUF returns
the OUTPUT buffer, release the pool slot and clear the surface's
borrow handle. Fixes the segv on second-frame submission.
* src/surface.c::RequestDestroySurfaces: remove the munmap of
source_data — pool owns the mmap.
* src/request.c::RequestTerminate: call request_pool_destroy()
before close(video_fd) so munmaps still target a valid fd.
* src/meson.build: add request_pool.c and request_pool.h to the
sources/headers lists.
This commit removes 0002's OUTPUT-pool hack inline (the
"floor to 4" line is gone). The DECODE_MODE/START_CODE block in 0002
remains until commit 4 lands.
Build-verified clean on aarch64.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
85 lines
2.9 KiB
C
85 lines
2.9 KiB
C
/*
|
|
* Copyright (C) 2026 Markus Fritsche <fritsche.markus@gmail.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
*/
|
|
|
|
#ifndef _REQUEST_POOL_H_
|
|
#define _REQUEST_POOL_H_
|
|
|
|
#include <stdbool.h>
|
|
|
|
/*
|
|
* OUTPUT (bitstream-input) buffer pool, decoupled from caller-allocated
|
|
* VA surfaces. Sizing is driven by codec pipeline depth (typically 4
|
|
* for H.264), not by the consumer's surface count.
|
|
*
|
|
* The pool owns the V4L2 buffer indices and their mmap pointers. A
|
|
* decode request "borrows" a slot at vaBeginPicture, fills it across
|
|
* vaRenderPicture calls, queues it at vaEndPicture, and releases it
|
|
* after VIDIOC_DQBUF returns.
|
|
*
|
|
* This replaces the per-surface OUTPUT-buffer ownership model in the
|
|
* pre-refactor code, where object_surface.source_* fields permanently
|
|
* held a single OUTPUT buffer per surface — incorrect because OUTPUT
|
|
* buffers are request-time resources, not picture-time resources, and
|
|
* because the per-surface loop in RequestCreateContext only ran when
|
|
* surfaces_count > 0 (breaking ffmpeg's vaapi-copy num_render_targets=0
|
|
* convention).
|
|
*/
|
|
|
|
struct request_pool_slot {
|
|
unsigned int index; /* V4L2 buffer index in OUTPUT queue */
|
|
void *data; /* mmap pointer for this slot */
|
|
unsigned int size; /* mmap size in bytes */
|
|
bool busy; /* true while borrowed for a request */
|
|
};
|
|
|
|
struct request_pool {
|
|
struct request_pool_slot *slots;
|
|
unsigned int count;
|
|
unsigned int next; /* round-robin acquire cursor */
|
|
bool initialized;
|
|
};
|
|
|
|
/*
|
|
* Allocate count OUTPUT buffers via VIDIOC_CREATE_BUFS, query and mmap
|
|
* each, populate pool->slots[]. Caller must have already done
|
|
* VIDIOC_S_FMT on the OUTPUT queue. Returns 0 on success, -1 on
|
|
* failure.
|
|
*/
|
|
int request_pool_init(struct request_pool *pool, int video_fd,
|
|
unsigned int output_type, unsigned int count);
|
|
|
|
/*
|
|
* Munmap all slots and free the slots array. Idempotent.
|
|
*/
|
|
void request_pool_destroy(struct request_pool *pool);
|
|
|
|
/*
|
|
* Claim the next free slot (round-robin). Returns the slot's V4L2
|
|
* buffer index on success (slot in pool->slots[] is determined by
|
|
* the returned index), or -1 if all slots are busy.
|
|
*/
|
|
int request_pool_acquire(struct request_pool *pool);
|
|
|
|
/*
|
|
* Mark the slot at pool->slots[i] free for reuse. Caller must pass the
|
|
* V4L2 buffer index returned earlier from request_pool_acquire().
|
|
*/
|
|
void request_pool_release(struct request_pool *pool, unsigned int index);
|
|
|
|
/*
|
|
* Look up the pool slot owning a given V4L2 buffer index. Returns
|
|
* pointer to the slot on success, NULL if the index is out of range.
|
|
* The returned pointer is valid until pool destruction; do not free.
|
|
*/
|
|
struct request_pool_slot *request_pool_slot(struct request_pool *pool,
|
|
unsigned int index);
|
|
|
|
#endif
|