shared data and pass fps to main thread

This commit is contained in:
2025-09-26 17:10:54 +02:00
parent 30c0eaa84b
commit 80ea990cf7
14 changed files with 210 additions and 42 deletions
+24 -10
View File
@@ -10,6 +10,7 @@
#include "forge.h"
#include "rand.h"
#include "shaders.h"
#include "shared.h"
#include "timer.h"
#include "types.h"
#include "video.h"
@@ -24,15 +25,19 @@ static File *fragment_shaders;
static File common_shader_code;
static Timer timer;
static ConfigFile shader_config;
static bool stop;
static SharedBool *stop;
static void compute_fps() {
unsigned int i;
static unsigned int compute_fps() {
double fps;
char title[100];
if (timer_inc(&timer)) {
fps = timer_reset(&timer);
log_trace("(main) %.2ffps", fps);
if (window_output != NULL) {
sprintf(title, PACKAGE " " VERSION " - %.0ffps", fps);
window_update_title(window_output, title);
@@ -42,9 +47,15 @@ static unsigned int compute_fps() {
sprintf(title, PACKAGE " " VERSION " (monitor) - %.0ffps", fps);
window_update_title(window_monitor, title);
}
context.fps = (unsigned int)round(fps);
}
return (unsigned int)round(fps);
for (i = 0; i < program.in_count; i++) {
if (!inputs[i].error) {
context.input_fps[i] = inputs[i].fps->value;
}
}
}
static void randomize_context_state() {
@@ -79,6 +90,8 @@ static void init_context(Parameters params) {
(unsigned int *)calloc(program.in_count, sizeof(unsigned int));
context.input_formats =
(unsigned int *)calloc(program.in_count, sizeof(unsigned int));
context.input_fps =
(unsigned int *)calloc(program.in_count, sizeof(unsigned int));
for (i = 0; i < program.in_count; i++) {
if (!inputs[i].error) {
@@ -95,6 +108,7 @@ static void free_context() {
free(context.input_widths);
free(context.input_heights);
free(context.input_formats);
free(context.input_fps);
}
static void hot_reload() {
@@ -175,7 +189,7 @@ static void start_video_captures(unsigned int video_count) {
for (i = 0; i < video_count; i++) {
if (!inputs[i].error) {
video_background_read(&inputs[i], &stop);
video_background_read(&inputs[i], stop);
}
}
}
@@ -195,7 +209,7 @@ static void free_video_captures(unsigned int video_count) {
static void error_callback(int error, const char *description) {
log_error("[GLFW] %d: %s", error, description);
window_terminate();
stop = true;
stop->value = true;
exit(EXIT_FAILURE);
}
@@ -219,7 +233,7 @@ static void loop(bool hr) {
hot_reload();
}
context.fps = compute_fps();
compute_fps();
context.time = window_get_time();
@@ -245,7 +259,7 @@ static void loop(bool hr) {
void forge_run(Parameters params) {
unsigned int frag_count;
stop = false;
stop = shared_init_bool("/" PACKAGE "_stop", false);
shader_config = config_file_read(params.frag_config_path, false);
@@ -253,12 +267,12 @@ void forge_run(Parameters params) {
init_files(params.frag_path, frag_count);
init_inputs(params.video_in, params.video_in_count, params.video_size);
window_startup(error_callback);
context.internal_height = params.internal_size;
init_inputs(params.video_in, params.video_in_count, params.video_size);
if (params.output) {
window_output = window_init(PACKAGE " " VERSION, params.output_screen,
params.windowed, NULL, key_callback);
@@ -303,7 +317,7 @@ void forge_run(Parameters params) {
loop(params.hot_reload);
}
stop = true;
stop->value = true;
wait(NULL);
+26 -5
View File
@@ -272,13 +272,28 @@ static void init_single_program(ShaderProgram *program, unsigned int i,
prefix = config_file_get_str(shader_config, "UNIFORM_IN_RESOLUTION_PREFIX",
"iInputResolution");
for (j = 0; j < program->in_count; j++) {
sprintf(name, "%s%d", prefix, j + 1);
program->iinres_locations[i * program->in_count + j] =
glGetUniformLocation(program->programs[i], name);
}
prefix = config_file_get_str(shader_config, "UNIFORM_IN_FORMAT_PREFIX",
"iInputFormat");
for (j = 0; j < program->in_count; j++) {
sprintf(name, "%s%d", prefix, j + 1);
program->iinfmt_locations[i * program->in_count + j] =
glGetUniformLocation(program->programs[i], name);
}
prefix =
config_file_get_str(shader_config, "UNIFORM_IN_FPS_PREFIX", "iInputFPS");
for (j = 0; j < program->in_count; j++) {
sprintf(name, "%s%d", prefix, j + 1);
program->iinfps_locations[i * program->in_count + j] =
glGetUniformLocation(program->programs[i], name);
}
prefix = config_file_get_str(shader_config, "UNIFORM_SEED_PREFIX", "seed");
for (j = 0; j < program->frag_count; j++) {
sprintf(name, "%s%d", prefix, j + 1);
@@ -335,6 +350,10 @@ static void init_programs(ShaderProgram *program, ConfigFile shader_config) {
program->itexres_locations = malloc(program->frag_count * sizeof(GLuint));
program->iinres_locations =
malloc(program->frag_count * program->in_count * sizeof(GLuint));
program->iinfmt_locations =
malloc(program->frag_count * program->in_count * sizeof(GLuint));
program->iinfps_locations =
malloc(program->frag_count * program->in_count * sizeof(GLuint));
program->idemo_locations = malloc(program->frag_count * sizeof(GLuint));
program->iseed_locations =
malloc(program->frag_count * program->frag_count * sizeof(GLuint));
@@ -435,8 +454,7 @@ static void use_program(ShaderProgram program, int i, bool output,
Context context) {
unsigned int j, k;
GLuint *subroutines;
vec2 resolution, tex_resolution;
vec3 in_resolution;
vec2 resolution, tex_resolution, in_resolution;
resolution[0] = (float)context.width;
resolution[1] = (float)context.height;
@@ -474,10 +492,13 @@ static void use_program(ShaderProgram program, int i, bool output,
for (j = 0; j < program.in_count; j++) {
in_resolution[0] = context.input_widths[j];
in_resolution[1] = context.input_heights[j];
in_resolution[2] = context.input_formats[j];
glUniform3fv(program.iinres_locations[i * program.in_count + j], 1,
glUniform2fv(program.iinres_locations[i * program.in_count + j], 1,
(const GLfloat *)&in_resolution);
glUniform1i(program.iinfmt_locations[i * program.in_count + j],
(const GLint)context.input_formats[j]);
glUniform1i(program.iinfps_locations[i * program.in_count + j],
(const GLint)context.input_fps[j]);
}
// set seeds uniforms
+51
View File
@@ -0,0 +1,51 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "shared.h"
#include "types.h"
static void *open_shared(const char *key, size_t size, int *fd) {
*fd = shm_open(key, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(*fd, size);
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
}
static void close_shared(void *shared, size_t size, int fd) {
munmap(shared, size);
close(fd);
}
SharedUint *shared_init_uint(const char *key, unsigned int initial_value) {
int shared_fd;
SharedUint *shared;
shared = open_shared(key, sizeof(SharedUint), &shared_fd);
shared->fd = shared_fd;
shared->value = initial_value;
return shared;
}
void shared_close_uint(SharedUint *shared) {
close_shared(shared, sizeof(SharedUint), shared->fd);
}
SharedBool *shared_init_bool(const char *key, bool initial_value) {
int shared_fd;
SharedBool *shared;
shared = open_shared(key, sizeof(SharedBool), &shared_fd);
shared->fd = shared_fd;
shared->value = initial_value;
return shared;
}
void shared_close_bool(SharedBool *shared) {
close_shared(shared, sizeof(SharedBool), shared->fd);
}
+12
View File
@@ -0,0 +1,12 @@
#include "types.h"
#ifndef SHARED_H
#define SHARED_H
SharedUint *shared_init_uint(const char *key, unsigned int initial_value);
void shared_close_uint(SharedUint *shared);
SharedBool *shared_init_bool(const char *key, bool initial_value);
void shared_close_bool(SharedBool *shared);
#endif /* SHARED_H */
+14
View File
@@ -13,6 +13,16 @@
#ifndef TYPES_H
#define TYPES_H
typedef struct SharedUint {
int fd;
unsigned int value;
} SharedUint;
typedef struct SharedBool {
int fd;
bool value;
} SharedBool;
typedef struct Parameters {
bool hot_reload;
bool output;
@@ -70,6 +80,8 @@ typedef struct ShaderProgram {
GLuint *ires_locations;
GLuint *itexres_locations;
GLuint *iinres_locations;
GLuint *iinfmt_locations;
GLuint *iinfps_locations;
GLuint *idemo_locations;
GLuint *iseed_locations;
GLuint *istate_locations;
@@ -95,6 +107,7 @@ typedef struct VideoCapture {
unsigned int height;
unsigned int pixelformat;
unsigned int bytesperline;
SharedUint *fps;
bool output;
struct v4l2_buffer buf;
EGLImageKHR dma_image;
@@ -117,6 +130,7 @@ typedef struct Context {
unsigned int *input_widths;
unsigned int *input_heights;
unsigned int *input_formats;
unsigned int *input_fps;
} Context;
typedef struct Timer {
+31 -6
View File
@@ -3,10 +3,14 @@
#include <linux/videodev2.h>
#include <log.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "config.h"
#include "rand.h"
#include "shared.h"
#include "timer.h"
#include "types.h"
#include "video.h"
@@ -266,6 +270,14 @@ static void create_image_buffer(VideoCapture *video_capture) {
ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf);
}
static void create_shared_data(VideoCapture *video_capture) {
char name[256];
sprintf(name, "/" PACKAGE "_fps_%d", rand_uint(1000000));
video_capture->fps = shared_init_uint(name, 0);
}
static void close_stream(VideoCapture video_capture) {
ioctl(video_capture.fd, VIDIOC_STREAMOFF, &buf_type);
}
@@ -305,6 +317,8 @@ VideoCapture video_init(char *name, unsigned int preferred_height) {
create_image_buffer(&video_capture);
create_shared_data(&video_capture);
return video_capture;
}
@@ -326,9 +340,11 @@ static bool read_video(VideoCapture *video_capture) {
return true;
}
void video_background_read(VideoCapture *video_capture, bool *stop) {
void video_background_read(VideoCapture *video_capture, SharedBool *stop) {
pid_t pid;
Timer timer;
double fps;
pid = fork();
if (pid < 0) {
log_error("Could not create subprocess");
@@ -341,21 +357,30 @@ void video_background_read(VideoCapture *video_capture, bool *stop) {
pid);
timer = timer_init(30);
while (!*stop && read_video(video_capture)) {
while (!stop->value && read_video(video_capture)) {
// repeat infinitely
if (timer_inc(&timer)) {
log_trace("(%s) %.2ffps", video_capture->name, timer_reset(&timer));
fps = timer_reset(&timer);
video_capture->fps->value = (unsigned int)round(fps);
log_trace("(%s) %.2ffps", video_capture->name, fps);
}
}
log_info("%s background acquisition stopped (pid: %d)", video_capture->name,
pid);
if (stop->value) {
log_info("%s background acquisition stopped by main thread (pid: %d)",
video_capture->name, pid);
} else {
log_info("%s background acquisition stopped after error (pid: %d)",
video_capture->name, pid);
}
window_terminate();
exit(EXIT_SUCCESS);
exit(stop->value ? EXIT_SUCCESS : EXIT_FAILURE);
}
void video_free(VideoCapture video_capture) {
if (!video_capture.error) {
close_stream(video_capture);
shared_close_uint(video_capture.fps);
}
if (video_capture.exp_fd != -1) {
close(video_capture.exp_fd);
+1 -1
View File
@@ -5,7 +5,7 @@
VideoCapture video_init(char *name, unsigned int preferred_height);
void video_background_read(VideoCapture *video_capture, bool *stop);
void video_background_read(VideoCapture *video_capture, SharedBool *stop);
void video_free(VideoCapture video_capture);