refactor: specify number of video input buffers
Clang Lint CI / lint-no-video (push) Successful in 1m5s
Clang Build CI / run-no-video (push) Successful in 1m5s
Clang Build CI / run-video (push) Successful in 1m5s
Clang Build CI / build-release (push) Successful in 2m24s
Clang Lint CI / lint-video (push) Successful in 2m22s

This commit is contained in:
2026-05-15 00:09:51 +02:00
parent 06d175c4fd
commit 37a492d00d
9 changed files with 172 additions and 150 deletions
+3 -2
View File
@@ -174,9 +174,9 @@ These are configurable in the [`forge_project.cfg`](#forge_projectcfg).
### CLI arguments
```txt
forge steel-dev
forge steel-VERSION
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-vi=FILE] [-vs=SIZE] [-vr / -nvr] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-mr / -nmr] [-tm] [-tf]
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-vi=FILE] [-vs=SIZE] [-vb=COUNT] [-vr / -nvr] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-mr / -nmr] [-tm] [-tf]
Fusion Of Real-time Generative Effects.
@@ -196,6 +196,7 @@ options:
-nar, --no-auto-random do not randomize state (default)
-arc, --auto-random-cycle auto random cycle length (default: 4)
-vi, --video-in path to video capture device (multiple allowed)
-vb, --video-buffers number of video buffers to use (default: 2)
-vs, --video-size video capture desired height (default: internal texture height)
-vr, --video-reconnect auto-reconnect video (default)
-nvr, --no-video-reconnect do not auto-reconnect video
-5
View File
@@ -51,8 +51,6 @@ UNIFORM_STATE_PREFIX=iState
UNIFORM_ACTIVE_PREFIX=iActive
# Input X format raw integer value
UNIFORM_IN_FORMAT_PREFIX=iInputFormat
# Input X should use swap texture or not (0/1)
UNIFORM_IN_SWAP_PREFIX=iInputSwap
# --- uniform vec2 ---
@@ -106,9 +104,6 @@ IN_COUNT=2
# To which texture will be bound video device X
IN_1_OUT=1
IN_2_OUT=2
# To which texture will be bound swap buffers (for double-buffering)
IN_1_SWAP_OUT=3
IN_2_SWAP_OUT=4
# === FRAGMENT SHADERS
# Fragment shaders will be read from the CLI directory as "fragX.glsl"
+35 -33
View File
@@ -32,6 +32,7 @@ static void print_help(int status_code) {
#ifdef VIDEO_IN
"[-vi=FILE] "
"[-vs=SIZE] "
"[-vb=COUNT] "
"[-vr / -nvr] "
#endif /* VIDEO_IN */
"[-is=SIZE] "
@@ -63,6 +64,8 @@ static void print_help(int status_code) {
#ifdef VIDEO_IN
" -vi, --video-in path to video capture device (multiple "
"allowed)\n"
" -vb, --video-buffers number of video buffers to use (default: "
"2)\n"
" -vs, --video-size video capture desired height (default: "
"internal texture height)\n"
" -vr, --video-reconnect auto-reconnect video (default)\n"
@@ -134,9 +137,12 @@ void args_parse(Parameters *params, int argc, char **argv) {
params->demo = false;
params->auto_random = false;
params->auto_random_cycle = 4;
#ifdef VIDEO_IN
params->video_in.length = 0;
params->video_buffers = 2;
params->video_size = 0;
params->video_reconnect = true;
#endif /* VIDEO_IN */
params->internal_size = 720;
params->load_state = true;
params->save_state = true;
@@ -184,38 +190,6 @@ void args_parse(Parameters *params, int argc, char **argv) {
if (params->auto_random_cycle == 0) {
invalid_value(arg, value);
}
} else if (is_arg(arg, "-vi") || is_arg(arg, "--video-in")) {
#ifdef VIDEO_IN
if (params->video_in.length == MAX_VIDEO) {
log_error("maximum video input reached");
exit(EXIT_FAILURE);
}
strlcpy(params->video_in.values[params->video_in.length++], value,
STR_LEN);
#else
invalid_arg(arg);
#endif /* VIDEO_IN */
} else if (is_arg(arg, "-vs") || is_arg(arg, "--video-size")) {
#ifdef VIDEO_IN
params->video_size = parse_uint(arg, value);
if (params->video_size == 0) {
invalid_value(arg, value);
}
#else
invalid_arg(arg);
#endif /* VIDEO_IN */
} else if (is_arg(arg, "-vr") || is_arg(arg, "--video-reconnect")) {
#ifdef VIDEO_IN
params->video_reconnect = true;
#else
invalid_arg(arg);
#endif /* VIDEO_IN */
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
#ifdef VIDEO_IN
params->video_reconnect = false;
#else
invalid_arg(arg);
#endif /* VIDEO_IN */
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
params->internal_size = parse_uint(arg, value);
if (params->internal_size == 0) {
@@ -238,7 +212,34 @@ void args_parse(Parameters *params, int argc, char **argv) {
} else if (is_arg(arg, "-tf") || is_arg(arg, "--trace-fps")) {
params->trace_fps = true;
} else {
#ifdef VIDEO_IN
if (is_arg(arg, "-vi") || is_arg(arg, "--video-in")) {
if (params->video_in.length == MAX_VIDEO) {
log_error("maximum video input reached");
exit(EXIT_FAILURE);
}
strlcpy(params->video_in.values[params->video_in.length++], value,
STR_LEN);
} else if (is_arg(arg, "-vb") || is_arg(arg, "--video-buffers")) {
params->video_buffers = parse_uint(arg, value);
if (params->video_buffers == 0) {
invalid_value(arg, value);
}
} else if (is_arg(arg, "-vs") || is_arg(arg, "--video-size")) {
params->video_size = parse_uint(arg, value);
if (params->video_size == 0) {
invalid_value(arg, value);
}
} else if (is_arg(arg, "-vr") || is_arg(arg, "--video-reconnect")) {
params->video_reconnect = true;
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
params->video_reconnect = false;
} else {
invalid_arg(arg);
}
#else
invalid_arg(arg);
#endif /* VIDEO_IN */
}
}
@@ -247,8 +248,9 @@ void args_parse(Parameters *params, int argc, char **argv) {
log_error("monitor screen cannot be the same as output screen");
exit(EXIT_FAILURE);
}
#ifdef VIDEO_IN
if (params->video_size == 0) {
params->video_size = params->internal_size;
}
#endif /* VIDEO_IN */
}
+5 -4
View File
@@ -70,7 +70,7 @@ static void init_context() {
memset(context.input_resolutions, 0, sizeof(context.input_resolutions));
memset(context.input_formats, 0, sizeof(context.input_formats));
memset(context.input_fps, 0, sizeof(context.input_fps));
memset(context.input_swap, 0, sizeof(context.input_swap));
memset(context.input_index, 0, sizeof(context.input_index));
#endif /* VIDEO_IN */
}
@@ -85,7 +85,7 @@ static void init_inputs() {
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
video_init(&video_captures.values[i], init_params.video_in.values[i],
init_params.video_size);
init_params.video_size, init_params.video_buffers);
if (!video_captures.values[i].error) {
context.input_resolutions[i][0] = video_captures.values[i].width;
@@ -121,7 +121,7 @@ background_reconnect_video_captures(__attribute__((unused)) void *args) {
if (video_captures.values[i].disconnected) {
video_free(&video_captures.values[i]);
video_init(&video_captures.values[i], init_params.video_in.values[i],
init_params.video_size);
init_params.video_size, init_params.video_buffers);
if (!video_captures.values[i].error) {
context.input_resolutions[i][0] = video_captures.values[i].width;
@@ -292,7 +292,8 @@ static bool init(const Parameters *params) {
}
#ifdef VIDEO_IN
shaders_link_inputs(&program, &project, &video_captures);
shaders_link_inputs(&program, &project, &video_captures,
init_params.video_buffers);
#endif /* VIDEO_IN */
if (program.error) {
+77 -53
View File
@@ -191,18 +191,20 @@ static void rebind_textures(const ShaderProgram *program) {
#ifdef VIDEO_IN
static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
unsigned int input_index,
unsigned int texture_index, bool swap,
bool reload) {
unsigned int sub_index, bool reload) {
unsigned int texture_index =
program->tex_count + input_index * program->sub_video_count + sub_index;
if (reload) {
glDeleteTextures(1, program->textures + texture_index);
if (check_glerror(program, "link_input_to_texture/glDeleteTextures")) {
return false;
}
}
glGenTextures(1, program->textures + texture_index);
if (check_glerror(program, "link_input_to_texture/glGenTextures")) {
return false;
}
glGenTextures(1, program->textures + texture_index);
if (check_glerror(program, "link_input_to_texture/glGenTextures")) {
return false;
}
EGLImageKHR dma_image;
@@ -217,7 +219,7 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
EGL_LINUX_DRM_FOURCC_EXT,
input->pixelformat,
EGL_DMA_BUF_PLANE0_FD_EXT,
swap ? input->exp_fd_swap : input->exp_fd,
input->exp_fd[sub_index],
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
0,
EGL_DMA_BUF_PLANE0_PITCH_EXT,
@@ -230,11 +232,8 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
return false;
}
if (swap) {
program->dma_images_swap[input_index] = dma_image;
} else {
program->dma_images[input_index] = dma_image;
}
program->dma_images[input_index * program->sub_video_count + sub_index] =
dma_image;
glActiveTexture(GL_TEXTURE0 + texture_index);
if (check_glerror(program, "link_input_to_texture/glActiveTexture")) {
@@ -259,33 +258,35 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
return false;
}
log_info("Texture %d linked to %s", texture_index, input->name);
log_info("Texture %d linked to %s[%d]", texture_index, input->name,
sub_index);
return true;
}
static bool init_input(ShaderProgram *program, const ConfigFile *config,
VideoCaptureArray *inputs, unsigned int i, bool reload) {
VideoCaptureArray *inputs, unsigned int input_index,
bool reload) {
unsigned int tex_i;
unsigned int sub_index;
char name[STR_LEN];
if (i < inputs->length && !inputs->values[i].error) {
snprintf(name, STR_LEN, "IN_%d_OUT", i + 1);
if (input_index < inputs->length && input_index < program->in_count &&
!inputs->values[input_index].error) {
snprintf(name, STR_LEN, "IN_%d_OUT", input_index + 1);
tex_i = config_file_get_int(config, name, 0);
if (!link_input_to_texture(program, &inputs->values[i], i, tex_i, false,
reload)) {
return false;
}
if (inputs->values[i].with_swap) {
snprintf(name, STR_LEN, "IN_%d_SWAP_OUT", i + 1);
tex_i = config_file_get_int(config, name, 0);
if (!link_input_to_texture(program, &inputs->values[i], i, tex_i, true,
reload)) {
for (sub_index = 0; sub_index < inputs->values[input_index].buf_count;
sub_index++) {
if (!link_input_to_texture(program, &inputs->values[input_index],
input_index, sub_index, reload)) {
return false;
}
}
program->input_tex_map[input_index] = tex_i;
program->tex_map[tex_i] =
program->tex_count + input_index * program->sub_video_count;
} else {
log_warn("Cannot link input %d", i + 1);
log_warn("Cannot link input %d", input_index + 1);
}
return true;
}
@@ -535,13 +536,6 @@ static bool init_single_program(ShaderProgram *program, unsigned int i,
glGetUniformLocation(program->programs[i], name);
}
prefix = config_file_get_str(config, "UNIFORM_IN_SWAP_PREFIX", "iInputSwap");
for (unsigned int j = 0; j < program->in_count; j++) {
snprintf(name, STR_LEN, "%s%d", prefix, j + 1);
program->iinswap_locations[i * program->in_count + j] =
glGetUniformLocation(program->programs[i], name);
}
prefix = config_file_get_str(config, "UNIFORM_SEED_PREFIX", "iSeed");
for (unsigned int j = 0; j < program->frag_count; j++) {
snprintf(name, STR_LEN, "%s%d", prefix, j + 1);
@@ -650,8 +644,7 @@ static void update_viewport(ShaderProgram *program, const Context *context) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, context->tex_resolution[0],
context->tex_resolution[1], 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
check_glerror_ro(
"update_viewport/glTexImage2D"); // TODO dont remap input textures
check_glerror_ro("update_viewport/glTexImage2D");
}
program->last_resolution[0] = context->resolution[0];
program->last_resolution[1] = context->resolution[1];
@@ -736,8 +729,6 @@ static void use_program(const ShaderProgram *program, int i, bool output,
context->input_formats[j]);
write_uniform_1i(program->iinfps_locations[i * program->in_count + j],
context->input_fps[j]);
write_uniform_1i(program->iinswap_locations[i * program->in_count + j],
context->input_swap[j] ? 1 : 0);
}
#endif /* VIDEO_IN */
@@ -781,10 +772,9 @@ static void use_program(const ShaderProgram *program, int i, bool output,
}
// set GL_TEXTURE(X) to uniform sampler2D texX
// TODO perform input swap here
for (unsigned int j = 0; j < program->tex_count; j++) {
write_uniform_1i(program->textures_locations[i * program->tex_count + j],
j);
program->tex_map[j]);
}
// draw output
@@ -793,11 +783,16 @@ static void use_program(const ShaderProgram *program, int i, bool output,
void shaders_init(ShaderProgram *program, const Project *project,
const Context *context, bool rebind) {
unsigned int i;
if (!rebind) {
program->error = false;
program->last_resolution[0] = context->resolution[0];
program->last_resolution[1] = context->resolution[1];
program->tex_count = config_file_get_int(&project->config, "TEX_COUNT", 9);
memset(program->tex_map, 0, sizeof(program->tex_map));
for (i = 0; i < program->tex_count; i++) {
program->tex_map[i] = i;
}
program->frag_count = project->frag_count;
program->frag_output_index =
config_file_get_int(&project->config, "FRAG_OUTPUT", 1) - 1;
@@ -812,7 +807,7 @@ void shaders_init(ShaderProgram *program, const Project *project,
#ifdef VIDEO_IN
memset(program->dma_images, 0, sizeof(program->dma_images));
memset(program->dma_images_swap, 0, sizeof(program->dma_images_swap));
memset(program->input_tex_map, 0, sizeof(program->input_tex_map));
#endif /* VIDEO_IN */
if (!init_gl(program)) {
@@ -848,31 +843,50 @@ void shaders_init(ShaderProgram *program, const Project *project,
#ifdef VIDEO_IN
void shaders_relink_input(ShaderProgram *program, const Project *project,
VideoCaptureArray *inputs, unsigned int i) {
// shaders_free_input(program, i);
init_input(program, &project->config, inputs, i, true);
VideoCaptureArray *inputs, unsigned int input_index) {
shaders_free_input(program, input_index);
init_input(program, &project->config, inputs, input_index, true);
}
void shaders_link_inputs(ShaderProgram *program, const Project *project,
VideoCaptureArray *inputs) {
for (unsigned int i = 0; i < program->in_count; i++) {
VideoCaptureArray *inputs, unsigned int buffer_count) {
unsigned int i;
program->sub_video_count = buffer_count;
for (i = 0; i < program->in_count; i++) {
init_input(program, &project->config, inputs, i, false);
}
}
void shaders_free_input(ShaderProgram *program, unsigned int input_index) {
if (program->dma_images[input_index] != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(program->egl_display, program->dma_images[input_index]);
program->dma_images[input_index] = EGL_NO_IMAGE_KHR;
}
if (program->dma_images_swap[input_index] != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(program->egl_display,
program->dma_images_swap[input_index]);
program->dma_images_swap[input_index] = EGL_NO_IMAGE_KHR;
unsigned int sub_index;
for (sub_index = 0; sub_index < program->sub_video_count; sub_index++) {
if (program->dma_images[input_index * program->sub_video_count +
sub_index] != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(
program->egl_display,
program
->dma_images[input_index * program->sub_video_count + sub_index]);
program->dma_images[input_index * program->sub_video_count + sub_index] =
EGL_NO_IMAGE_KHR;
}
}
check_eglerror_ro("shaders_free_input/eglDestroyImageKHR");
}
static void update_inputs_tex_map(ShaderProgram *program,
const Context *context) {
unsigned int i;
unsigned int tex_i;
for (i = 0; i < program->in_count; i++) {
if (context->input_formats[i] != 0) {
tex_i = program->input_tex_map[i];
program->tex_map[tex_i] = program->tex_count +
i * program->sub_video_count +
context->input_index[i];
}
}
}
#endif /* VIDEO_IN */
void shaders_update(ShaderProgram *program, const File *fragment_shader,
@@ -887,6 +901,10 @@ void shaders_update(ShaderProgram *program, const File *fragment_shader,
void shaders_compute(ShaderProgram *program, const Context *context,
bool monitor, bool output_only) {
#ifdef VIDEO_IN
update_inputs_tex_map(program, context);
#endif /* VIDEO_IN */
if (!output_only) {
glBindVertexArray(program->vertex_array[0]);
@@ -923,6 +941,12 @@ void shaders_free(const ShaderProgram *program) {
glDeleteTextures(program->tex_count, program->textures);
check_glerror_ro("shaders_free/glDeleteTextures");
#ifdef VIDEO_IN
glDeleteTextures(program->in_count * program->sub_video_count,
program->textures + program->tex_count);
check_glerror_ro("shaders_free/glDeleteTextures");
#endif
glDeleteBuffers(1, &program->vertex_buffer);
check_glerror_ro("shaders_free/glDeleteBuffers");
}
+1 -1
View File
@@ -12,7 +12,7 @@ void shaders_relink_input(ShaderProgram *program, const Project *project,
VideoCaptureArray *inputs, unsigned int i);
void shaders_link_inputs(ShaderProgram *program, const Project *project,
VideoCaptureArray *inputs);
VideoCaptureArray *inputs, unsigned int buffer_count);
void shaders_free_input(ShaderProgram *program, unsigned int input_index);
+12 -10
View File
@@ -45,10 +45,13 @@ typedef struct Parameters {
bool demo;
bool auto_random;
unsigned int auto_random_cycle;
#ifdef VIDEO_IN
StringArray video_in;
unsigned int video_buffers;
unsigned int video_size;
unsigned int internal_size;
bool video_reconnect;
#endif /* VIDEO_IN */
unsigned int internal_size;
bool load_state;
bool save_state;
bool midi_reconnect;
@@ -85,6 +88,7 @@ typedef struct ShaderProgram {
GLuint vertex_array[2];
unsigned int tex_count;
unsigned int tex_map[ARRAY_SIZE];
GLuint textures[ARRAY_SIZE];
unsigned int frag_count;
@@ -105,7 +109,6 @@ typedef struct ShaderProgram {
GLuint iinres_locations[ARRAY_SIZE];
GLuint iinfmt_locations[ARRAY_SIZE];
GLuint iinfps_locations[ARRAY_SIZE];
GLuint iinswap_locations[ARRAY_SIZE];
GLuint idemo_locations[ARRAY_SIZE];
GLuint iautorand_locations[ARRAY_SIZE];
GLuint iautorandcycle_locations[ARRAY_SIZE];
@@ -130,9 +133,10 @@ typedef struct ShaderProgram {
unsigned int in_count;
#ifdef VIDEO_IN
unsigned int sub_video_count;
unsigned int input_tex_map[MAX_VIDEO];
EGLDisplay egl_display;
EGLImageKHR dma_images[MAX_VIDEO];
EGLImageKHR dma_images_swap[MAX_VIDEO];
#endif /* VIDEO_IN */
} ShaderProgram;
@@ -163,7 +167,7 @@ typedef struct Context {
vec2 input_resolutions[MAX_VIDEO];
unsigned int input_formats[MAX_VIDEO];
unsigned int input_fps[MAX_VIDEO];
bool input_swap[MAX_VIDEO];
unsigned int input_index[MAX_VIDEO];
#endif /* VIDEO_IN */
double time;
Tempo tempo;
@@ -190,17 +194,15 @@ typedef struct VideoCapture {
_Atomic bool error;
_Atomic bool disconnected;
_Atomic bool needs_reload;
bool with_swap;
_Atomic bool swap;
unsigned int buf_count;
unsigned int buf_index;
int fd;
int exp_fd;
int exp_fd_swap;
int exp_fd[ARRAY_SIZE];
unsigned int width;
unsigned int height;
unsigned int pixelformat;
unsigned int bytesperline;
struct v4l2_buffer buf;
struct v4l2_buffer buf_swap;
struct v4l2_buffer buf[ARRAY_SIZE];
} VideoCapture;
typedef struct VideoCaptureArray {
+38 -41
View File
@@ -192,14 +192,15 @@ static bool set_format(VideoCapture *video_capture) {
return true;
}
static bool request_buffers(VideoCapture *video_capture) {
static bool request_buffers(VideoCapture *video_capture,
unsigned int buffer_count) {
struct v4l2_requestbuffers reqbuf;
memset(&reqbuf, 0, sizeof(reqbuf));
reqbuf.type = buf_type;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 2; // TODO buffer array with count from parameters
reqbuf.count = buffer_count;
if (ioctl(video_capture->fd, VIDIOC_REQBUFS, &reqbuf) == -1) {
ioctl_error(video_capture, "VIDIOC_REQBUFS",
@@ -209,7 +210,7 @@ static bool request_buffers(VideoCapture *video_capture) {
log_info("(%s) V4L2 Buffer Count: %d", video_capture->name, reqbuf.count);
video_capture->with_swap = reqbuf.count > 1;
video_capture->buf_count = reqbuf.count;
return true;
}
@@ -239,16 +240,15 @@ static bool export_buffer(VideoCapture *video_capture, int *fd,
}
static bool export_buffers(VideoCapture *video_capture) {
bool result;
unsigned int i;
result = export_buffer(video_capture, &video_capture->exp_fd, 0);
if (result && video_capture->with_swap) {
result =
result && export_buffer(video_capture, &video_capture->exp_fd_swap, 1);
for (i = 0; i < video_capture->buf_count; i++) {
if (!export_buffer(video_capture, &video_capture->exp_fd[i], i)) {
return false;
}
}
return result;
return true;
}
static bool open_stream(VideoCapture *video_capture) {
@@ -274,10 +274,10 @@ static void create_image_buffer(const VideoCapture *video_capture,
}
static void create_image_buffers(VideoCapture *video_capture) {
create_image_buffer(video_capture, &video_capture->buf, 0);
unsigned int i;
if (video_capture->with_swap) {
create_image_buffer(video_capture, &video_capture->buf_swap, 1);
for (i = 0; i < video_capture->buf_count; i++) {
create_image_buffer(video_capture, &video_capture->buf[i], i);
}
}
@@ -286,31 +286,26 @@ static void close_stream(const VideoCapture *video_capture) {
}
static unsigned int read_video(VideoCapture *video_capture) {
unsigned int result;
struct v4l2_capability cap;
result = 0;
if (ioctl(video_capture->fd, VIDIOC_DQBUF,
&video_capture->buf[video_capture->buf_index]) != -1) {
ioctl(video_capture->fd, VIDIOC_QBUF,
&video_capture->buf[video_capture->buf_index]);
video_capture->buf_index =
(video_capture->buf_index + 1) % video_capture->buf_count;
return true;
}
if ((video_capture->swap || !video_capture->with_swap) &&
ioctl(video_capture->fd, VIDIOC_DQBUF, &video_capture->buf) != -1) {
ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf);
result = 1;
} else if (!video_capture->swap && video_capture->with_swap &&
ioctl(video_capture->fd, VIDIOC_DQBUF, &video_capture->buf_swap) !=
-1) {
ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf_swap);
result = 2;
} else if (ioctl(video_capture->fd, VIDIOC_QUERYCAP, &cap) == -1) {
if (ioctl(video_capture->fd, VIDIOC_QUERYCAP, &cap) == -1) {
video_capture->error = true;
}
return result;
return false;
}
void video_init(VideoCapture *video_capture, const char *name,
unsigned int preferred_height) {
unsigned int preferred_height, unsigned int buffer_count) {
open_device(video_capture, name);
if (video_capture->error) {
@@ -329,7 +324,7 @@ void video_init(VideoCapture *video_capture, const char *name,
return;
}
if (!request_buffers(video_capture)) {
if (!request_buffers(video_capture, buffer_count)) {
return;
}
@@ -352,14 +347,15 @@ void *video_background_read(void *args) {
bool trace_fps = process_args->trace_fps;
Timer timer;
double fps;
unsigned int video_result;
bool result;
log_info("(%s) background acquisition started", video_capture->name);
timer_init(&timer, 30);
while (!context->stop && !video_capture->error) {
video_result = read_video(video_capture);
if (video_result > 0 && timer_inc(&timer)) {
result = read_video(video_capture);
if (result && timer_inc(&timer)) {
fps = timer_reset(&timer);
context->input_fps[input_index] = (unsigned int)round(fps);
@@ -367,9 +363,9 @@ void *video_background_read(void *args) {
log_trace("(%s) %.2ffps", video_capture->name, fps);
}
}
if (video_result > 0) {
context->input_swap[input_index] = video_capture->swap =
video_result == 2;
if (result) {
context->input_index[input_index] = video_capture->buf_index;
}
}
if (context->stop) {
@@ -385,13 +381,14 @@ void *video_background_read(void *args) {
}
void video_free(const VideoCapture *video_capture) {
unsigned int i;
close_stream(video_capture);
if (video_capture->exp_fd != -1) {
close(video_capture->exp_fd);
}
if (video_capture->exp_fd_swap != -1) {
close(video_capture->exp_fd_swap);
for (i = 0; i < video_capture->buf_count; i++) {
close(video_capture->exp_fd[i]);
}
if (video_capture->fd != -1) {
close(video_capture->fd);
}
+1 -1
View File
@@ -6,7 +6,7 @@
#ifdef VIDEO_IN
void video_init(VideoCapture *video_capture, const char *name,
unsigned int preferred_height);
unsigned int preferred_height, unsigned int buffer_count);
void *video_background_read(void *args);