shared data and pass fps to main thread
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects -Wall
|
||||
bin_PROGRAMS = forge
|
||||
forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c src/window.c src/shaders.c src/timer.c src/string.c src/config_file.c src/rand.c src/video.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c
|
||||
forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c src/window.c src/shaders.c src/timer.c src/string.c src/config_file.c src/rand.c src/video.c src/shared.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c
|
||||
forge_CFLAGS = -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp -I$(top_srcdir)/include -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE -DLOG_USE_COLOR
|
||||
forge_LDADD = -lm -lGL -lglfw
|
||||
include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h src/window.h src/shaders.h src/timer.h src/string.h src/config_file.h src/rand.h src/video.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h
|
||||
include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h src/window.h src/shaders.h src/timer.h src/string.h src/config_file.h src/rand.h src/video.h src/shared.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h
|
||||
+1
-1
@@ -25,7 +25,7 @@ build:
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
./build/$(TARGET) $(TEST_ARGS) --monitor-only --internal-size=240 --hot-reload
|
||||
./build/$(TARGET) $(TEST_ARGS) --monitor-only --internal-size=480 --video-size=240 --hot-reload
|
||||
|
||||
.PHONY: demo
|
||||
demo: build
|
||||
|
||||
@@ -139,7 +139,8 @@ make -f Makefile.dev release-arch
|
||||
- [x] Shader based format mapping
|
||||
- [x] Video mapping config file
|
||||
- [x] Get first video size matching internal size
|
||||
- [x] other internal size for video
|
||||
- [x] Other internal size for video
|
||||
- [x] Pass input fps into shaders for debug
|
||||
- [ ] Clean code and fix things
|
||||
- [x] Monitor screen
|
||||
- [x] 2nd window
|
||||
|
||||
@@ -5,6 +5,8 @@ UNIFORM_DEMO=iDemo
|
||||
UNIFORM_RESOLUTION=iResolution
|
||||
UNIFORM_TEX_RESOLUTION=iTexResolution
|
||||
UNIFORM_IN_RESOLUTION_PREFIX=iInputResolution
|
||||
UNIFORM_IN_FORMAT_PREFIX=iInputFormat
|
||||
UNIFORM_IN_FPS_PREFIX=iInputFPS
|
||||
UNIFORM_SEED_PREFIX=seed
|
||||
UNIFORM_STATE_PREFIX=state
|
||||
UNIFORM_TEX_PREFIX=tex
|
||||
|
||||
+38
-10
@@ -11,6 +11,10 @@ uniform float iTempo;
|
||||
uniform int iFPS;
|
||||
uniform vec2 iResolution;
|
||||
uniform vec2 iTexResolution;
|
||||
uniform vec2 iInputResolution1;
|
||||
uniform vec2 iInputResolution2;
|
||||
uniform int iInputFPS1;
|
||||
uniform int iInputFPS2;
|
||||
uniform int iDemo;
|
||||
|
||||
uniform int seed1;
|
||||
@@ -1310,12 +1314,26 @@ subroutine(src_stage_sub) vec4 src_16(vec2 vUV, int seed)
|
||||
f += selected_fx == 4 ? h_rect(uv2, vec2(-2, -3.2), vec2(1, 0), 0.1) : 0;
|
||||
|
||||
// show inputs / feedback
|
||||
f += selected_srca == 5 ? rect(uv2, vec2(-8, 2), vec2(2, 0.1)) : 0;
|
||||
f += selected_srca == 10 ? rect(uv2, vec2(-7, 2), vec2(1, 0.1)) + rect(uv2, vec2(-8, 0.5), vec2(0.1, 1.6)) + rect(uv2, vec2(-9, -1), vec2(1, 0.1)) : 0;
|
||||
f += (selected_srca == 0 || selected_srca % 5 != 0 && selected_srca >= 8) ? rect(uv2, vec2(-6.5, 2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, 4), vec2(7, 0.1)) + rect(uv2, vec2(-7, 3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, 2), vec2(0.1, 2.1)) : 0;
|
||||
f += selected_srcb == 5 ? rect(uv2, vec2(-6.5, -2), vec2(0.5, 0.1)) + rect(uv2, vec2(-7, -0.5), vec2(0.1, 1.6)) + rect(uv2, vec2(-8.5, 1), vec2(1.5, 0.1)) : 0;
|
||||
f += selected_srcb == 10 ? rect(uv2, vec2(-8, -2), vec2(2, 0.1)) : 0;
|
||||
f += (selected_srcb == 0 || selected_srcb % 5 != 0 && selected_srcb >= 8) ? rect(uv2, vec2(-6.5, -2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, -4), vec2(7, 0.1)) + rect(uv2, vec2(-7, -3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, -2), vec2(0.1, 2.1)) : 0;
|
||||
float line_a_a = rect(uv2, vec2(-8, 2), vec2(2, 0.1));
|
||||
float line_a_b = rect(uv2, vec2(-7, 2), vec2(1, 0.1)) + rect(uv2, vec2(-8, 0.5), vec2(0.1, 1.6)) + rect(uv2, vec2(-9, -1), vec2(1, 0.1));
|
||||
float line_a_f = rect(uv2, vec2(-6.5, 2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, 4), vec2(7, 0.1)) + rect(uv2, vec2(-7, 3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, 2), vec2(0.1, 2.1));
|
||||
if (selected_srca == 5) {
|
||||
f += iInputResolution1.x > 0 ? line_a_a : line_a_f;
|
||||
} else if (selected_srca == 10) {
|
||||
f += iInputResolution2.x > 0 ? line_a_b : line_a_f;
|
||||
} else if (selected_srca == 0 || selected_srca >= 8) {
|
||||
f += line_a_f;
|
||||
}
|
||||
float line_b_a = rect(uv2, vec2(-6.5, -2), vec2(0.5, 0.1)) + rect(uv2, vec2(-7, -0.5), vec2(0.1, 1.6)) + rect(uv2, vec2(-8.5, 1), vec2(1.5, 0.1));
|
||||
float line_b_b = rect(uv2, vec2(-8, -2), vec2(2, 0.1));
|
||||
float line_b_f = rect(uv2, vec2(-6.5, -2), vec2(0.5, 0.1)) + rect(uv2, vec2(0, -4), vec2(7, 0.1)) + rect(uv2, vec2(-7, -3), vec2(0.1, 1.1)) + rect(uv2, vec2(7, -2), vec2(0.1, 2.1));
|
||||
if (selected_srcb == 5) {
|
||||
f += iInputResolution1.x > 0 ? line_b_a : line_b_f;
|
||||
} else if (selected_srcb == 10) {
|
||||
f += iInputResolution2.x > 0 ? line_b_b : line_b_f;
|
||||
} else if (selected_srcb == 0 || selected_srcb >= 8) {
|
||||
f += line_b_f;
|
||||
}
|
||||
|
||||
// show page
|
||||
f += char_at(uv2, vec2(-9.2, -4.3), hex_chars[page]);
|
||||
@@ -1338,24 +1356,34 @@ subroutine(src_stage_sub) vec4 src_16(vec2 vUV, int seed)
|
||||
f += write_int(uv3, vec2(x - 4,13), iFPS, 3);
|
||||
v = min(1, iFPS/60.0);
|
||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||
f += rect(uv3, vec2(x + 4 * v - 3.5, 12), vec2(4 * v, 0.4));
|
||||
|
||||
x = 0;
|
||||
f += write_5(uv3, vec2(x,13), texts[1]);
|
||||
f += write_int(uv3, vec2(x - 4,13), int(iTempo), 3);
|
||||
v = modTime(1);
|
||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||
f += rect(uv3, vec2(x + 4 * v - 3.5, 12), vec2(4 * v, 0.4));
|
||||
|
||||
x = 15;
|
||||
f += write_5(uv3, vec2(x,13), texts[2]);
|
||||
f += write_int(uv3, vec2(x - 6,13), int(iTime), 5);
|
||||
v = fract(iTime);
|
||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||
f += rect(uv3, vec2(x + 4 * v - 3.5, 12), vec2(4 * v, 0.4));
|
||||
|
||||
f += write_5(uv3, vec2(-2,-15), iDemo > 0 ? texts[3] : texts[4]);
|
||||
|
||||
if (iInputResolution1.x > 0) {
|
||||
f += write_5(uv3, vec2(-23.5,5.5), texts[0]);
|
||||
f += write_int(uv3, vec2(-27,5.5), iInputFPS1, 3);
|
||||
}
|
||||
|
||||
if (iInputResolution2.x > 0) {
|
||||
f += write_5(uv3, vec2(-23.5,-9.5), texts[0]);
|
||||
f += write_int(uv3, vec2(-27,-9.5), iInputFPS2, 3);
|
||||
}
|
||||
|
||||
return vec4(f);
|
||||
}
|
||||
|
||||
@@ -1924,7 +1952,7 @@ subroutine(mix_stage_sub) vec4 mix_16(vec2 vUV, sampler2D ta, sampler2D tb, int
|
||||
|
||||
const mat3x3 yuv_to_rgb = {{1,1,1},{0,-0.39465,2.03211},{1.13983,-0.5806,0}};
|
||||
|
||||
const float YUYV_FOURCC = 1448695129.0;
|
||||
const int YUYV_FOURCC = 1448695129;
|
||||
|
||||
vec4 yuyvTex(sampler2D tex, vec2 vUV, int base_width) {
|
||||
float w = base_width - 1;
|
||||
|
||||
+3
-3
@@ -6,12 +6,12 @@
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec3 iInputResolution1;
|
||||
uniform int iInputFormat1;
|
||||
|
||||
void main() {
|
||||
if (iInputResolution1.z == YUYV_FOURCC) {
|
||||
if (iInputFormat1 == YUYV_FOURCC) {
|
||||
fragColor = yuyvTex(tex1, vUV, int(iInputResolution1.x));
|
||||
} else {
|
||||
fragColor = vec4(0, 0, 0, 1);
|
||||
fragColor = texture(tex0, vUV);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -6,12 +6,12 @@
|
||||
in vec2 vUV;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec3 iInputResolution2;
|
||||
uniform int iInputFormat2;
|
||||
|
||||
void main() {
|
||||
if (iInputResolution2.z == YUYV_FOURCC) {
|
||||
if (iInputFormat2 == YUYV_FOURCC) {
|
||||
fragColor = yuyvTex(tex2, vUV, int(iInputResolution2.x));
|
||||
} else {
|
||||
fragColor = vec4(0, 0, 0, 1);
|
||||
fragColor = texture(tex0, vUV);
|
||||
}
|
||||
}
|
||||
+24
-10
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user