/* * Copyright (C) 2026 Markus Fritsche * * 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. */ #include "request_pool.h" #include #include #include #include #include "utils.h" #include "v4l2.h" int request_pool_init(struct request_pool *pool, int video_fd, unsigned int output_type, unsigned int count) { unsigned int index_base; unsigned int length; unsigned int offset; unsigned int i; int rc; if (pool == NULL || count == 0) return -1; if (pool->initialized) return 0; pool->slots = calloc(count, sizeof(*pool->slots)); if (pool->slots == NULL) return -1; pool->count = count; pool->next = 0; rc = v4l2_create_buffers(video_fd, output_type, count, &index_base); if (rc < 0) goto error; for (i = 0; i < count; i++) { pool->slots[i].index = index_base + i; pool->slots[i].busy = false; rc = v4l2_query_buffer(video_fd, output_type, pool->slots[i].index, &length, &offset, 1); if (rc < 0) goto error; pool->slots[i].data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, video_fd, offset); if (pool->slots[i].data == MAP_FAILED) { pool->slots[i].data = NULL; goto error; } pool->slots[i].size = length; } pool->initialized = true; return 0; error: request_pool_destroy(pool); return -1; } void request_pool_destroy(struct request_pool *pool) { unsigned int i; if (pool == NULL || pool->slots == NULL) return; for (i = 0; i < pool->count; i++) { if (pool->slots[i].data != NULL && pool->slots[i].size > 0) munmap(pool->slots[i].data, pool->slots[i].size); } free(pool->slots); pool->slots = NULL; pool->count = 0; pool->next = 0; pool->initialized = false; } int request_pool_acquire(struct request_pool *pool) { unsigned int start; unsigned int i; if (pool == NULL || !pool->initialized || pool->count == 0) return -1; start = pool->next; for (i = 0; i < pool->count; i++) { unsigned int slot = (start + i) % pool->count; if (!pool->slots[slot].busy) { pool->slots[slot].busy = true; pool->next = (slot + 1) % pool->count; return (int)pool->slots[slot].index; } } /* All slots busy; caller must wait for an in-flight DQBUF. */ return -1; } void request_pool_release(struct request_pool *pool, unsigned int index) { unsigned int i; if (pool == NULL || pool->slots == NULL) return; for (i = 0; i < pool->count; i++) { if (pool->slots[i].index == index) { pool->slots[i].busy = false; return; } } } struct request_pool_slot *request_pool_slot(struct request_pool *pool, unsigned int index) { unsigned int i; if (pool == NULL || pool->slots == NULL) return NULL; for (i = 0; i < pool->count; i++) { if (pool->slots[i].index == index) return &pool->slots[i]; } return NULL; }