diff --git a/Makefile.dev b/Makefile.dev index fe18012..67aa4ef 100644 --- a/Makefile.dev +++ b/Makefile.dev @@ -25,7 +25,7 @@ build: .PHONY: run run: build - ./build/$(TARGET) $(TEST_ARGS) --monitor-only --internal-size=480 --hot-reload + ./build/$(TARGET) $(TEST_ARGS) --monitor-only --internal-size=240 --hot-reload .PHONY: demo demo: build diff --git a/README.md b/README.md index e23ca8e..a2f6ab1 100644 --- a/README.md +++ b/README.md @@ -134,11 +134,12 @@ make -f Makefile.dev release-arch - [ ] Clean code and fix things - [ ] Video input - [x] Fixed camera video - - [ ] Pass video info to shaders + - [x] Pass video info to shaders - [x] Sub process video reading - [x] Shader based format mapping - [x] Video mapping config file - [x] Get first video size matching internal size + - [ ] other internal size for video - [ ] Clean code and fix things - [x] Monitor screen - [x] 2nd window diff --git a/shaders/frag0.glsl b/shaders/frag0.glsl index bef552d..0217d9b 100644 --- a/shaders/frag0.glsl +++ b/shaders/frag0.glsl @@ -798,15 +798,15 @@ float write_20(vec2 uv, vec2 pos, int str[20]) return d; } -float write_int(vec2 uv, vec2 pos, int value, int magnitude) +float write_int(vec2 uv, vec2 pos, uint value, uint magnitude) { int i; - int m = 1; + uint m = 1; float d = 0; for (i = 0; i < magnitude; i++) { if (i == 0 || value >= m) { - d += char_at(uv, pos + vec2(magnitude - i - 1, 0), int(0x30 + (value % (m * 10)) / m)); - m *= 10; + d += char_at(uv, pos + vec2(magnitude - i - 1, 0), int(0x30 + (value % (m * 10u)) / m)); + m *= 10u; } } return d; @@ -1924,15 +1924,24 @@ 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; + vec4 yuyvTex(sampler2D tex, vec2 vUV, int base_width) { float w = base_width - 1; + int x = int(vUV.x * w); + int xU = x - x % 2; int xV = x - x % 2 + 1; + + vec4 tU = texture(tex, vec2(xU / w, 1 - vUV.y)); + vec4 tV = texture(tex, vec2(xV / w, 1 - vUV.y)); + vec3 yuv = vec3( - texture(tex, vec2(vUV.x, 1 - vUV.y)).x, - texture(tex, vec2(xU / w, 1 - vUV.y)).y - 0.5, - texture(tex, vec2(xV / w, 1 - vUV.y)).y - 0.5 + x % 2 == 0 ? tU.x : tV.x, + tU.y - 0.5, + tV.y - 0.5 ); + return vec4(yuv_to_rgb * yuv, 1.0); } \ No newline at end of file diff --git a/shaders/frag1.glsl b/shaders/frag1.glsl index 4f9272f..8be51ea 100644 --- a/shaders/frag1.glsl +++ b/shaders/frag1.glsl @@ -6,6 +6,12 @@ in vec2 vUV; out vec4 fragColor; +uniform vec3 iInputResolution1; + void main() { - fragColor = yuyvTex(tex1, vUV, 848); // TODO uniform + if (iInputResolution1.z == YUYV_FOURCC) { + fragColor = yuyvTex(tex1, vUV, int(iInputResolution1.x)); + } else { + fragColor = vec4(0, 0, 0, 1); + } } \ No newline at end of file diff --git a/shaders/frag2.glsl b/shaders/frag2.glsl index b42c6ad..7fb44ff 100644 --- a/shaders/frag2.glsl +++ b/shaders/frag2.glsl @@ -6,6 +6,12 @@ in vec2 vUV; out vec4 fragColor; +uniform vec3 iInputResolution2; + void main() { - fragColor = yuyvTex(tex2, vUV, 320); // TODO uniform + if (iInputResolution2.z == YUYV_FOURCC) { + fragColor = yuyvTex(tex2, vUV, int(iInputResolution2.x)); + } else { + fragColor = vec4(0, 0, 0, 1); + } } \ No newline at end of file diff --git a/src/forge.c b/src/forge.c index 26138b0..cb4a5a3 100644 --- a/src/forge.c +++ b/src/forge.c @@ -61,12 +61,8 @@ static void init_context(Parameters params) { context.demo = params.demo; context.monitor = params.monitor; - context.sub_state = malloc(program.frag_count * program.sub_type_count * - sizeof(unsigned int)); - - for (i = 0; i < program.frag_count * program.sub_type_count; i++) { - context.sub_state[i] = 0; - } + context.sub_state = (unsigned int *)calloc( + program.frag_count * program.sub_type_count, sizeof(unsigned int)); if (params.demo) { randomize_context_state(); @@ -76,11 +72,30 @@ static void init_context(Parameters params) { for (i = 0; i < program.frag_count; i++) { context.seeds[i] = rand_uint(1000); } + + context.input_widths = + (unsigned int *)calloc(program.in_count, sizeof(unsigned int)); + context.input_heights = + (unsigned int *)calloc(program.in_count, sizeof(unsigned int)); + context.input_formats = + (unsigned int *)calloc(program.in_count, sizeof(unsigned int)); + + for (i = 0; i < program.in_count; i++) { + if (!inputs[i].error) { + context.input_widths[i] = inputs[i].width; + context.input_heights[i] = inputs[i].height; + context.input_formats[i] = inputs[i].pixelformat; + log_debug("%d %x", inputs[i].pixelformat, inputs[i].pixelformat); + } + } } static void free_context() { free(context.sub_state); free(context.seeds); + free(context.input_widths); + free(context.input_heights); + free(context.input_formats); } static void hot_reload() { diff --git a/src/shaders.c b/src/shaders.c index 8e14b5a..97c6f7c 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -435,6 +435,7 @@ static void use_program(ShaderProgram program, int i, bool output, unsigned int j, k; GLuint *subroutines; vec2 resolution, tex_resolution; + vec3 in_resolution; resolution[0] = (float)context.width; resolution[1] = (float)context.height; @@ -469,7 +470,14 @@ static void use_program(ShaderProgram program, int i, bool output, glUniform2fv(program.itexres_locations[i], 1, (const GLfloat *)&tex_resolution); - // TODO video resolution + 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, + (const GLfloat *)&in_resolution); + } // set seeds uniforms for (j = 0; j < program.frag_count; j++) { diff --git a/src/types.h b/src/types.h index 3662a6b..ad9c264 100644 --- a/src/types.h +++ b/src/types.h @@ -115,6 +115,7 @@ typedef struct Context { bool monitor; unsigned int *input_widths; unsigned int *input_heights; + unsigned int *input_formats; } Context; typedef struct Timer { diff --git a/src/video.c b/src/video.c index bff7a81..caca7cd 100644 --- a/src/video.c +++ b/src/video.c @@ -107,6 +107,7 @@ static bool get_available_sizes(VideoCapture *video_capture, unsigned int preferred_height) { struct v4l2_frmsizeenum fmt_enum; unsigned int index; + bool found = false; memset(&fmt_enum, 0, sizeof(fmt_enum)); @@ -114,6 +115,7 @@ static bool get_available_sizes(VideoCapture *video_capture, fmt_enum.index = index; fmt_enum.pixel_format = V4L2_PIX_FMT_YUYV; + found = false; video_capture->width = 0; video_capture->height = 0; @@ -124,12 +126,18 @@ static bool get_available_sizes(VideoCapture *video_capture, if (fmt_enum.discrete.height == preferred_height) { video_capture->height = preferred_height; + found = true; if (video_capture->width == 0 || video_capture->width < fmt_enum.discrete.width) { video_capture->width = fmt_enum.discrete.width; } - } else if (fmt_enum.discrete.height < preferred_height && - fmt_enum.discrete.height > video_capture->height) { + } else if (fmt_enum.discrete.height < preferred_height) { + if (!found || fmt_enum.discrete.height > video_capture->height) { + video_capture->height = fmt_enum.discrete.height; + video_capture->width = fmt_enum.discrete.width; + found = true; + } + } else if (video_capture->height == 0) { video_capture->height = fmt_enum.discrete.height; video_capture->width = fmt_enum.discrete.width; } @@ -141,6 +149,7 @@ static bool get_available_sizes(VideoCapture *video_capture, } if (video_capture->height == 0) { + log_warn("(%s) No format found"); video_capture->error = true; return false; } @@ -159,7 +168,7 @@ static bool set_format(VideoCapture *video_capture) { fmt.fmt.pix.width = video_capture->width; fmt.fmt.pix.height = video_capture->height; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix.field = V4L2_FIELD_ANY; if (ioctl(video_capture->fd, VIDIOC_S_FMT, &fmt) == -1) { fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;