Compare commits
7
Commits
fddb11dbe3
...
v1.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5b2d2306f | ||
|
|
54b166d33f | ||
|
|
344029f195 | ||
|
|
4837ab2786 | ||
|
|
e38f57af46 | ||
|
|
e667c6b869 | ||
|
|
0b344eb52a |
@@ -1,12 +1,12 @@
|
|||||||
pkgname=forge-steel
|
pkgname=forge-steel
|
||||||
pkgver=1.1.2
|
pkgver=1.1.3
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Fusion Of Real Time Generative Effects"
|
pkgdesc="Fusion Of Real Time Generative Effects"
|
||||||
arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv7h' 'armv6h' 'aarch64' 'riscv64')
|
arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv7h' 'armv6h' 'aarch64' 'riscv64')
|
||||||
depends=('glfw>=1:3', 'v4l-utils>=1.32', 'alsa-lib>=1.2', 'libglvnd>=1.7')
|
depends=('glfw>=1:3', 'v4l-utils>=1.32', 'alsa-lib>=1.2', 'libglvnd>=1.7')
|
||||||
url="https://git.klemek.fr/klemek/forge-steel"
|
url="https://git.klemek.fr/klemek/forge-steel"
|
||||||
source=("${pkgname}-steel-${pkgver}.tar.gz::https://git.klemek.fr/klemek/forge-steel/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
source=("${pkgname}-steel-${pkgver}.tar.gz::https://git.klemek.fr/klemek/forge-steel/releases/download/v${pkgver}/${pkgname}-${pkgver}.tar.gz")
|
||||||
sha256sums=('cf4b280fba47d649ab33596d43872a70dd443ed6d15dc587b9dac4e5db294e06')
|
sha256sums=('536370c14aaac35729b29270cecca01a6c966bcae306fa2ec20f8a514a3ed8bd')
|
||||||
srcdir=build
|
srcdir=build
|
||||||
backup=("usr/share/${pkgname}")
|
backup=("usr/share/${pkgname}")
|
||||||
|
|
||||||
|
|||||||
@@ -174,9 +174,9 @@ These are configurable in the [`forge_project.cfg`](#forge_projectcfg).
|
|||||||
### CLI arguments
|
### CLI arguments
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
forge steel-VERSION
|
forge steel-dev
|
||||||
|
|
||||||
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]
|
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] [-vf=FOURCC] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-mr / -nmr] [-tm] [-tf]
|
||||||
|
|
||||||
Fusion Of Real-time Generative Effects.
|
Fusion Of Real-time Generative Effects.
|
||||||
|
|
||||||
@@ -196,10 +196,11 @@ options:
|
|||||||
-nar, --no-auto-random do not randomize state (default)
|
-nar, --no-auto-random do not randomize state (default)
|
||||||
-arc, --auto-random-cycle auto random cycle length (default: 4)
|
-arc, --auto-random-cycle auto random cycle length (default: 4)
|
||||||
-vi, --video-in path to video capture device (multiple allowed)
|
-vi, --video-in path to video capture device (multiple allowed)
|
||||||
-vb, --video-buffers number of video buffers to use (default: 2)
|
-vb, --video-buffers number of video buffers to use (default: 1)
|
||||||
-vs, --video-size video capture desired height (default: internal texture height)
|
-vs, --video-size video capture desired height (default: internal texture height)
|
||||||
-vr, --video-reconnect auto-reconnect video (default)
|
-vr, --video-reconnect auto-reconnect video (default)
|
||||||
-nvr, --no-video-reconnect do not auto-reconnect video
|
-nvr, --no-video-reconnect do not auto-reconnect video
|
||||||
|
-vf, --video-fourcc video codec fourcc (default: YUYV)
|
||||||
-is, --internal-size internal texture height (default: 720)
|
-is, --internal-size internal texture height (default: 720)
|
||||||
-ls, --load-state load saved state (default)
|
-ls, --load-state load saved state (default)
|
||||||
-nls, --no-load-state do not load saved state
|
-nls, --no-load-state do not load saved state
|
||||||
@@ -499,7 +500,7 @@ You can check your device real FPS on [V4L2 UCP](https://github.com/HedgeHawk/v4
|
|||||||
|
|
||||||
### My video feed got strange lines
|
### My video feed got strange lines
|
||||||
|
|
||||||
You need to decode the [V4L2 YUYV format](https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-yuyv.html).
|
You may need to decode the [V4L2 YUYV format](https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-yuyv.html).
|
||||||
|
|
||||||
The code is available in the default project [default/inc_yuyv.glsl](./default/inc_yuyv.glsl)
|
The code is available in the default project [default/inc_yuyv.glsl](./default/inc_yuyv.glsl)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([forge], [steel-1.1.2], [klemek.dev@proton.me])
|
AC_INIT([forge], [steel-1.1.3], [klemek.dev@proton.me])
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ GROUP_3_1_Y=58
|
|||||||
GROUP_3_1_Z=
|
GROUP_3_1_Z=
|
||||||
GROUP_3_2_X=0
|
GROUP_3_2_X=0
|
||||||
GROUP_3_2_Y=16
|
GROUP_3_2_Y=16
|
||||||
GROUP_3_2_Z=
|
GROUP_3_2_Z=11089
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
# OTHER
|
# OTHER
|
||||||
|
|||||||
+4
-1
@@ -15,9 +15,12 @@ uniform sampler2D iTex1;
|
|||||||
uniform sampler2D iTex3;
|
uniform sampler2D iTex3;
|
||||||
uniform int iInputFormat1;
|
uniform int iInputFormat1;
|
||||||
uniform vec2 iInputResolution1;
|
uniform vec2 iInputResolution1;
|
||||||
|
uniform vec3 iGroup3_1[2];
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (iInputFormat1 == YUYV_FOURCC) {
|
if (iGroup3_1[1].z > 0) {
|
||||||
|
fragColor = texture(iTex1, vUV * vec2(1, -1));
|
||||||
|
} else if (iInputFormat1 == YUYV_FOURCC) {
|
||||||
fragColor = yuyvTex(iTex1, vUV, int(iInputResolution1.x));
|
fragColor = yuyvTex(iTex1, vUV, int(iInputResolution1.x));
|
||||||
} else {
|
} else {
|
||||||
fragColor = texture(iTex0, vUV);
|
fragColor = texture(iTex0, vUV);
|
||||||
|
|||||||
+4
-1
@@ -15,9 +15,12 @@ uniform sampler2D iTex2;
|
|||||||
uniform sampler2D iTex4;
|
uniform sampler2D iTex4;
|
||||||
uniform int iInputFormat2;
|
uniform int iInputFormat2;
|
||||||
uniform vec2 iInputResolution2;
|
uniform vec2 iInputResolution2;
|
||||||
|
uniform vec3 iGroup3_1[2];
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
if (iInputFormat2 == YUYV_FOURCC) {
|
if (iGroup3_1[1].z > 0) {
|
||||||
|
fragColor = texture(iTex2, vUV * vec2(1, -1));
|
||||||
|
} else if (iInputFormat2 == YUYV_FOURCC) {
|
||||||
fragColor = yuyvTex(iTex2, vUV, int(iInputResolution2.x));
|
fragColor = yuyvTex(iTex2, vUV, int(iInputResolution2.x));
|
||||||
} else {
|
} else {
|
||||||
fragColor = texture(iTex0, vUV);
|
fragColor = texture(iTex0, vUV);
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
uniform int iDemo;
|
uniform int iDemo;
|
||||||
|
|
||||||
uniform sampler2D iTex0;
|
uniform sampler2D iTex0;
|
||||||
uniform sampler2D iTex5;
|
uniform sampler2D iTex3;
|
||||||
uniform sampler2D iTex6;
|
uniform sampler2D iTex4;
|
||||||
|
|
||||||
subroutine vec4 src_stage_sub(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3);
|
subroutine vec4 src_stage_sub(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3);
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ subroutine ( src_stage_sub ) vec4 src_6(vec2 vUV, int seed, vec3 b1, vec2 f1, ve
|
|||||||
return src_2(vUV, seed, b1, f1, b2, f2, b3, f3);
|
return src_2(vUV, seed, b1, f1, b2, f2, b3, f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
return src_thru(vUV, iTex5, seed, b1, f1, b2, f2, b3, f3);
|
return src_thru(vUV, iTex3, seed, b1, f1, b2, f2, b3, f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include inc_cp437.glsl
|
#include inc_cp437.glsl
|
||||||
@@ -462,7 +462,7 @@ subroutine ( src_stage_sub ) vec4 src_11(vec2 vUV, int seed, vec3 b1, vec2 f1, v
|
|||||||
return src_3(vUV, seed, b1, f1, b2, f2, b3, f3);
|
return src_3(vUV, seed, b1, f1, b2, f2, b3, f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
return src_thru(vUV, iTex6, seed, b1, f1, b2, f2, b3, f3);
|
return src_thru(vUV, iTex4, seed, b1, f1, b2, f2, b3, f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRC 12 : Scales
|
// SRC 12 : Scales
|
||||||
|
|||||||
+23
-7
@@ -3,11 +3,27 @@
|
|||||||
|
|
||||||
const int YUYV_FOURCC = 1448695129;
|
const int YUYV_FOURCC = 1448695129;
|
||||||
|
|
||||||
const mat3x3 yuyv_to_rgb = {{1,1,1},{0,-0.39465,2.03211},{1.13983,-0.5806,0}};
|
// https://en.wikipedia.org/wiki/Y%E2%80%B2UV
|
||||||
|
const mat3x3 yuyv_to_rgb_bt709 = {
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
-0.21482,
|
||||||
|
2.12798
|
||||||
|
},
|
||||||
|
{
|
||||||
|
1.28033,
|
||||||
|
-0.38059,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
vec4 yuyvTex(sampler2D tex, vec2 vUV, int base_width) {
|
vec4 yuyvTex(sampler2D tex, vec2 vUV, int base_width) {
|
||||||
float w = base_width - 1;
|
float w = base_width - 1;
|
||||||
|
|
||||||
int x = int(vUV.x * w);
|
int x = int(vUV.x * w);
|
||||||
|
|
||||||
int xU = x - x % 2;
|
int xU = x - x % 2;
|
||||||
@@ -17,12 +33,12 @@ vec4 yuyvTex(sampler2D tex, vec2 vUV, int base_width) {
|
|||||||
vec4 tV = texture(tex, vec2(xV / w, 1 - vUV.y));
|
vec4 tV = texture(tex, vec2(xV / w, 1 - vUV.y));
|
||||||
|
|
||||||
vec3 yuv = vec3(
|
vec3 yuv = vec3(
|
||||||
x % 2 == 0 ? tU.x : tV.x,
|
x % 2 == 0 ? tU.x : tV.x,
|
||||||
tU.y - 0.5,
|
tU.y - 0.5,
|
||||||
tV.y - 0.5
|
tV.y - 0.5
|
||||||
);
|
);
|
||||||
|
|
||||||
return vec4(yuyv_to_rgb * yuv, 1.0);
|
return vec4(yuyv_to_rgb_bt709 * yuv, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+10
-2
@@ -34,6 +34,7 @@ static void print_help(int status_code) {
|
|||||||
"[-vs=SIZE] "
|
"[-vs=SIZE] "
|
||||||
"[-vb=COUNT] "
|
"[-vb=COUNT] "
|
||||||
"[-vr / -nvr] "
|
"[-vr / -nvr] "
|
||||||
|
"[-vf=FOURCC] "
|
||||||
#endif /* VIDEO_IN */
|
#endif /* VIDEO_IN */
|
||||||
"[-is=SIZE] "
|
"[-is=SIZE] "
|
||||||
"[-ls / -nls] "
|
"[-ls / -nls] "
|
||||||
@@ -65,11 +66,12 @@ static void print_help(int status_code) {
|
|||||||
" -vi, --video-in path to video capture device (multiple "
|
" -vi, --video-in path to video capture device (multiple "
|
||||||
"allowed)\n"
|
"allowed)\n"
|
||||||
" -vb, --video-buffers number of video buffers to use (default: "
|
" -vb, --video-buffers number of video buffers to use (default: "
|
||||||
"2)\n"
|
"1)\n"
|
||||||
" -vs, --video-size video capture desired height (default: "
|
" -vs, --video-size video capture desired height (default: "
|
||||||
"internal texture height)\n"
|
"internal texture height)\n"
|
||||||
" -vr, --video-reconnect auto-reconnect video (default)\n"
|
" -vr, --video-reconnect auto-reconnect video (default)\n"
|
||||||
" -nvr, --no-video-reconnect do not auto-reconnect video\n"
|
" -nvr, --no-video-reconnect do not auto-reconnect video\n"
|
||||||
|
" -vf, --video-fourcc video codec fourcc (default: YUYV)\n"
|
||||||
#endif /* VIDEO_IN */
|
#endif /* VIDEO_IN */
|
||||||
" -is, --internal-size internal texture height (default: 720)\n"
|
" -is, --internal-size internal texture height (default: 720)\n"
|
||||||
" -ls, --load-state load saved state (default)\n"
|
" -ls, --load-state load saved state (default)\n"
|
||||||
@@ -139,9 +141,10 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
|||||||
params->auto_random_cycle = 4;
|
params->auto_random_cycle = 4;
|
||||||
#ifdef VIDEO_IN
|
#ifdef VIDEO_IN
|
||||||
params->video_in.length = 0;
|
params->video_in.length = 0;
|
||||||
params->video_buffers = 2;
|
params->video_buffers = 1;
|
||||||
params->video_size = 0;
|
params->video_size = 0;
|
||||||
params->video_reconnect = true;
|
params->video_reconnect = true;
|
||||||
|
strlcpy(params->video_fourcc, "YUYV", 5);
|
||||||
#endif /* VIDEO_IN */
|
#endif /* VIDEO_IN */
|
||||||
params->internal_size = 720;
|
params->internal_size = 720;
|
||||||
params->load_state = true;
|
params->load_state = true;
|
||||||
@@ -243,6 +246,11 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
|||||||
params->video_reconnect = true;
|
params->video_reconnect = true;
|
||||||
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
|
} else if (is_arg(arg, "-nvr") || is_arg(arg, "--no-video-reconnect")) {
|
||||||
params->video_reconnect = false;
|
params->video_reconnect = false;
|
||||||
|
} else if (is_arg(arg, "-vf") || is_arg(arg, "--video-fourcc")) {
|
||||||
|
if (strlen(value) == 0) {
|
||||||
|
invalid_value(arg, value);
|
||||||
|
}
|
||||||
|
strlcpy(params->video_fourcc, value, 5);
|
||||||
} else {
|
} else {
|
||||||
invalid_arg(arg);
|
invalid_arg(arg);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -85,7 +85,8 @@ static void init_inputs() {
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
|
for (unsigned int i = 0; i < init_params.video_in.length; i++) {
|
||||||
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
||||||
init_params.video_size, init_params.video_buffers, true);
|
init_params.video_size, init_params.video_buffers,
|
||||||
|
init_params.video_fourcc, true);
|
||||||
|
|
||||||
if (!video_captures.values[i].error) {
|
if (!video_captures.values[i].error) {
|
||||||
context.input_resolutions[i][0] = video_captures.values[i].width;
|
context.input_resolutions[i][0] = video_captures.values[i].width;
|
||||||
@@ -125,7 +126,8 @@ background_reconnect_video_captures(__attribute__((unused)) void *args) {
|
|||||||
if (video_captures.values[i].disconnected) {
|
if (video_captures.values[i].disconnected) {
|
||||||
video_free(&video_captures.values[i]);
|
video_free(&video_captures.values[i]);
|
||||||
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
video_init(&video_captures.values[i], init_params.video_in.values[i],
|
||||||
init_params.video_size, init_params.video_buffers, false);
|
init_params.video_size, init_params.video_buffers,
|
||||||
|
init_params.video_fourcc, false);
|
||||||
|
|
||||||
if (!video_captures.values[i].error) {
|
if (!video_captures.values[i].error) {
|
||||||
context.input_resolutions[i][0] = video_captures.values[i].width;
|
context.input_resolutions[i][0] = video_captures.values[i].width;
|
||||||
@@ -313,6 +315,10 @@ static bool init(const Parameters *params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VIDEO_IN
|
#ifdef VIDEO_IN
|
||||||
|
if (params->output && params->monitor) {
|
||||||
|
window_use(window_output, &context);
|
||||||
|
}
|
||||||
|
|
||||||
shaders_link_inputs(&program, &project, &video_captures,
|
shaders_link_inputs(&program, &project, &video_captures,
|
||||||
init_params.video_buffers);
|
init_params.video_buffers);
|
||||||
#endif /* VIDEO_IN */
|
#endif /* VIDEO_IN */
|
||||||
|
|||||||
@@ -245,12 +245,6 @@ static bool link_input_to_texture(ShaderProgram *program, VideoCapture *input,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, input->width, input->height, 0, GL_RGB,
|
|
||||||
GL_UNSIGNED_BYTE, 0);
|
|
||||||
if (check_glerror(program, "link_input_to_texture/glTexImage2D")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_EGL_image_storage.txt
|
// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_EGL_image_storage.txt
|
||||||
glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, dma_image, NULL);
|
glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, dma_image, NULL);
|
||||||
if (check_eglerror(program,
|
if (check_eglerror(program,
|
||||||
|
|||||||
+7
-1
@@ -7,7 +7,13 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "tempo.h"
|
#include "tempo.h"
|
||||||
|
|
||||||
static long now_ms() { return 1000 * clock() / CLOCKS_PER_SEC; }
|
static long now_ms() {
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1000 * ts.tv_sec + ts.tv_nsec / 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
static void reset_tap_chain(Tempo *tempo, long t) {
|
static void reset_tap_chain(Tempo *tempo, long t) {
|
||||||
tempo->last_reset = t;
|
tempo->last_reset = t;
|
||||||
|
|||||||
+8
-4
@@ -1,3 +1,4 @@
|
|||||||
|
#include <bits/time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@
|
|||||||
void timer_init(Timer *timer, const unsigned int target) {
|
void timer_init(Timer *timer, const unsigned int target) {
|
||||||
timer->counter = 0;
|
timer->counter = 0;
|
||||||
timer->target = target;
|
timer->target = target;
|
||||||
timer->start = clock();
|
clock_gettime(CLOCK_REALTIME, &timer->start);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool timer_inc(Timer *timer) {
|
bool timer_inc(Timer *timer) {
|
||||||
@@ -17,13 +18,16 @@ bool timer_inc(Timer *timer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double timer_reset(Timer *timer) {
|
double timer_reset(Timer *timer) {
|
||||||
clock_t stop;
|
struct timespec stop;
|
||||||
double secs;
|
double secs;
|
||||||
double per_secs;
|
double per_secs;
|
||||||
|
|
||||||
stop = clock();
|
if (clock_gettime(CLOCK_REALTIME, &stop) != 0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
secs = (double)(stop - timer->start) / CLOCKS_PER_SEC;
|
secs = (double)(stop.tv_sec - timer->start.tv_sec) +
|
||||||
|
(double)(stop.tv_nsec - timer->start.tv_nsec) / 1e9;
|
||||||
per_secs = (double)timer->counter / secs;
|
per_secs = (double)timer->counter / secs;
|
||||||
|
|
||||||
timer->start = stop;
|
timer->start = stop;
|
||||||
|
|||||||
+2
-1
@@ -50,6 +50,7 @@ typedef struct Parameters {
|
|||||||
unsigned int video_buffers;
|
unsigned int video_buffers;
|
||||||
unsigned int video_size;
|
unsigned int video_size;
|
||||||
bool video_reconnect;
|
bool video_reconnect;
|
||||||
|
char video_fourcc[5];
|
||||||
#endif /* VIDEO_IN */
|
#endif /* VIDEO_IN */
|
||||||
unsigned int internal_size;
|
unsigned int internal_size;
|
||||||
bool load_state;
|
bool load_state;
|
||||||
@@ -279,7 +280,7 @@ typedef struct StateBackgroundWriteArgs {
|
|||||||
// timer.c
|
// timer.c
|
||||||
|
|
||||||
typedef struct Timer {
|
typedef struct Timer {
|
||||||
clock_t start;
|
struct timespec start;
|
||||||
unsigned int counter;
|
unsigned int counter;
|
||||||
unsigned int target;
|
unsigned int target;
|
||||||
} Timer;
|
} Timer;
|
||||||
|
|||||||
+26
-9
@@ -16,7 +16,6 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
|
|
||||||
static const unsigned int pixel_format = V4L2_PIX_FMT_YUYV;
|
|
||||||
static const enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
static const enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
|
||||||
static void ioctl_error(VideoCapture *video_capture, const char *operation,
|
static void ioctl_error(VideoCapture *video_capture, const char *operation,
|
||||||
@@ -70,6 +69,19 @@ static void ioctl_error(VideoCapture *video_capture, const char *operation,
|
|||||||
video_capture->error = true;
|
video_capture->error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fourcc_to_string(unsigned int fourcc, char *str) {
|
||||||
|
str[0] = (char)(fourcc & 0xFF);
|
||||||
|
str[1] = (char)((fourcc >> 8) & 0xFF);
|
||||||
|
str[2] = (char)((fourcc >> 16) & 0xFF);
|
||||||
|
str[3] = (char)((fourcc >> 24) & 0xFF);
|
||||||
|
str[4] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int string_to_fourcc(const char *str) {
|
||||||
|
return (unsigned int)str[0] | ((unsigned int)str[1] << 8) |
|
||||||
|
((unsigned int)str[2] << 16) | ((unsigned int)str[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
static void open_device(VideoCapture *video_capture, const char *name,
|
static void open_device(VideoCapture *video_capture, const char *name,
|
||||||
bool log_error) {
|
bool log_error) {
|
||||||
strlcpy(video_capture->name, name, STR_LEN);
|
strlcpy(video_capture->name, name, STR_LEN);
|
||||||
@@ -112,7 +124,8 @@ static bool check_caps(VideoCapture *video_capture) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool get_available_sizes(VideoCapture *video_capture,
|
static bool get_available_sizes(VideoCapture *video_capture,
|
||||||
unsigned int preferred_height) {
|
unsigned int preferred_height,
|
||||||
|
unsigned int pixel_format) {
|
||||||
struct v4l2_frmsizeenum fmt_enum;
|
struct v4l2_frmsizeenum fmt_enum;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -165,8 +178,9 @@ static bool get_available_sizes(VideoCapture *video_capture,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool set_format(VideoCapture *video_capture) {
|
static bool set_format(VideoCapture *video_capture, unsigned int pixel_format) {
|
||||||
struct v4l2_format fmt;
|
struct v4l2_format fmt;
|
||||||
|
char fourcc[STR_LEN];
|
||||||
|
|
||||||
memset(&fmt, 0, sizeof(fmt));
|
memset(&fmt, 0, sizeof(fmt));
|
||||||
|
|
||||||
@@ -187,9 +201,9 @@ static bool set_format(VideoCapture *video_capture) {
|
|||||||
video_capture->pixelformat = fmt.fmt.pix.pixelformat;
|
video_capture->pixelformat = fmt.fmt.pix.pixelformat;
|
||||||
video_capture->bytesperline = fmt.fmt.pix.bytesperline;
|
video_capture->bytesperline = fmt.fmt.pix.bytesperline;
|
||||||
|
|
||||||
log_info("(%s) Format fourcc: %c%c%c%c", video_capture->name,
|
fourcc_to_string(fmt.fmt.pix.pixelformat, fourcc);
|
||||||
fmt.fmt.pix.pixelformat, fmt.fmt.pix.pixelformat >> 8,
|
|
||||||
fmt.fmt.pix.pixelformat >> 16, fmt.fmt.pix.pixelformat >> 24);
|
log_info("(%s) Format fourcc: %s", video_capture->name, fourcc);
|
||||||
log_info("(%s) Resolution: %dx%d", video_capture->name, fmt.fmt.pix.width,
|
log_info("(%s) Resolution: %dx%d", video_capture->name, fmt.fmt.pix.width,
|
||||||
fmt.fmt.pix.height);
|
fmt.fmt.pix.height);
|
||||||
|
|
||||||
@@ -326,7 +340,7 @@ static unsigned int read_video(VideoCapture *video_capture) {
|
|||||||
|
|
||||||
void video_init(VideoCapture *video_capture, const char *name,
|
void video_init(VideoCapture *video_capture, const char *name,
|
||||||
unsigned int preferred_height, unsigned int buffer_count,
|
unsigned int preferred_height, unsigned int buffer_count,
|
||||||
bool log_error) {
|
const char *video_fourcc, bool log_error) {
|
||||||
open_device(video_capture, name, log_error);
|
open_device(video_capture, name, log_error);
|
||||||
|
|
||||||
if (video_capture->error) {
|
if (video_capture->error) {
|
||||||
@@ -339,13 +353,14 @@ void video_init(VideoCapture *video_capture, const char *name,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_available_sizes(video_capture, preferred_height)) {
|
if (!get_available_sizes(video_capture, preferred_height,
|
||||||
|
string_to_fourcc(video_fourcc))) {
|
||||||
video_capture->error = true;
|
video_capture->error = true;
|
||||||
video_free(video_capture);
|
video_free(video_capture);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!set_format(video_capture)) {
|
if (!set_format(video_capture, string_to_fourcc(video_fourcc))) {
|
||||||
video_capture->error = true;
|
video_capture->error = true;
|
||||||
video_free(video_capture);
|
video_free(video_capture);
|
||||||
return;
|
return;
|
||||||
@@ -413,6 +428,8 @@ void *video_background_read(void *args) {
|
|||||||
video_capture->name);
|
video_capture->name);
|
||||||
video_capture->disconnected = true;
|
video_capture->disconnected = true;
|
||||||
context->input_formats[input_index] = 0;
|
context->input_formats[input_index] = 0;
|
||||||
|
context->input_resolutions[input_index][0] = 0;
|
||||||
|
context->input_resolutions[input_index][1] = 0;
|
||||||
}
|
}
|
||||||
free(process_args);
|
free(process_args);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
void video_init(VideoCapture *video_capture, const char *name,
|
void video_init(VideoCapture *video_capture, const char *name,
|
||||||
unsigned int preferred_height, unsigned int buffer_count,
|
unsigned int preferred_height, unsigned int buffer_count,
|
||||||
bool log_error);
|
const char *video_fourcc, bool log_error);
|
||||||
|
|
||||||
void *video_background_read(void *args);
|
void *video_background_read(void *args);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user