feat: video reconnect (wip egl error 3003)

This commit is contained in:
2026-05-11 07:40:20 +02:00
parent dd20515e2b
commit 7d03c9719e
5 changed files with 192 additions and 82 deletions
+77 -23
View File
@@ -4,13 +4,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "types.h"
#include "config.h"
#include "config_file.h"
#include "file.h"
#include "forge.h"
#include "midi.h"
#include "project.h"
@@ -22,11 +21,11 @@
#include "video.h"
#include "window.h"
static Parameters init_params;
static SharedContext *context;
static ShaderProgram program;
static Window *window_output;
static Window *window_monitor;
static VideoCaptureArray inputs;
static Timer timer;
static MidiDevice midi;
static bool trace_midi;
@@ -66,9 +65,6 @@ static void init_context(const Parameters *params) {
params->auto_random_cycle, params->base_tempo, params->load_state);
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));
}
static void free_context() { shared_close_context(context); }
@@ -79,36 +75,79 @@ static void reload_shader(unsigned int i) {
#ifdef VIDEO_IN
static void init_inputs(const StringArray *video_in, unsigned int video_size) {
inputs.length = video_in->length;
context->inputs.length = video_in->length;
for (unsigned int i = 0; i < video_in->length; i++) {
video_init(&inputs.values[i], video_in->values[i], video_size);
video_init(&context->inputs.values[i], video_in->values[i], video_size);
if (!inputs.values[i].error) {
context->input_resolutions[i][0] = inputs.values[i].width;
context->input_resolutions[i][1] = inputs.values[i].height;
context->input_formats[i] = inputs.values[i].pixelformat;
if (!context->inputs.values[i].error) {
context->input_resolutions[i][0] = context->inputs.values[i].width;
context->input_resolutions[i][1] = context->inputs.values[i].height;
context->inputs.values[i].needs_reload = false;
context->inputs.values[i].disconnected = false;
}
}
}
static bool start_video_captures(unsigned int video_count, bool trace_fps) {
for (unsigned int i = 0; i < video_count; i++) {
if (!inputs.values[i].error &&
!video_background_read(&inputs.values[i], context, i, trace_fps)) {
return false;
static bool reconnect_video_captures(const StringArray *video_in,
unsigned int video_size, bool trace_fps) {
for (unsigned int i = 0; i < video_in->length; i++) {
if (context->inputs.values[i].disconnected) {
video_init(&context->inputs.values[i], video_in->values[i], video_size);
if (!context->inputs.values[i].error) {
context->input_resolutions[i][0] = context->inputs.values[i].width;
context->input_resolutions[i][1] = context->inputs.values[i].height;
if (!video_background_read(&context->inputs.values[i], context, i,
trace_fps)) {
return false;
}
context->inputs.values[i].needs_reload = true;
context->inputs.values[i].disconnected = false;
}
}
}
return true;
}
static bool start_video_captures(unsigned int video_count, bool trace_fps) {
pid_t pid;
for (unsigned int i = 0; i < video_count; i++) {
if (!context->inputs.values[i].error &&
!video_background_read(&context->inputs.values[i], context, i,
trace_fps)) {
return false;
}
}
pid = fork();
if (pid < 0) {
log_error("Could not create subprocess");
return false;
}
if (pid == 0) {
return true;
}
log_info("background reconnect acquisition started (pid: %d)", pid);
while (!context->stop) {
sleep(1);
if (!reconnect_video_captures(&init_params.video_in, init_params.video_size,
init_params.trace_fps)) {
return false;
}
}
exit(EXIT_SUCCESS);
}
static void free_video_captures(unsigned int video_count) {
for (unsigned int i = 0; i < video_count; i++) {
shaders_free_input(&program, &inputs.values[i]);
shaders_free_input(&program, i);
video_free(&inputs.values[i]);
video_free(&context->inputs.values[i]);
}
}
#endif /* VIDEO_IN */
static void error_callback(int error, const char *description) {
@@ -140,6 +179,8 @@ static void midi_callback(unsigned char code, unsigned char value) {
}
static bool init(const Parameters *params) {
init_params = *params;
project_init(&project, params->project_path, params->config_file);
if (project.error) {
@@ -200,7 +241,7 @@ static bool init(const Parameters *params) {
}
#ifdef VIDEO_IN
shaders_link_inputs(&program, &project, &inputs);
shaders_link_inputs(&program, &project, &context->inputs);
#endif /* VIDEO_IN */
if (program.error) {
@@ -221,11 +262,20 @@ static bool should_close() {
(window_monitor != NULL && window_should_close(window_monitor));
}
static void loop(bool hr, bool trace_fps) {
static bool loop(bool hr, bool trace_fps) {
if (hr) {
project_reload(&project, reload_shader);
}
#ifdef VIDEO_IN
for (unsigned int i = 0; i < context->inputs.length; i++) {
if (context->inputs.values[i].needs_reload) {
shaders_relink_input(&program, &project, &context->inputs, i);
context->inputs.values[i].needs_reload = false;
}
}
#endif /* VIDEO_IN */
compute_fps(trace_fps);
context->time = window_get_time();
@@ -248,6 +298,8 @@ static void loop(bool hr, bool trace_fps) {
}
window_events();
return true;
}
static void shutdown(const Parameters *params) {
@@ -288,8 +340,10 @@ void forge_run(const Parameters *params) {
}
while (!should_close()) {
loop(params->hot_reload, params->trace_fps);
if (!loop(params->hot_reload, params->trace_fps)) {
return;
}
}
shutdown(params);
}
}