context: introduce request_pool, decouple OUTPUT buffers from surfaces
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>
This commit is contained in:
+18
-49
@@ -54,20 +54,12 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
{
|
||||
struct request_data *driver_data = context->pDriverData;
|
||||
struct object_config *config_object;
|
||||
struct object_surface *surface_object;
|
||||
struct object_context *context_object = NULL;
|
||||
struct video_format *video_format;
|
||||
unsigned int length;
|
||||
unsigned int offset;
|
||||
void *source_data = MAP_FAILED;
|
||||
VASurfaceID *ids = NULL;
|
||||
VAContextID id;
|
||||
VAStatus status;
|
||||
unsigned int output_type, capture_type;
|
||||
unsigned int output_buffers_count;
|
||||
unsigned int index_base;
|
||||
unsigned int index;
|
||||
unsigned int i;
|
||||
int rc;
|
||||
|
||||
video_format = driver_data->video_format;
|
||||
@@ -92,15 +84,20 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
memset(&context_object->dpb, 0, sizeof(context_object->dpb));
|
||||
|
||||
/*
|
||||
* The OUTPUT (bitstream-input) queue must be non-empty before
|
||||
* VIDIOC_STREAMON or hantro-class drivers reject with EINVAL.
|
||||
* VA-API callers (e.g. ffmpeg's vaapi-copy path) may invoke
|
||||
* vaCreateContext with num_render_targets=0; allocate a small
|
||||
* minimum pool independent of the caller's surface count.
|
||||
* Initialize the OUTPUT (bitstream-input) buffer pool. Sized by
|
||||
* codec pipeline depth (4 H.264 frames in flight is sufficient
|
||||
* for current hantro/rkvdec scheduling); independent of caller-
|
||||
* supplied surfaces_count. Pool is owned by driver_data so it
|
||||
* outlives any single context destroy/recreate cycle.
|
||||
*
|
||||
* This replaces the prior per-surface OUTPUT loop, which (a)
|
||||
* created an empty queue when surfaces_count==0 (ffmpeg vaapi-
|
||||
* copy path) and (b) only populated surface->source_* for
|
||||
* surfaces present at vaCreateContext time, NULL-derefing on
|
||||
* surfaces created later.
|
||||
*/
|
||||
output_buffers_count = surfaces_count > 0 ? surfaces_count : 4;
|
||||
rc = v4l2_create_buffers(driver_data->video_fd, output_type,
|
||||
output_buffers_count, &index_base);
|
||||
rc = request_pool_init(&driver_data->output_pool,
|
||||
driver_data->video_fd, output_type, 4);
|
||||
if (rc < 0) {
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
@@ -111,40 +108,15 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
* we don't have any indication wrt its life time. Let's make sure
|
||||
* its life span is under our control.
|
||||
*/
|
||||
ids = malloc(surfaces_count * sizeof(VASurfaceID));
|
||||
if (ids == NULL) {
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(ids, surfaces_ids, surfaces_count * sizeof(VASurfaceID));
|
||||
|
||||
for (i = 0; i < surfaces_count; i++) {
|
||||
index = index_base + i;
|
||||
|
||||
surface_object = SURFACE(driver_data, surfaces_ids[i]);
|
||||
if (surface_object == NULL) {
|
||||
status = VA_STATUS_ERROR_INVALID_SURFACE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = v4l2_query_buffer(driver_data->video_fd, output_type,
|
||||
index, &length, &offset, 1);
|
||||
if (rc < 0) {
|
||||
if (surfaces_count > 0) {
|
||||
ids = malloc(surfaces_count * sizeof(VASurfaceID));
|
||||
if (ids == NULL) {
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
source_data = mmap(NULL, length, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, driver_data->video_fd, offset);
|
||||
if (source_data == MAP_FAILED) {
|
||||
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
surface_object->source_index = index;
|
||||
surface_object->source_data = source_data;
|
||||
surface_object->source_size = length;
|
||||
memcpy(ids, surfaces_ids,
|
||||
surfaces_count * sizeof(VASurfaceID));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -200,9 +172,6 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
|
||||
goto complete;
|
||||
|
||||
error:
|
||||
if (source_data != MAP_FAILED)
|
||||
munmap(source_data, length);
|
||||
|
||||
if (ids != NULL)
|
||||
free(ids);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user