Add clang-format as part of CI

This commit is contained in:
Benjamin Schaaf
2021-11-12 20:27:47 +11:00
parent e78bd99305
commit a92104e27c
23 changed files with 560 additions and 452 deletions

View File

@@ -7,12 +7,18 @@
build:debian: build:debian:
image: debian:bookworm-slim image: debian:bookworm-slim
before_script: before_script:
- apt update && apt -y install gcc meson ninja-build libgtk-4-dev libtiff-dev libzbar-dev - apt update && apt -y install gcc meson ninja-build clang-format-12 libgtk-4-dev libtiff-dev libzbar-dev
<<: *build_definition script:
- meson build
- ninja -C build
- ninja -C build test
- ninja -C build clang-format-check
build:alpine: build:alpine:
image: alpine:edge image: alpine:edge
before_script: before_script:
- apk add --no-cache build-base meson samurai gtk4.0-dev tiff-dev zbar-dev - apk add --no-cache build-base meson samurai gtk4.0-dev tiff-dev zbar-dev
<<: *build_definition script:
- meson build
- ninja -C build
- ninja -C build test

4
clang-format.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
cd "$MESON_SOURCE_ROOT"
clang-format-12 $@

View File

@@ -6,6 +6,8 @@ uniform sampler2D texture;
varying vec2 uv; varying vec2 uv;
void main() { void
main()
{
gl_FragColor = vec4(texture2D(texture, uv).rgb, 1); gl_FragColor = vec4(texture2D(texture, uv).rgb, 1);
} }

View File

@@ -9,7 +9,9 @@ uniform mat3 transform;
varying vec2 uv; varying vec2 uv;
void main() { void
main()
{
uv = tex_coord; uv = tex_coord;
gl_Position = vec4(transform * vec3(vert, 1), 1); gl_Position = vec4(transform * vec3(vert, 1), 1);

View File

@@ -10,15 +10,16 @@ varying vec2 top_right_uv;
varying vec2 bottom_left_uv; varying vec2 bottom_left_uv;
varying vec2 bottom_right_uv; varying vec2 bottom_right_uv;
void main() { void
main()
{
// Note the coordinates for texture samples need to be a varying, as the // Note the coordinates for texture samples need to be a varying, as the
// Mali-400 has this as a fast path allowing 32-bit floats. Otherwise // Mali-400 has this as a fast path allowing 32-bit floats. Otherwise
// they end up as 16-bit floats and that's not accurate enough. // they end up as 16-bit floats and that's not accurate enough.
vec4 samples = vec4( vec4 samples = vec4(texture2D(texture, top_left_uv).r,
texture2D(texture, top_left_uv).r, texture2D(texture, top_right_uv).r,
texture2D(texture, top_right_uv).r, texture2D(texture, bottom_left_uv).r,
texture2D(texture, bottom_left_uv).r, texture2D(texture, bottom_right_uv).r);
texture2D(texture, bottom_right_uv).r);
// Assume BGGR for now. Currently this just takes 3 of the four samples // Assume BGGR for now. Currently this just takes 3 of the four samples
// for each pixel, there's room here to do some better debayering. // for each pixel, there's room here to do some better debayering.
@@ -31,7 +32,8 @@ void main() {
//vec3 corrected = color_matrix * color2; //vec3 corrected = color_matrix * color2;
// Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/ // Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/
vec3 srgb_color = (vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected; vec3 srgb_color =
(vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected;
// Slow SRGB estimate // Slow SRGB estimate
// vec3 srgb_color = pow(color, vec3(1.0 / 2.2)); // vec3 srgb_color = pow(color, vec3(1.0 / 2.2));

View File

@@ -13,7 +13,9 @@ varying vec2 top_right_uv;
varying vec2 bottom_left_uv; varying vec2 bottom_left_uv;
varying vec2 bottom_right_uv; varying vec2 bottom_right_uv;
void main() { void
main()
{
top_left_uv = tex_coord - pixel_size / 2.0; top_left_uv = tex_coord - pixel_size / 2.0;
bottom_right_uv = tex_coord + pixel_size / 2.0; bottom_right_uv = tex_coord + pixel_size / 2.0;
top_right_uv = vec2(top_left_uv.x, bottom_right_uv.y); top_right_uv = vec2(top_left_uv.x, bottom_right_uv.y);

View File

@@ -4,6 +4,8 @@ precision mediump float;
uniform vec4 color; uniform vec4 color;
void main() { void
main()
{
gl_FragColor = color; gl_FragColor = color;
} }

View File

@@ -4,6 +4,8 @@ precision mediump float;
attribute vec2 vert; attribute vec2 vert;
void main() { void
main()
{
gl_Position = vec4(vert, 0, 1); gl_Position = vec4(vert, 0, 1);
} }

View File

@@ -77,3 +77,46 @@ executable('megapixels-camera-test',
include_directories: 'src/', include_directories: 'src/',
dependencies: [gtkdep], dependencies: [gtkdep],
install: true) install: true)
# Formatting
clang_format = find_program('clang-format-12', required: false)
if clang_format.found()
format_files = [
'data/blit.frag',
'data/blit.vert',
'data/debayer.frag',
'data/debayer.vert',
'data/solid.frag',
'data/solid.vert',
'src/camera.c',
'src/camera.h',
'src/camera_config.c',
'src/camera_config.h',
'src/device.c',
'src/device.h',
'src/flash.c',
'src/flash.h',
'src/gl_util.c',
'src/gl_util.h',
'src/gles2_debayer.c',
'src/gles2_debayer.h',
'src/io_pipeline.c',
'src/io_pipeline.h',
'src/main.c',
'src/main.h',
'src/matrix.c',
'src/matrix.h',
'src/pipeline.c',
'src/pipeline.h',
'src/process_pipeline.c',
'src/process_pipeline.h',
'src/zbar_pipeline.c',
'src/zbar_pipeline.h',
'tools/camera_test.c',
'tools/list_devices.c',
]
run_target('clang-format',
command: ['clang-format.sh', '-i'] + format_files)
run_target('clang-format-check',
command: ['clang-format.sh', '-n', '-Werror'] + format_files)
endif

View File

@@ -277,7 +277,8 @@ mp_camera_new(int video_fd, int subdev_fd)
camera->has_set_mode = false; camera->has_set_mode = false;
camera->num_buffers = 0; camera->num_buffers = 0;
camera->use_mplane = use_mplane; camera->use_mplane = use_mplane;
memset(camera->child_bg_pids, 0, sizeof(camera->child_bg_pids[0]) * MAX_BG_TASKS); memset(camera->child_bg_pids, 0,
sizeof(camera->child_bg_pids[0]) * MAX_BG_TASKS);
return camera; return camera;
} }
@@ -305,7 +306,8 @@ mp_camera_add_bg_task(MPCamera *camera, pid_t pid)
return; return;
} else { } else {
// error == -1, still running == 0 // error == -1, still running == 0
if (waitpid(camera->child_bg_pids[i], &status, WNOHANG) <= 0) if (waitpid(camera->child_bg_pids[i], &status,
WNOHANG) <= 0)
continue; // consider errored wait still running continue; // consider errored wait still running
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
@@ -741,7 +743,8 @@ mp_camera_capture_buffer(MPCamera *camera, MPBuffer *buffer)
return true; return true;
} }
bool mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index) bool
mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index)
{ {
struct v4l2_buffer buf = {}; struct v4l2_buffer buf = {};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

View File

@@ -37,8 +37,8 @@ find_config(char *conffile)
} }
// Check for a config file in XDG_CONFIG_HOME // Check for a config file in XDG_CONFIG_HOME
sprintf(conffile, "%s/megapixels/config/%s.ini", g_get_user_config_dir (), sprintf(conffile, "%s/megapixels/config/%s.ini",
buf); g_get_user_config_dir(), buf);
if (access(conffile, F_OK) != -1) { if (access(conffile, F_OK) != -1) {
printf("Found config file at %s\n", conffile); printf("Found config file at %s\n", conffile);
return true; return true;

View File

@@ -29,7 +29,7 @@ struct _MPFlash {
}; };
MPFlash * MPFlash *
mp_led_flash_from_path(const char * path) mp_led_flash_from_path(const char *path)
{ {
MPFlash *flash = malloc(sizeof(MPFlash)); MPFlash *flash = malloc(sizeof(MPFlash));
flash->type = FLASH_TYPE_LED; flash->type = FLASH_TYPE_LED;
@@ -52,28 +52,27 @@ static GtkWidget *flash_window = NULL;
static GDBusProxy *dbus_brightness_proxy = NULL; static GDBusProxy *dbus_brightness_proxy = NULL;
static int dbus_old_brightness = 0; static int dbus_old_brightness = 0;
static void dbus_brightness_init(GObject *src, GAsyncResult *res, gpointer *user_data) static void
dbus_brightness_init(GObject *src, GAsyncResult *res, gpointer *user_data)
{ {
GError *err = NULL; GError *err = NULL;
dbus_brightness_proxy = g_dbus_proxy_new_finish (res, &err); dbus_brightness_proxy = g_dbus_proxy_new_finish(res, &err);
if (!dbus_brightness_proxy || err) { if (!dbus_brightness_proxy || err) {
printf("Failed to connect to dbus brightness service %s\n", err->message); printf("Failed to connect to dbus brightness service %s\n",
err->message);
g_object_unref(err); g_object_unref(err);
return; return;
} }
} }
void mp_flash_gtk_init(GDBusConnection *conn) void
mp_flash_gtk_init(GDBusConnection *conn)
{ {
g_dbus_proxy_new(conn, g_dbus_proxy_new(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
G_DBUS_PROXY_FLAGS_NONE, "org.gnome.SettingsDaemon.Power",
NULL, "/org/gnome/SettingsDaemon/Power",
"org.gnome.SettingsDaemon.Power", "org.gnome.SettingsDaemon.Power.Screen", NULL,
"/org/gnome/SettingsDaemon/Power", (GAsyncReadyCallback)dbus_brightness_init, NULL);
"org.gnome.SettingsDaemon.Power.Screen",
NULL,
(GAsyncReadyCallback)dbus_brightness_init,
NULL);
// Create a full screen full white window as a flash // Create a full screen full white window as a flash
GtkWidget *window = gtk_window_new(); GtkWidget *window = gtk_window_new();
@@ -88,7 +87,8 @@ void mp_flash_gtk_init(GDBusConnection *conn)
flash_window = window; flash_window = window;
} }
void mp_flash_gtk_clean() void
mp_flash_gtk_clean()
{ {
gtk_window_destroy(GTK_WINDOW(flash_window)); gtk_window_destroy(GTK_WINDOW(flash_window));
g_object_unref(dbus_brightness_proxy); g_object_unref(dbus_brightness_proxy);
@@ -107,33 +107,28 @@ void
mp_flash_free(MPFlash *flash) mp_flash_free(MPFlash *flash)
{ {
switch (flash->type) { switch (flash->type) {
case FLASH_TYPE_LED: case FLASH_TYPE_LED:
close(flash->led.fd); close(flash->led.fd);
break; break;
case FLASH_TYPE_DISPLAY: case FLASH_TYPE_DISPLAY:
break; break;
} }
free(flash); free(flash);
} }
static void set_display_brightness(int brightness) static void
set_display_brightness(int brightness)
{ {
g_dbus_proxy_call(dbus_brightness_proxy, g_dbus_proxy_call(
"org.freedesktop.DBus.Properties.Set", dbus_brightness_proxy, "org.freedesktop.DBus.Properties.Set",
g_variant_new( g_variant_new("(ssv)", "org.gnome.SettingsDaemon.Power.Screen",
"(ssv)", "Brightness", g_variant_new("i", brightness)),
"org.gnome.SettingsDaemon.Power.Screen", G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
"Brightness",
g_variant_new("i", brightness)),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL,
NULL);
} }
static void brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) static void
brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *result = g_dbus_proxy_call_finish(proxy, res, &error); GVariant *result = g_dbus_proxy_call_finish(proxy, res, &error);
@@ -155,7 +150,8 @@ static void brightness_received(GDBusProxy *proxy, GAsyncResult *res, gpointer u
g_variant_unref(result); g_variant_unref(result);
} }
static bool show_display_flash(MPFlash *flash) static bool
show_display_flash(MPFlash *flash)
{ {
if (!flash_window) if (!flash_window)
return false; return false;
@@ -166,17 +162,12 @@ static bool show_display_flash(MPFlash *flash)
if (!dbus_brightness_proxy) if (!dbus_brightness_proxy)
return false; return false;
g_dbus_proxy_call(dbus_brightness_proxy, g_dbus_proxy_call(
"org.freedesktop.DBus.Properties.Get", dbus_brightness_proxy, "org.freedesktop.DBus.Properties.Get",
g_variant_new( g_variant_new("(ss)", "org.gnome.SettingsDaemon.Power.Screen",
"(ss)", "Brightness"),
"org.gnome.SettingsDaemon.Power.Screen", G_DBUS_CALL_FLAGS_NONE, -1, NULL,
"Brightness"), (GAsyncReadyCallback)brightness_received, NULL);
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback)brightness_received,
NULL);
set_display_brightness(100); set_display_brightness(100);
@@ -187,17 +178,18 @@ void
mp_flash_enable(MPFlash *flash) mp_flash_enable(MPFlash *flash)
{ {
switch (flash->type) { switch (flash->type) {
case FLASH_TYPE_LED: case FLASH_TYPE_LED:
lseek(flash->led.fd, 0, SEEK_SET); lseek(flash->led.fd, 0, SEEK_SET);
dprintf(flash->led.fd, "1\n"); dprintf(flash->led.fd, "1\n");
break; break;
case FLASH_TYPE_DISPLAY: case FLASH_TYPE_DISPLAY:
g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash); g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash);
break; break;
} }
} }
static bool hide_display_flash(MPFlash *flash) static bool
hide_display_flash(MPFlash *flash)
{ {
if (!flash_window) if (!flash_window)
return false; return false;
@@ -212,12 +204,11 @@ void
mp_flash_disable(MPFlash *flash) mp_flash_disable(MPFlash *flash)
{ {
switch (flash->type) { switch (flash->type) {
case FLASH_TYPE_LED: case FLASH_TYPE_LED:
// Flash gets reset automatically // Flash gets reset automatically
break; break;
case FLASH_TYPE_DISPLAY: case FLASH_TYPE_DISPLAY:
g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash); g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash);
break; break;
} }
} }

View File

@@ -8,32 +8,33 @@
#include <gmodule.h> #include <gmodule.h>
#include <gdk/gdk.h> #include <gdk/gdk.h>
void gl_util_check_error(const char *file, int line) void
gl_util_check_error(const char *file, int line)
{ {
GLenum error = glGetError(); GLenum error = glGetError();
const char *name; const char *name;
switch (error) { switch (error) {
case GL_NO_ERROR: case GL_NO_ERROR:
return; // no error return; // no error
case GL_INVALID_ENUM: case GL_INVALID_ENUM:
name = "GL_INVALID_ENUM"; name = "GL_INVALID_ENUM";
break; break;
case GL_INVALID_VALUE: case GL_INVALID_VALUE:
name = "GL_INVALID_VALUE"; name = "GL_INVALID_VALUE";
break; break;
case GL_INVALID_OPERATION: case GL_INVALID_OPERATION:
name = "GL_INVALID_OPERATION"; name = "GL_INVALID_OPERATION";
break; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: case GL_INVALID_FRAMEBUFFER_OPERATION:
name = "GL_INVALID_FRAMEBUFFER_OPERATION"; name = "GL_INVALID_FRAMEBUFFER_OPERATION";
break; break;
case GL_OUT_OF_MEMORY: case GL_OUT_OF_MEMORY:
name = "GL_OUT_OF_MEMORY"; name = "GL_OUT_OF_MEMORY";
break; break;
default: default:
name = "UNKNOWN ERROR!"; name = "UNKNOWN ERROR!";
break; break;
} }
printf("GL error at %s:%d - %s\n", file, line, name); printf("GL error at %s:%d - %s\n", file, line, name);
@@ -42,7 +43,8 @@ void gl_util_check_error(const char *file, int line)
} }
GLuint GLuint
gl_util_load_shader(const char *resource, GLenum type, const char **extra_sources, size_t num_extra) gl_util_load_shader(const char *resource, GLenum type, const char **extra_sources,
size_t num_extra)
{ {
GdkGLContext *context = gdk_gl_context_get_current(); GdkGLContext *context = gdk_gl_context_get_current();
assert(context); assert(context);
@@ -63,7 +65,9 @@ gl_util_load_shader(const char *resource, GLenum type, const char **extra_source
int major, minor; int major, minor;
gdk_gl_context_get_version(context, &major, &minor); gdk_gl_context_get_version(context, &major, &minor);
char context_info_buf[128]; char context_info_buf[128];
snprintf(context_info_buf, 128, "#define %s\n#define GL_%d\n#define GL_%d_%d\n", is_es ? "GL_ES" : "GL_NO_ES", major, major, minor); snprintf(context_info_buf, 128,
"#define %s\n#define GL_%d\n#define GL_%d_%d\n",
is_es ? "GL_ES" : "GL_NO_ES", major, major, minor);
gsize glib_size = 0; gsize glib_size = 0;
const GLchar *source = g_bytes_get_data(bytes, &glib_size); const GLchar *source = g_bytes_get_data(bytes, &glib_size);
@@ -151,18 +155,27 @@ gl_util_link_program(GLuint *shaders, size_t num_shaders)
static const GLfloat quad_data[] = { static const GLfloat quad_data[] = {
// Vertices // Vertices
-1, -1, -1,
1, -1, -1,
-1, 1, 1,
1, 1, -1,
-1,
1,
1,
1,
// Texcoords // Texcoords
0, 0, 0,
1, 0, 0,
0, 1, 1,
1, 1, 0,
0,
1,
1,
1,
}; };
GLuint gl_util_new_quad() GLuint
gl_util_new_quad()
{ {
GdkGLContext *context = gdk_gl_context_get_current(); GdkGLContext *context = gdk_gl_context_get_current();
assert(context); assert(context);
@@ -174,7 +187,8 @@ GLuint gl_util_new_quad()
glGenBuffers(1, &buffer); glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data,
GL_STATIC_DRAW);
check_gl(); check_gl();
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -184,18 +198,21 @@ GLuint gl_util_new_quad()
} }
} }
void gl_util_bind_quad(GLuint buffer) void
gl_util_bind_quad(GLuint buffer)
{ {
GdkGLContext *context = gdk_gl_context_get_current(); GdkGLContext *context = gdk_gl_context_get_current();
assert(context); assert(context);
if (gdk_gl_context_get_use_es(context)) { if (gdk_gl_context_get_use_es(context)) {
glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, quad_data); glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0,
quad_data);
check_gl(); check_gl();
glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
check_gl(); check_gl();
glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, 0, 0, quad_data + 8); glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, 0, 0,
quad_data + 8);
check_gl(); check_gl();
glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE);
check_gl(); check_gl();
@@ -203,17 +220,20 @@ void gl_util_bind_quad(GLuint buffer)
glBindBuffer(GL_ARRAY_BUFFER, buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer);
check_gl(); check_gl();
glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT,
GL_FALSE, 0, 0);
glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
check_gl(); check_gl();
glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, (void*) (8 * sizeof(float))); glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT,
GL_FALSE, 0, (void *)(8 * sizeof(float)));
glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE);
check_gl(); check_gl();
} }
} }
void gl_util_draw_quad(GLuint buffer) void
gl_util_draw_quad(GLuint buffer)
{ {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
check_gl(); check_gl();

View File

@@ -9,7 +9,8 @@
#define check_gl() gl_util_check_error(__FILE__, __LINE__) #define check_gl() gl_util_check_error(__FILE__, __LINE__)
void gl_util_check_error(const char *file, int line); void gl_util_check_error(const char *file, int line);
GLuint gl_util_load_shader(const char *resource, GLenum type, const char **extra_sources, size_t num_extra); GLuint gl_util_load_shader(const char *resource, GLenum type,
const char **extra_sources, size_t num_extra);
GLuint gl_util_link_program(GLuint *shaders, size_t num_shaders); GLuint gl_util_link_program(GLuint *shaders, size_t num_shaders);
GLuint gl_util_new_quad(); GLuint gl_util_new_quad();

View File

@@ -30,8 +30,10 @@ gles2_debayer_new(MPPixelFormat format)
check_gl(); check_gl();
GLuint shaders[] = { GLuint shaders[] = {
gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert", GL_VERTEX_SHADER, NULL, 0), gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert",
gl_util_load_shader("/org/postmarketos/Megapixels/debayer.frag", GL_FRAGMENT_SHADER, NULL, 0), GL_VERTEX_SHADER, NULL, 0),
gl_util_load_shader("/org/postmarketos/Megapixels/debayer.frag",
GL_FRAGMENT_SHADER, NULL, 0),
}; };
GLuint program = gl_util_link_program(shaders, 2); GLuint program = gl_util_link_program(shaders, 2);
@@ -46,7 +48,8 @@ gles2_debayer_new(MPPixelFormat format)
self->uniform_transform = glGetUniformLocation(self->program, "transform"); self->uniform_transform = glGetUniformLocation(self->program, "transform");
self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size"); self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size");
self->uniform_texture = glGetUniformLocation(self->program, "texture"); self->uniform_texture = glGetUniformLocation(self->program, "texture");
self->uniform_color_matrix = glGetUniformLocation(self->program, "color_matrix"); self->uniform_color_matrix =
glGetUniformLocation(self->program, "color_matrix");
check_gl(); check_gl();
self->quad = gl_util_new_quad(); self->quad = gl_util_new_quad();
@@ -74,12 +77,10 @@ gles2_debayer_use(GLES2Debayer *self)
} }
void void
gles2_debayer_configure(GLES2Debayer *self, gles2_debayer_configure(GLES2Debayer *self, const uint32_t dst_width,
const uint32_t dst_width, const uint32_t dst_height, const uint32_t dst_height, const uint32_t src_width,
const uint32_t src_width, const uint32_t src_height, const uint32_t src_height, const uint32_t rotation,
const uint32_t rotation, const bool mirrored, const float *colormatrix,
const bool mirrored,
const float *colormatrix,
const uint8_t blacklevel) const uint8_t blacklevel)
{ {
glViewport(0, 0, dst_width, dst_height); glViewport(0, 0, dst_width, dst_height);
@@ -92,9 +93,11 @@ gles2_debayer_configure(GLES2Debayer *self,
GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4]; GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4];
GLfloat scale_x = mirrored ? 1 : -1; GLfloat scale_x = mirrored ? 1 : -1;
GLfloat matrix[9] = { GLfloat matrix[9] = {
cos_rot * scale_x, sin_rot, 0, // clang-format off
cos_rot * scale_x, sin_rot, 0,
-sin_rot * scale_x, cos_rot, 0, -sin_rot * scale_x, cos_rot, 0,
0, 0, 1, 0, 0, 1,
// clang-format on
}; };
glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix); glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix);
check_gl(); check_gl();
@@ -110,14 +113,18 @@ gles2_debayer_configure(GLES2Debayer *self,
for (int j = 0; j < 3; ++j) for (int j = 0; j < 3; ++j)
transposed[i + j * 3] = colormatrix[j + i * 3]; transposed[i + j * 3] = colormatrix[j + i * 3];
glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, transposed); glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE,
transposed);
} else { } else {
static const GLfloat identity[9] = { static const GLfloat identity[9] = {
// clang-format off
1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 1,
// clang-format on
}; };
glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, identity); glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE,
identity);
} }
check_gl(); check_gl();
} }
@@ -127,7 +134,8 @@ gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer); glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer);
glBindTexture(GL_TEXTURE_2D, dst_id); glBindTexture(GL_TEXTURE_2D, dst_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
dst_id, 0);
check_gl(); check_gl();
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

View File

@@ -5,17 +5,15 @@
typedef struct _GLES2Debayer GLES2Debayer; typedef struct _GLES2Debayer GLES2Debayer;
GLES2Debayer* gles2_debayer_new(MPPixelFormat format); GLES2Debayer *gles2_debayer_new(MPPixelFormat format);
void gles2_debayer_free(GLES2Debayer *self); void gles2_debayer_free(GLES2Debayer *self);
void gles2_debayer_use(GLES2Debayer *self); void gles2_debayer_use(GLES2Debayer *self);
void gles2_debayer_configure(GLES2Debayer *self, void gles2_debayer_configure(GLES2Debayer *self, const uint32_t dst_width,
const uint32_t dst_width, const uint32_t dst_height, const uint32_t dst_height, const uint32_t src_width,
const uint32_t src_width, const uint32_t src_height, const uint32_t src_height, const uint32_t rotation,
const uint32_t rotation, const bool mirrored, const float *colormatrix,
const bool mirrored,
const float *colormatrix,
const uint8_t blacklevel); const uint8_t blacklevel);
void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id); void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id);

View File

@@ -147,7 +147,8 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
info->video_fd = open(dev_name, O_RDWR); info->video_fd = open(dev_name, O_RDWR);
if (info->video_fd == -1) { if (info->video_fd == -1) {
g_printerr("Could not open %s: %s\n", dev_name, strerror(errno)); g_printerr("Could not open %s: %s\n", dev_name,
strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -188,7 +189,8 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
info->fd = open(info->dev_fname, O_RDWR); info->fd = open(info->dev_fname, O_RDWR);
if (info->fd == -1) { if (info->fd == -1) {
g_printerr("Could not open %s: %s\n", info->dev_fname, strerror(errno)); g_printerr("Could not open %s: %s\n", info->dev_fname,
strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -204,8 +206,8 @@ setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config)
if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO, if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO,
NULL)) { NULL)) {
info->has_auto_focus_continuous = true; info->has_auto_focus_continuous = true;
mp_camera_control_set_bool_bg(info->camera, V4L2_CID_FOCUS_AUTO, mp_camera_control_set_bool_bg(info->camera,
true); V4L2_CID_FOCUS_AUTO, true);
} }
if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_FOCUS_START, if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_FOCUS_START,
NULL)) { NULL)) {
@@ -254,7 +256,7 @@ static void
clean_cameras() clean_cameras()
{ {
for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) {
struct camera_info* info = &cameras[i]; struct camera_info *info = &cameras[i];
if (info->camera) { if (info->camera) {
mp_camera_free(info->camera); mp_camera_free(info->camera);
info->camera = NULL; info->camera = NULL;
@@ -378,9 +380,11 @@ release_buffer(MPPipeline *pipeline, const uint32_t *buffer_index)
mp_camera_release_buffer(info->camera, *buffer_index); mp_camera_release_buffer(info->camera, *buffer_index);
} }
void mp_io_pipeline_release_buffer(uint32_t buffer_index) void
mp_io_pipeline_release_buffer(uint32_t buffer_index)
{ {
mp_pipeline_invoke(pipeline, (MPPipelineCallback) release_buffer, &buffer_index, sizeof(uint32_t)); mp_pipeline_invoke(pipeline, (MPPipelineCallback)release_buffer,
&buffer_index, sizeof(uint32_t));
} }
static pid_t focus_continuous_task = 0; static pid_t focus_continuous_task = 0;
@@ -389,16 +393,16 @@ static void
start_focus(struct camera_info *info) start_focus(struct camera_info *info)
{ {
// only run 1 manual focus at once // only run 1 manual focus at once
if (!mp_camera_check_task_complete(info->camera, start_focus_task) if (!mp_camera_check_task_complete(info->camera, start_focus_task) ||
|| !mp_camera_check_task_complete(info->camera, focus_continuous_task)) !mp_camera_check_task_complete(info->camera, focus_continuous_task))
return; return;
if (info->has_auto_focus_continuous) { if (info->has_auto_focus_continuous) {
focus_continuous_task = mp_camera_control_set_bool_bg(info->camera, focus_continuous_task = mp_camera_control_set_bool_bg(
V4L2_CID_FOCUS_AUTO, 1); info->camera, V4L2_CID_FOCUS_AUTO, 1);
} else if (info->has_auto_focus_start) { } else if (info->has_auto_focus_start) {
start_focus_task = mp_camera_control_set_bool_bg(info->camera, start_focus_task = mp_camera_control_set_bool_bg(
V4L2_CID_AUTO_FOCUS_START, 1); info->camera, V4L2_CID_AUTO_FOCUS_START, 1);
} }
} }
@@ -419,34 +423,34 @@ update_controls()
if (current_controls.gain_is_manual != desired_controls.gain_is_manual) { if (current_controls.gain_is_manual != desired_controls.gain_is_manual) {
mp_camera_control_set_bool_bg(info->camera, V4L2_CID_AUTOGAIN, mp_camera_control_set_bool_bg(info->camera, V4L2_CID_AUTOGAIN,
!desired_controls.gain_is_manual); !desired_controls.gain_is_manual);
} }
if (desired_controls.gain_is_manual && if (desired_controls.gain_is_manual &&
current_controls.gain != desired_controls.gain) { current_controls.gain != desired_controls.gain) {
mp_camera_control_set_int32_bg(info->camera, info->gain_ctrl, mp_camera_control_set_int32_bg(info->camera, info->gain_ctrl,
desired_controls.gain); desired_controls.gain);
} }
if (current_controls.exposure_is_manual != if (current_controls.exposure_is_manual !=
desired_controls.exposure_is_manual) { desired_controls.exposure_is_manual) {
mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE_AUTO, mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE_AUTO,
desired_controls.exposure_is_manual ? desired_controls.exposure_is_manual ?
V4L2_EXPOSURE_MANUAL : V4L2_EXPOSURE_MANUAL :
V4L2_EXPOSURE_AUTO); V4L2_EXPOSURE_AUTO);
} }
if (desired_controls.exposure_is_manual && if (desired_controls.exposure_is_manual &&
current_controls.exposure != desired_controls.exposure) { current_controls.exposure != desired_controls.exposure) {
mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE, mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE,
desired_controls.exposure); desired_controls.exposure);
} }
current_controls = desired_controls; current_controls = desired_controls;
} }
static void static void
on_frame(MPBuffer buffer, void * _data) on_frame(MPBuffer buffer, void *_data)
{ {
// Only update controls right after a frame was captured // Only update controls right after a frame was captured
update_controls(); update_controls();
@@ -489,14 +493,14 @@ on_frame(MPBuffer buffer, void * _data)
// Restore the auto exposure and gain if needed // Restore the auto exposure and gain if needed
if (!current_controls.exposure_is_manual) { if (!current_controls.exposure_is_manual) {
mp_camera_control_set_int32_bg(info->camera, mp_camera_control_set_int32_bg(
V4L2_CID_EXPOSURE_AUTO, info->camera, V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_AUTO); V4L2_EXPOSURE_AUTO);
} }
if (!current_controls.gain_is_manual) { if (!current_controls.gain_is_manual) {
mp_camera_control_set_bool_bg(info->camera, mp_camera_control_set_bool_bg(
V4L2_CID_AUTOGAIN, true); info->camera, V4L2_CID_AUTOGAIN, true);
} }
// Go back to preview mode // Go back to preview mode
@@ -594,11 +598,10 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
desired_controls.exposure_is_manual = state->exposure_is_manual; desired_controls.exposure_is_manual = state->exposure_is_manual;
desired_controls.exposure = state->exposure; desired_controls.exposure = state->exposure;
has_changed = has_changed = has_changed ||
has_changed memcmp(&previous_desired, &desired_controls,
|| memcmp(&previous_desired, &desired_controls, sizeof(struct control_state)) != 0 ||
sizeof(struct control_state)) != 0 flash_enabled != state->flash_enabled;
|| flash_enabled != state->flash_enabled;
flash_enabled = state->flash_enabled; flash_enabled = state->flash_enabled;
} }

View File

@@ -24,7 +24,7 @@
#include <wordexp.h> #include <wordexp.h>
#include <zbar.h> #include <zbar.h>
#define RENDERDOC // #define RENDERDOC
#ifdef RENDERDOC #ifdef RENDERDOC
#include <dlfcn.h> #include <dlfcn.h>
@@ -158,7 +158,8 @@ mp_main_update_state(const struct mp_main_state *state)
(GSourceFunc)update_state, state_copy, free); (GSourceFunc)update_state, state_copy, free);
} }
static bool set_zbar_result(MPZBarScanResult *result) static bool
set_zbar_result(MPZBarScanResult *result)
{ {
if (zbar_result) { if (zbar_result) {
for (uint8_t i = 0; i < zbar_result->size; ++i) { for (uint8_t i = 0; i < zbar_result->size; ++i) {
@@ -174,7 +175,8 @@ static bool set_zbar_result(MPZBarScanResult *result)
return false; return false;
} }
void mp_main_set_zbar_result(MPZBarScanResult *result) void
mp_main_set_zbar_result(MPZBarScanResult *result)
{ {
g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)set_zbar_result, result, NULL); (GSourceFunc)set_zbar_result, result, NULL);
@@ -223,7 +225,8 @@ capture_completed(struct capture_completed_args *args)
void void
mp_main_capture_completed(GdkTexture *thumb, const char *fname) mp_main_capture_completed(GdkTexture *thumb, const char *fname)
{ {
struct capture_completed_args *args = malloc(sizeof(struct capture_completed_args)); struct capture_completed_args *args =
malloc(sizeof(struct capture_completed_args));
args->thumb = thumb; args->thumb = thumb;
args->fname = g_strdup(fname); args->fname = g_strdup(fname);
g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
@@ -255,8 +258,10 @@ preview_realize(GtkGLArea *area)
} }
GLuint blit_shaders[] = { GLuint blit_shaders[] = {
gl_util_load_shader("/org/postmarketos/Megapixels/blit.vert", GL_VERTEX_SHADER, NULL, 0), gl_util_load_shader("/org/postmarketos/Megapixels/blit.vert",
gl_util_load_shader("/org/postmarketos/Megapixels/blit.frag", GL_FRAGMENT_SHADER, NULL, 0), GL_VERTEX_SHADER, NULL, 0),
gl_util_load_shader("/org/postmarketos/Megapixels/blit.frag",
GL_FRAGMENT_SHADER, NULL, 0),
}; };
blit_program = gl_util_link_program(blit_shaders, 2); blit_program = gl_util_link_program(blit_shaders, 2);
@@ -268,8 +273,10 @@ preview_realize(GtkGLArea *area)
blit_uniform_texture = glGetUniformLocation(blit_program, "texture"); blit_uniform_texture = glGetUniformLocation(blit_program, "texture");
GLuint solid_shaders[] = { GLuint solid_shaders[] = {
gl_util_load_shader("/org/postmarketos/Megapixels/solid.vert", GL_VERTEX_SHADER, NULL, 0), gl_util_load_shader("/org/postmarketos/Megapixels/solid.vert",
gl_util_load_shader("/org/postmarketos/Megapixels/solid.frag", GL_FRAGMENT_SHADER, NULL, 0), GL_VERTEX_SHADER, NULL, 0),
gl_util_load_shader("/org/postmarketos/Megapixels/solid.frag",
GL_FRAGMENT_SHADER, NULL, 0),
}; };
solid_program = gl_util_link_program(solid_shaders, 2); solid_program = gl_util_link_program(solid_shaders, 2);
@@ -294,11 +301,14 @@ position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
} }
int scale_factor = gtk_widget_get_scale_factor(preview); int scale_factor = gtk_widget_get_scale_factor(preview);
int top_height = gtk_widget_get_allocated_height(preview_top_box) * scale_factor; int top_height =
int bottom_height = gtk_widget_get_allocated_height(preview_bottom_box) * scale_factor; gtk_widget_get_allocated_height(preview_top_box) * scale_factor;
int bottom_height =
gtk_widget_get_allocated_height(preview_bottom_box) * scale_factor;
int inner_height = preview_height - top_height - bottom_height; int inner_height = preview_height - top_height - bottom_height;
double scale = MIN(preview_width / (float) buffer_width, preview_height / (float) buffer_height); double scale = MIN(preview_width / (float)buffer_width,
preview_height / (float)buffer_height);
*size_x = scale * buffer_width; *size_x = scale * buffer_width;
*size_y = scale * buffer_height; *size_y = scale * buffer_height;
@@ -310,7 +320,6 @@ position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y)
} else { } else {
*offset_y = top_height + (inner_height - *size_y) / 2.0; *offset_y = top_height + (inner_height - *size_y) / 2.0;
} }
} }
static gboolean static gboolean
@@ -325,7 +334,9 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
} }
#ifdef RENDERDOC #ifdef RENDERDOC
if (rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL); if (rdoc_api) {
rdoc_api->StartFrameCapture(NULL, NULL);
}
#endif #endif
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, 1);
@@ -333,10 +344,7 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
float offset_x, offset_y, size_x, size_y; float offset_x, offset_y, size_x, size_y;
position_preview(&offset_x, &offset_y, &size_x, &size_y); position_preview(&offset_x, &offset_y, &size_x, &size_y);
glViewport(offset_x, glViewport(offset_x, preview_height - size_y - offset_y, size_x, size_y);
preview_height - size_y - offset_y,
size_x,
size_y);
if (current_preview_buffer) { if (current_preview_buffer) {
glUseProgram(blit_program); glUseProgram(blit_program);
@@ -347,15 +355,19 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
GLfloat sin_rot = rotation_list[rotation_index]; GLfloat sin_rot = rotation_list[rotation_index];
GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4]; GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4];
GLfloat matrix[9] = { GLfloat matrix[9] = {
cos_rot, sin_rot, 0, // clang-format off
cos_rot, sin_rot, 0,
-sin_rot, cos_rot, 0, -sin_rot, cos_rot, 0,
0, 0, 1, 0, 0, 1,
// clang-format on
}; };
glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix); glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix);
check_gl(); check_gl();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mp_process_pipeline_buffer_get_texture_id(current_preview_buffer)); glBindTexture(GL_TEXTURE_2D,
mp_process_pipeline_buffer_get_texture_id(
current_preview_buffer));
glUniform1i(blit_uniform_texture, 0); glUniform1i(blit_uniform_texture, 0);
check_gl(); check_gl();
@@ -388,20 +400,27 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
}; };
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
vertices[i * 2] = 2 * vertices[i * 2] / preview_buffer_width - 1.0; vertices[i * 2] =
vertices[i * 2 + 1] = 1.0 - 2 * vertices[i * 2 + 1] / preview_buffer_height; 2 * vertices[i * 2] / preview_buffer_width -
1.0;
vertices[i * 2 + 1] =
1.0 - 2 * vertices[i * 2 + 1] /
preview_buffer_height;
} }
if (gtk_gl_area_get_use_es(area)) { if (gtk_gl_area_get_use_es(area)) {
glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, vertices); glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2,
GL_FLOAT, 0, 0, vertices);
check_gl(); check_gl();
glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
check_gl(); check_gl();
} else { } else {
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STREAM_DRAW);
check_gl(); check_gl();
glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2,
GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE);
check_gl(); check_gl();
} }
@@ -417,7 +436,9 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data)
glFlush(); glFlush();
#ifdef RENDERDOC #ifdef RENDERDOC
if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); if (rdoc_api) {
rdoc_api->EndFrameCapture(NULL, NULL);
}
#endif #endif
return FALSE; return FALSE;
@@ -446,7 +467,8 @@ run_open_last_action(GSimpleAction *action, GVariant *param, gpointer user_data)
} }
sprintf(uri, "file://%s", last_path); sprintf(uri, "file://%s", last_path);
if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) { if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) {
g_printerr("Could not launch image viewer for '%s': %s\n", uri, error->message); g_printerr("Could not launch image viewer for '%s': %s\n", uri,
error->message);
} }
} }
@@ -472,14 +494,13 @@ run_capture_action(GSimpleAction *action, GVariant *param, gpointer user_data)
void void
run_about_action(GSimpleAction *action, GVariant *param, GApplication *app) run_about_action(GSimpleAction *action, GVariant *param, GApplication *app)
{ {
gtk_show_about_dialog(NULL, "program-name", "Megapixels", gtk_show_about_dialog(NULL, "program-name", "Megapixels", "title",
"title", "Megapixels", "Megapixels", "logo-icon-name",
"logo-icon-name", "org.postmarketos.Megapixels", "org.postmarketos.Megapixels", "comments",
"comments", "The postmarketOS camera application", "The postmarketOS camera application", "website",
"website", "https://sr.ht/~martijnbraam/megapixels", "https://sr.ht/~martijnbraam/megapixels", "version",
"version", VERSION, VERSION, "license-type", GTK_LICENSE_GPL_3_0_ONLY,
"license-type", GTK_LICENSE_GPL_3_0_ONLY, NULL);
NULL);
} }
void void
@@ -512,23 +533,19 @@ on_zbar_dialog_response(GtkDialog *dialog, int response, char *data)
{ {
GError *error = NULL; GError *error = NULL;
switch (response) { switch (response) {
case GTK_RESPONSE_YES: case GTK_RESPONSE_YES:
if (!g_app_info_launch_default_for_uri(data, if (!g_app_info_launch_default_for_uri(data, NULL, &error)) {
NULL, &error)) { g_printerr("Could not launch application: %s\n",
g_printerr("Could not launch application: %s\n", error->message);
error->message);
}
case GTK_RESPONSE_ACCEPT:
{
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(dialog));
gdk_clipboard_set_text(
gdk_display_get_clipboard(display),
data);
} }
case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_ACCEPT: {
break; GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(dialog));
default: gdk_clipboard_set_text(gdk_display_get_clipboard(display), data);
g_printerr("Wrong dialog response: %d\n", response); }
case GTK_RESPONSE_CANCEL:
break;
default:
g_printerr("Wrong dialog response: %d\n", response);
} }
g_free(data); g_free(data);
@@ -540,48 +557,31 @@ on_zbar_code_tapped(GtkWidget *widget, const MPZBarCode *code)
{ {
GtkWidget *dialog; GtkWidget *dialog;
GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
bool data_is_url = g_uri_is_valid( bool data_is_url =
code->data, G_URI_FLAGS_PARSE_RELAXED, NULL); g_uri_is_valid(code->data, G_URI_FLAGS_PARSE_RELAXED, NULL);
char* data = strdup(code->data); char *data = strdup(code->data);
if (data_is_url) { if (data_is_url) {
dialog = gtk_message_dialog_new( dialog = gtk_message_dialog_new(
GTK_WINDOW(gtk_widget_get_root(widget)), GTK_WINDOW(gtk_widget_get_root(widget)), flags,
flags, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
GTK_MESSAGE_QUESTION, "Found a URL '%s' encoded in a %s.", code->data, code->type);
GTK_BUTTONS_NONE, gtk_dialog_add_buttons(GTK_DIALOG(dialog), "_Open URL",
"Found a URL '%s' encoded in a %s.", GTK_RESPONSE_YES, NULL);
code->data,
code->type);
gtk_dialog_add_buttons(
GTK_DIALOG(dialog),
"_Open URL",
GTK_RESPONSE_YES,
NULL);
} else { } else {
dialog = gtk_message_dialog_new( dialog = gtk_message_dialog_new(
GTK_WINDOW(gtk_widget_get_root(widget)), GTK_WINDOW(gtk_widget_get_root(widget)), flags,
flags, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
GTK_MESSAGE_QUESTION, "Found data encoded in a %s.", code->type);
GTK_BUTTONS_NONE, gtk_message_dialog_format_secondary_markup(
"Found data encoded in a %s.", GTK_MESSAGE_DIALOG(dialog), "<small>%s</small>", code->data);
code->type);
gtk_message_dialog_format_secondary_markup (
GTK_MESSAGE_DIALOG(dialog),
"<small>%s</small>",
code->data
);
} }
gtk_dialog_add_buttons( gtk_dialog_add_buttons(GTK_DIALOG(dialog), "_Copy", GTK_RESPONSE_ACCEPT,
GTK_DIALOG(dialog), "_Cancel", GTK_RESPONSE_CANCEL, NULL);
"_Copy",
GTK_RESPONSE_ACCEPT,
"_Cancel",
GTK_RESPONSE_CANCEL,
NULL);
g_signal_connect(dialog, "response", G_CALLBACK(on_zbar_dialog_response), data); g_signal_connect(dialog, "response", G_CALLBACK(on_zbar_dialog_response),
data);
gtk_widget_show(GTK_WIDGET(dialog)); gtk_widget_show(GTK_WIDGET(dialog));
} }
@@ -589,7 +589,8 @@ on_zbar_code_tapped(GtkWidget *widget, const MPZBarCode *code)
static void static void
preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y) preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
{ {
GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); GtkWidget *widget =
gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
int scale_factor = gtk_widget_get_scale_factor(widget); int scale_factor = gtk_widget_get_scale_factor(widget);
// Tapped zbar result // Tapped zbar result
@@ -598,13 +599,16 @@ preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y)
float offset_x, offset_y, size_x, size_y; float offset_x, offset_y, size_x, size_y;
position_preview(&offset_x, &offset_y, &size_x, &size_y); position_preview(&offset_x, &offset_y, &size_x, &size_y);
int zbar_x = (x - offset_x) * scale_factor / size_x * preview_buffer_width; int zbar_x = (x - offset_x) * scale_factor / size_x *
int zbar_y = (y - offset_y) * scale_factor / size_y * preview_buffer_height; preview_buffer_width;
int zbar_y = (y - offset_y) * scale_factor / size_y *
preview_buffer_height;
for (uint8_t i = 0; i < zbar_result->size; ++i) { for (uint8_t i = 0; i < zbar_result->size; ++i) {
MPZBarCode *code = &zbar_result->codes[i]; MPZBarCode *code = &zbar_result->codes[i];
if (check_point_inside_bounds(zbar_x, zbar_y, code->bounds_x, code->bounds_y)) { if (check_point_inside_bounds(zbar_x, zbar_y, code->bounds_x,
code->bounds_y)) {
on_zbar_code_tapped(widget, code); on_zbar_code_tapped(widget, code);
return; return;
} }
@@ -647,8 +651,7 @@ run_close_settings_action(GSimpleAction *action, GVariant *param, gpointer user_
// Update settings // Update settings
bool save_dng = g_settings_get_boolean(settings, "save-raw"); bool save_dng = g_settings_get_boolean(settings, "save-raw");
if (save_dng != setting_save_dng) if (save_dng != setting_save_dng) {
{
setting_save_dng = save_dng; setting_save_dng = save_dng;
update_io_pipeline(); update_io_pipeline();
} }
@@ -677,23 +680,25 @@ on_auto_controls_toggled(GtkToggleButton *button, void (*set_auto_fn)(bool))
static void static void
update_scale(GtkToggleButton *button, GtkScale *scale) update_scale(GtkToggleButton *button, GtkScale *scale)
{ {
gtk_widget_set_sensitive(GTK_WIDGET(scale), !gtk_toggle_button_get_active(button)); gtk_widget_set_sensitive(GTK_WIDGET(scale),
!gtk_toggle_button_get_active(button));
} }
static void static void
open_controls(GtkWidget *parent, const char *title_name, open_controls(GtkWidget *parent, const char *title_name, double min_value,
double min_value, double max_value, double current, double max_value, double current, bool auto_enabled,
bool auto_enabled, void (*set_fn)(double), void (*set_auto_fn)(bool))
void (*set_fn)(double),
void (*set_auto_fn)(bool))
{ {
GtkBuilder *builder = gtk_builder_new_from_resource( GtkBuilder *builder = gtk_builder_new_from_resource(
"/org/postmarketos/Megapixels/controls-popover.ui"); "/org/postmarketos/Megapixels/controls-popover.ui");
GtkPopover *popover = GTK_POPOVER(gtk_builder_get_object(builder, "controls")); GtkPopover *popover =
GTK_POPOVER(gtk_builder_get_object(builder, "controls"));
GtkScale *scale = GTK_SCALE(gtk_builder_get_object(builder, "scale")); GtkScale *scale = GTK_SCALE(gtk_builder_get_object(builder, "scale"));
GtkLabel *title = GTK_LABEL(gtk_builder_get_object(builder, "title")); GtkLabel *title = GTK_LABEL(gtk_builder_get_object(builder, "title"));
GtkLabel *value_label = GTK_LABEL(gtk_builder_get_object(builder, "value-label")); GtkLabel *value_label =
GtkToggleButton *auto_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "auto-button")); GTK_LABEL(gtk_builder_get_object(builder, "value-label"));
GtkToggleButton *auto_button =
GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "auto-button"));
gtk_label_set_label(title, title_name); gtk_label_set_label(title, title_name);
@@ -706,9 +711,12 @@ open_controls(GtkWidget *parent, const char *title_name,
gtk_toggle_button_set_active(auto_button, auto_enabled); gtk_toggle_button_set_active(auto_button, auto_enabled);
update_scale(auto_button, scale); update_scale(auto_button, scale);
g_signal_connect(adjustment, "value-changed", G_CALLBACK(on_controls_scale_changed), set_fn); g_signal_connect(adjustment, "value-changed",
g_signal_connect(adjustment, "value-changed", G_CALLBACK(update_value), value_label); G_CALLBACK(on_controls_scale_changed), set_fn);
g_signal_connect(auto_button, "toggled", G_CALLBACK(on_auto_controls_toggled), set_auto_fn); g_signal_connect(adjustment, "value-changed", G_CALLBACK(update_value),
value_label);
g_signal_connect(auto_button, "toggled",
G_CALLBACK(on_auto_controls_toggled), set_auto_fn);
g_signal_connect(auto_button, "toggled", G_CALLBACK(update_scale), scale); g_signal_connect(auto_button, "toggled", G_CALLBACK(update_scale), scale);
gtk_widget_set_parent(GTK_WIDGET(popover), parent); gtk_widget_set_parent(GTK_WIDGET(popover), parent);
@@ -737,14 +745,14 @@ set_gain_auto(bool is_auto)
static void static void
open_iso_controls(GtkWidget *button, gpointer user_data) open_iso_controls(GtkWidget *button, gpointer user_data)
{ {
open_controls(button, "ISO", 0, gain_max, gain, !gain_is_manual, set_gain, set_gain_auto); open_controls(button, "ISO", 0, gain_max, gain, !gain_is_manual, set_gain,
set_gain_auto);
} }
static void static void
set_shutter(double value) set_shutter(double value)
{ {
int new_exposure = int new_exposure = (int)(value / 360.0 * camera->capture_mode.height);
(int)(value / 360.0 * camera->capture_mode.height);
if (new_exposure != exposure) { if (new_exposure != exposure) {
exposure = new_exposure; exposure = new_exposure;
update_io_pipeline(); update_io_pipeline();
@@ -763,7 +771,8 @@ set_shutter_auto(bool is_auto)
static void static void
open_shutter_controls(GtkWidget *button, gpointer user_data) open_shutter_controls(GtkWidget *button, gpointer user_data)
{ {
open_controls(button, "Shutter", 1.0, 360.0, exposure, !exposure_is_manual, set_shutter, set_shutter_auto); open_controls(button, "Shutter", 1.0, 360.0, exposure, !exposure_is_manual,
set_shutter, set_shutter_auto);
} }
static void static void
@@ -772,7 +781,8 @@ flash_button_clicked(GtkWidget *button, gpointer user_data)
flash_enabled = !flash_enabled; flash_enabled = !flash_enabled;
update_io_pipeline(); update_io_pipeline();
const char * icon_name = flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic"; const char *icon_name =
flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic";
gtk_button_set_icon_name(GTK_BUTTON(button), icon_name); gtk_button_set_icon_name(GTK_BUTTON(button), icon_name);
} }
@@ -795,15 +805,18 @@ create_simple_action(GtkApplication *app, const char *name, GCallback callback)
return action; return action;
} }
static void update_ui_rotation() static void
update_ui_rotation()
{ {
if (device_rotation == 0 || device_rotation == 180) { if (device_rotation == 0 || device_rotation == 180) {
// Portrait // Portrait
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL); gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL);
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), GTK_ORIENTATION_VERTICAL); gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box),
GTK_ORIENTATION_VERTICAL);
gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_FILL); gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_FILL);
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), GTK_ORIENTATION_HORIZONTAL); gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
GTK_ORIENTATION_HORIZONTAL);
if (device_rotation == 0) { if (device_rotation == 0) {
gtk_widget_set_valign(preview_top_box, GTK_ALIGN_START); gtk_widget_set_valign(preview_top_box, GTK_ALIGN_START);
@@ -815,10 +828,12 @@ static void update_ui_rotation()
} else { } else {
// Landscape // Landscape
gtk_widget_set_valign(preview_top_box, GTK_ALIGN_FILL); gtk_widget_set_valign(preview_top_box, GTK_ALIGN_FILL);
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), GTK_ORIENTATION_HORIZONTAL); gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box),
GTK_ORIENTATION_HORIZONTAL);
gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_FILL); gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_FILL);
gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), GTK_ORIENTATION_VERTICAL); gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box),
GTK_ORIENTATION_VERTICAL);
if (device_rotation == 90) { if (device_rotation == 90) {
gtk_widget_set_halign(preview_top_box, GTK_ALIGN_END); gtk_widget_set_halign(preview_top_box, GTK_ALIGN_END);
@@ -830,7 +845,8 @@ static void update_ui_rotation()
} }
} }
static void display_config_received(GDBusConnection *conn, GAsyncResult *res, gpointer user_data) static void
display_config_received(GDBusConnection *conn, GAsyncResult *res, gpointer user_data)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *result = g_dbus_connection_call_finish(conn, res, &error); GVariant *result = g_dbus_connection_call_finish(conn, res, &error);
@@ -862,30 +878,20 @@ static void display_config_received(GDBusConnection *conn, GAsyncResult *res, gp
g_variant_unref(result); g_variant_unref(result);
} }
static void update_screen_rotation(GDBusConnection *conn) static void
update_screen_rotation(GDBusConnection *conn)
{ {
g_dbus_connection_call(conn, g_dbus_connection_call(conn, "org.gnome.Mutter.DisplayConfig",
"org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig",
"/org/gnome/Mutter/DisplayConfig", "org.gnome.Mutter.DisplayConfig", "GetResources",
"org.gnome.Mutter.DisplayConfig", NULL, NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL,
"GetResources", (GAsyncReadyCallback)display_config_received, NULL);
NULL,
NULL,
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
(GAsyncReadyCallback)display_config_received,
NULL);
} }
static void on_screen_rotate( static void
GDBusConnection *conn, on_screen_rotate(GDBusConnection *conn, const gchar *sender_name,
const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
const gchar *object_path, const gchar *signal_name, GVariant *parameters, gpointer user_data)
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{ {
update_screen_rotation(conn); update_screen_rotation(conn);
} }
@@ -911,18 +917,25 @@ activate(GtkApplication *app, gpointer data)
"/org/postmarketos/Megapixels/camera.ui"); "/org/postmarketos/Megapixels/camera.ui");
GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
GtkWidget *iso_button = GTK_WIDGET(gtk_builder_get_object(builder, "iso-controls-button")); GtkWidget *iso_button =
GtkWidget *shutter_button = GTK_WIDGET(gtk_builder_get_object(builder, "shutter-controls-button")); GTK_WIDGET(gtk_builder_get_object(builder, "iso-controls-button"));
flash_button = GTK_WIDGET(gtk_builder_get_object(builder, "flash-controls-button")); GtkWidget *shutter_button = GTK_WIDGET(
GtkWidget *setting_dng_button = GTK_WIDGET(gtk_builder_get_object(builder, "setting-raw")); gtk_builder_get_object(builder, "shutter-controls-button"));
flash_button =
GTK_WIDGET(gtk_builder_get_object(builder, "flash-controls-button"));
GtkWidget *setting_dng_button =
GTK_WIDGET(gtk_builder_get_object(builder, "setting-raw"));
preview = GTK_WIDGET(gtk_builder_get_object(builder, "preview")); preview = GTK_WIDGET(gtk_builder_get_object(builder, "preview"));
main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_stack")); main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_stack"));
open_last_stack = GTK_WIDGET(gtk_builder_get_object(builder, "open_last_stack")); open_last_stack =
GTK_WIDGET(gtk_builder_get_object(builder, "open_last_stack"));
thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last")); thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last"));
process_spinner = GTK_WIDGET(gtk_builder_get_object(builder, "process_spinner")); process_spinner =
GTK_WIDGET(gtk_builder_get_object(builder, "process_spinner"));
scanned_codes = GTK_WIDGET(gtk_builder_get_object(builder, "scanned-codes")); scanned_codes = GTK_WIDGET(gtk_builder_get_object(builder, "scanned-codes"));
preview_top_box = GTK_WIDGET(gtk_builder_get_object(builder, "top-box")); preview_top_box = GTK_WIDGET(gtk_builder_get_object(builder, "top-box"));
preview_bottom_box = GTK_WIDGET(gtk_builder_get_object(builder, "bottom-box")); preview_bottom_box =
GTK_WIDGET(gtk_builder_get_object(builder, "bottom-box"));
g_signal_connect(window, "realize", G_CALLBACK(on_realize), NULL); g_signal_connect(window, "realize", G_CALLBACK(on_realize), NULL);
@@ -934,14 +947,19 @@ activate(GtkApplication *app, gpointer data)
gtk_widget_add_controller(preview, GTK_EVENT_CONTROLLER(click)); gtk_widget_add_controller(preview, GTK_EVENT_CONTROLLER(click));
g_signal_connect(iso_button, "clicked", G_CALLBACK(open_iso_controls), NULL); g_signal_connect(iso_button, "clicked", G_CALLBACK(open_iso_controls), NULL);
g_signal_connect(shutter_button, "clicked", G_CALLBACK(open_shutter_controls), NULL); g_signal_connect(shutter_button, "clicked",
g_signal_connect(flash_button, "clicked", G_CALLBACK(flash_button_clicked), NULL); G_CALLBACK(open_shutter_controls), NULL);
g_signal_connect(flash_button, "clicked", G_CALLBACK(flash_button_clicked),
NULL);
// Setup actions // Setup actions
create_simple_action(app, "capture", G_CALLBACK(run_capture_action)); create_simple_action(app, "capture", G_CALLBACK(run_capture_action));
create_simple_action(app, "switch-camera", G_CALLBACK(run_camera_switch_action)); create_simple_action(app, "switch-camera",
create_simple_action(app, "open-settings", G_CALLBACK(run_open_settings_action)); G_CALLBACK(run_camera_switch_action));
create_simple_action(app, "close-settings", G_CALLBACK(run_close_settings_action)); create_simple_action(app, "open-settings",
G_CALLBACK(run_open_settings_action));
create_simple_action(app, "close-settings",
G_CALLBACK(run_close_settings_action));
create_simple_action(app, "open-last", G_CALLBACK(run_open_last_action)); create_simple_action(app, "open-last", G_CALLBACK(run_open_last_action));
create_simple_action(app, "open-photos", G_CALLBACK(run_open_photos_action)); create_simple_action(app, "open-photos", G_CALLBACK(run_open_photos_action));
create_simple_action(app, "about", G_CALLBACK(run_about_action)); create_simple_action(app, "about", G_CALLBACK(run_about_action));
@@ -956,23 +974,18 @@ activate(GtkApplication *app, gpointer data)
// Setup settings // Setup settings
settings = g_settings_new("org.postmarketos.Megapixels"); settings = g_settings_new("org.postmarketos.Megapixels");
g_settings_bind (settings, "save-raw", setting_dng_button, "active", G_SETTINGS_BIND_DEFAULT); g_settings_bind(settings, "save-raw", setting_dng_button, "active",
G_SETTINGS_BIND_DEFAULT);
setting_save_dng = g_settings_get_boolean(settings, "save-raw"); setting_save_dng = g_settings_get_boolean(settings, "save-raw");
// Listen for phosh rotation // Listen for phosh rotation
GDBusConnection *conn = g_application_get_dbus_connection(G_APPLICATION(app)); GDBusConnection *conn =
g_application_get_dbus_connection(G_APPLICATION(app));
g_dbus_connection_signal_subscribe( g_dbus_connection_signal_subscribe(
conn, conn, NULL, "org.gnome.Mutter.DisplayConfig", "MonitorsChanged",
NULL, "/org/gnome/Mutter/DisplayConfig", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
"org.gnome.Mutter.DisplayConfig", &on_screen_rotate, NULL, NULL);
"MonitorsChanged",
"/org/gnome/Mutter/DisplayConfig",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
&on_screen_rotate,
NULL,
NULL);
update_screen_rotation(conn); update_screen_rotation(conn);
// Initialize display flash // Initialize display flash
@@ -1000,14 +1013,13 @@ main(int argc, char *argv[])
#ifdef RENDERDOC #ifdef RENDERDOC
{ {
void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD); void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD);
if (mod) if (mod) {
{ pRENDERDOC_GetAPI RENDERDOC_GetAPI =
pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI"); (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI");
int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void **)&rdoc_api); int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2,
assert(ret == 1); (void **)&rdoc_api);
} assert(ret == 1);
else } else {
{
printf("Renderdoc not found\n"); printf("Renderdoc not found\n");
} }
} }

View File

@@ -79,7 +79,8 @@ mp_pipeline_sync(MPPipeline *pipeline)
g_mutex_init(&mutex); g_mutex_init(&mutex);
g_mutex_lock(&mutex); g_mutex_lock(&mutex);
g_main_context_invoke_full(pipeline->main_context, G_PRIORITY_LOW, (GSourceFunc)unlock_mutex, &mutex, NULL); g_main_context_invoke_full(pipeline->main_context, G_PRIORITY_LOW,
(GSourceFunc)unlock_mutex, &mutex, NULL);
g_mutex_lock(&mutex); g_mutex_lock(&mutex);
g_mutex_unlock(&mutex); g_mutex_unlock(&mutex);

View File

@@ -123,7 +123,6 @@ mp_process_pipeline_start()
mp_pipeline_invoke(pipeline, setup, NULL, 0); mp_pipeline_invoke(pipeline, setup, NULL, 0);
mp_zbar_pipeline_start(); mp_zbar_pipeline_start();
} }
@@ -172,7 +171,7 @@ static GLES2Debayer *gles2_debayer = NULL;
static GdkGLContext *context; static GdkGLContext *context;
#define RENDERDOC // #define RENDERDOC
#ifdef RENDERDOC #ifdef RENDERDOC
#include <renderdoc/app.h> #include <renderdoc/app.h>
@@ -239,13 +238,15 @@ init_gl(MPPipeline *pipeline, GdkSurface **surface)
int major, minor; int major, minor;
gdk_gl_context_get_version(context, &major, &minor); gdk_gl_context_get_version(context, &major, &minor);
printf("Initialized %s %d.%d\n", is_es ? "OpenGL ES" : "OpenGL", major, minor); printf("Initialized %s %d.%d\n", is_es ? "OpenGL ES" : "OpenGL", major,
minor);
} }
void void
mp_process_pipeline_init_gl(GdkSurface *surface) mp_process_pipeline_init_gl(GdkSurface *surface)
{ {
mp_pipeline_invoke(pipeline, (MPPipelineCallback) init_gl, &surface, sizeof(GdkSurface *)); mp_pipeline_invoke(pipeline, (MPPipelineCallback)init_gl, &surface,
sizeof(GdkSurface *));
} }
static GdkTexture * static GdkTexture *
@@ -269,7 +270,9 @@ process_image_for_preview(const uint8_t *image)
assert(output_buffer != NULL); assert(output_buffer != NULL);
#ifdef RENDERDOC #ifdef RENDERDOC
if (rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL); if (rdoc_api) {
rdoc_api->StartFrameCapture(NULL, NULL);
}
#endif #endif
// Copy image to a GL texture. TODO: This can be avoided // Copy image to a GL texture. TODO: This can be avoided
@@ -280,11 +283,12 @@ process_image_for_preview(const uint8_t *image)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, mode.width, mode.height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, mode.width, mode.height, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, image);
check_gl(); check_gl();
gles2_debayer_process( gles2_debayer_process(gles2_debayer, output_buffer->texture_id,
gles2_debayer, output_buffer->texture_id, input_texture); input_texture);
check_gl(); check_gl();
glFinish(); glFinish();
@@ -293,11 +297,14 @@ process_image_for_preview(const uint8_t *image)
#ifdef PROFILE_DEBAYER #ifdef PROFILE_DEBAYER
clock_t t2 = clock(); clock_t t2 = clock();
printf("process_image_for_preview %fms\n", (float)(t2 - t1) / CLOCKS_PER_SEC * 1000); printf("process_image_for_preview %fms\n",
(float)(t2 - t1) / CLOCKS_PER_SEC * 1000);
#endif #endif
#ifdef RENDERDOC #ifdef RENDERDOC
if(rdoc_api) rdoc_api->EndFrameCapture(NULL, NULL); if (rdoc_api) {
rdoc_api->EndFrameCapture(NULL, NULL);
}
#endif #endif
mp_process_pipeline_buffer_ref(output_buffer); mp_process_pipeline_buffer_ref(output_buffer);
@@ -308,27 +315,31 @@ process_image_for_preview(const uint8_t *image)
if (captures_remaining == 1) { if (captures_remaining == 1) {
printf("Making thumbnail\n"); printf("Making thumbnail\n");
size_t size = output_buffer_width * output_buffer_height * sizeof(uint32_t); size_t size = output_buffer_width * output_buffer_height *
sizeof(uint32_t);
uint32_t *data = g_malloc_n(size, 1); uint32_t *data = g_malloc_n(size, 1);
glReadPixels(0, 0, output_buffer_width, output_buffer_height, GL_RGBA, GL_UNSIGNED_BYTE, data); glReadPixels(0, 0, output_buffer_width, output_buffer_height,
GL_RGBA, GL_UNSIGNED_BYTE, data);
check_gl(); check_gl();
// Flip vertically // Flip vertically
for (size_t y = 0; y < output_buffer_height / 2; ++y) { for (size_t y = 0; y < output_buffer_height / 2; ++y) {
for (size_t x = 0; x < output_buffer_width; ++x) { for (size_t x = 0; x < output_buffer_width; ++x) {
uint32_t tmp = data[(output_buffer_height - y - 1) * output_buffer_width + x]; uint32_t tmp = data[(output_buffer_height - y - 1) *
data[(output_buffer_height - y - 1) * output_buffer_width + x] = data[y * output_buffer_width + x]; output_buffer_width +
x];
data[(output_buffer_height - y - 1) *
output_buffer_width +
x] = data[y * output_buffer_width + x];
data[y * output_buffer_width + x] = tmp; data[y * output_buffer_width + x] = tmp;
} }
} }
thumb = gdk_memory_texture_new( thumb = gdk_memory_texture_new(
output_buffer_width, output_buffer_width, output_buffer_height,
output_buffer_height, GDK_MEMORY_R8G8B8A8, g_bytes_new_take(data, size),
GDK_MEMORY_R8G8B8A8,
g_bytes_new_take(data, size),
output_buffer_width * sizeof(uint32_t)); output_buffer_width * sizeof(uint32_t));
} }
@@ -365,16 +376,16 @@ process_image_for_capture(const uint8_t *image, int count)
uint16_t orientation; uint16_t orientation;
if (camera_rotation == 0) { if (camera_rotation == 0) {
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
ORIENTATION_TOPLEFT; ORIENTATION_TOPLEFT;
} else if (camera_rotation == 90) { } else if (camera_rotation == 90) {
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
ORIENTATION_LEFTBOT; ORIENTATION_LEFTBOT;
} else if (camera_rotation == 180) { } else if (camera_rotation == 180) {
orientation = camera->mirrored ? ORIENTATION_BOTLEFT : orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
ORIENTATION_BOTRIGHT; ORIENTATION_BOTRIGHT;
} else { } else {
orientation = camera->mirrored ? ORIENTATION_LEFTTOP : orientation = camera->mirrored ? ORIENTATION_LEFTTOP :
ORIENTATION_RIGHTTOP; ORIENTATION_RIGHTTOP;
} }
TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation); TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
TIFFSetField(tif, TIFFTAG_DATETIME, datetime); TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
@@ -415,7 +426,8 @@ process_image_for_capture(const uint8_t *image, int count)
TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0);
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, mp_pixel_format_bits_per_pixel(mode.pixel_format)); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,
mp_pixel_format_bits_per_pixel(mode.pixel_format));
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
@@ -429,7 +441,8 @@ process_image_for_capture(const uint8_t *image, int count)
printf("TIFF version %d\n", TIFFLIB_VERSION); printf("TIFF version %d\n", TIFFLIB_VERSION);
int whitelevel = camera->whitelevel; int whitelevel = camera->whitelevel;
if (!whitelevel) { if (!whitelevel) {
whitelevel = (1 << mp_pixel_format_pixel_depth(mode.pixel_format)) - 1; whitelevel =
(1 << mp_pixel_format_pixel_depth(mode.pixel_format)) - 1;
} }
TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel); TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel);
if (camera->blacklevel) { if (camera->blacklevel) {
@@ -440,7 +453,12 @@ process_image_for_capture(const uint8_t *image, int count)
printf("Writing frame to %s\n", fname); printf("Writing frame to %s\n", fname);
for (int row = 0; row < mode.height; row++) { for (int row = 0; row < mode.height; row++) {
TIFFWriteScanline(tif, (void *) image + (row * mp_pixel_format_width_to_bytes(mode.pixel_format, mode.width)), row, 0); TIFFWriteScanline(
tif,
(void *)image +
(row * mp_pixel_format_width_to_bytes(
mode.pixel_format, mode.width)),
row, 0);
} }
TIFFWriteDirectory(tif); TIFFWriteDirectory(tif);
@@ -522,19 +540,14 @@ process_capture_burst(GdkTexture *thumb)
strftime(timestamp, 30, "%Y%m%d%H%M%S", &tim); strftime(timestamp, 30, "%Y%m%d%H%M%S", &tim);
if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) { if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) {
sprintf(capture_fname, sprintf(capture_fname, "%s/IMG%s",
"%s/IMG%s",
g_get_user_special_dir(G_USER_DIRECTORY_PICTURES), g_get_user_special_dir(G_USER_DIRECTORY_PICTURES),
timestamp); timestamp);
} else if (getenv("XDG_PICTURES_DIR") != NULL) { } else if (getenv("XDG_PICTURES_DIR") != NULL) {
sprintf(capture_fname, sprintf(capture_fname, "%s/IMG%s", getenv("XDG_PICTURES_DIR"),
"%s/IMG%s",
getenv("XDG_PICTURES_DIR"),
timestamp); timestamp);
} else { } else {
sprintf(capture_fname, sprintf(capture_fname, "%s/Pictures/IMG%s", getenv("HOME"),
"%s/Pictures/IMG%s",
getenv("HOME"),
timestamp); timestamp);
} }
@@ -544,16 +557,12 @@ process_capture_burst(GdkTexture *thumb)
} }
// Start post-processing the captured burst // Start post-processing the captured burst
g_print("Post process %s to %s.ext (save-dng %s)\n", burst_dir, capture_fname, save_dng_s); g_print("Post process %s to %s.ext (save-dng %s)\n", burst_dir,
capture_fname, save_dng_s);
GError *error = NULL; GError *error = NULL;
GSubprocess *proc = g_subprocess_new( GSubprocess *proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error,
G_SUBPROCESS_FLAGS_STDOUT_PIPE, processing_script, burst_dir,
&error, capture_fname, save_dng_s, NULL);
processing_script,
burst_dir,
capture_fname,
save_dng_s,
NULL);
if (!proc) { if (!proc) {
g_printerr("Failed to spawn postprocess process: %s\n", g_printerr("Failed to spawn postprocess process: %s\n",
@@ -562,11 +571,7 @@ process_capture_burst(GdkTexture *thumb)
} }
g_subprocess_communicate_utf8_async( g_subprocess_communicate_utf8_async(
proc, proc, NULL, NULL, (GAsyncReadyCallback)post_process_finished, thumb);
NULL,
NULL,
(GAsyncReadyCallback)post_process_finished,
thumb);
} }
static void static void
@@ -576,14 +581,15 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
clock_t t1 = clock(); clock_t t1 = clock();
#endif #endif
size_t size = size_t size = mp_pixel_format_width_to_bytes(mode.pixel_format, mode.width) *
mp_pixel_format_width_to_bytes(mode.pixel_format, mode.width) * mode.height;
mode.height;
uint8_t *image = malloc(size); uint8_t *image = malloc(size);
memcpy(image, buffer->data, size); memcpy(image, buffer->data, size);
mp_io_pipeline_release_buffer(buffer->index); mp_io_pipeline_release_buffer(buffer->index);
MPZBarImage *zbar_image = mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height, camera_rotation, camera->mirrored); MPZBarImage *zbar_image =
mp_zbar_image_new(image, mode.pixel_format, mode.width, mode.height,
camera_rotation, camera->mirrored);
mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image)); mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image));
#ifdef PROFILE_PROCESS #ifdef PROFILE_PROCESS
@@ -678,16 +684,16 @@ on_output_changed()
for (size_t i = 0; i < NUM_BUFFERS; ++i) { for (size_t i = 0; i < NUM_BUFFERS; ++i) {
glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id); glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_buffer_width, output_buffer_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_buffer_width,
output_buffer_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
NULL);
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
gles2_debayer_configure( gles2_debayer_configure(
gles2_debayer, gles2_debayer, output_buffer_width, output_buffer_height, mode.width,
output_buffer_width, output_buffer_height, mode.height, camera->rotate, camera->mirrored,
mode.width, mode.height,
camera->rotate, camera->mirrored,
camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix,
camera->blacklevel); camera->blacklevel);
} }
@@ -695,18 +701,18 @@ on_output_changed()
static int static int
mod(int a, int b) mod(int a, int b)
{ {
int r = a % b; int r = a % b;
return r < 0 ? r + b : r; return r < 0 ? r + b : r;
} }
static void static void
update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state) update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state)
{ {
const bool output_changed = const bool output_changed =
!mp_camera_mode_is_equivalent(&mode, &state->mode) !mp_camera_mode_is_equivalent(&mode, &state->mode) ||
|| preview_width != state->preview_width preview_width != state->preview_width ||
|| preview_height != state->preview_height preview_height != state->preview_height ||
|| device_rotation != state->device_rotation; device_rotation != state->device_rotation;
camera = state->camera; camera = state->camera;
mode = state->mode; mode = state->mode;
@@ -756,4 +762,7 @@ mp_process_pipeline_update_state(const struct mp_process_pipeline_state *new_sta
} }
// GTK4 seems to require this // GTK4 seems to require this
void pango_fc_font_get_languages() {} void
pango_fc_font_get_languages()
{
}

View File

@@ -24,7 +24,8 @@ static volatile int frames_received = 0;
static zbar_image_scanner_t *scanner; static zbar_image_scanner_t *scanner;
static void setup(MPPipeline *pipeline, const void *data) static void
setup(MPPipeline *pipeline, const void *data)
{ {
scanner = zbar_image_scanner_create(); scanner = zbar_image_scanner_create();
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1); zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
@@ -48,29 +49,29 @@ static bool
is_3d_code(zbar_symbol_type_t type) is_3d_code(zbar_symbol_type_t type)
{ {
switch (type) { switch (type) {
case ZBAR_EAN2: case ZBAR_EAN2:
case ZBAR_EAN5: case ZBAR_EAN5:
case ZBAR_EAN8: case ZBAR_EAN8:
case ZBAR_UPCE: case ZBAR_UPCE:
case ZBAR_ISBN10: case ZBAR_ISBN10:
case ZBAR_UPCA: case ZBAR_UPCA:
case ZBAR_EAN13: case ZBAR_EAN13:
case ZBAR_ISBN13: case ZBAR_ISBN13:
case ZBAR_I25: case ZBAR_I25:
case ZBAR_DATABAR: case ZBAR_DATABAR:
case ZBAR_DATABAR_EXP: case ZBAR_DATABAR_EXP:
case ZBAR_CODABAR: case ZBAR_CODABAR:
case ZBAR_CODE39: case ZBAR_CODE39:
case ZBAR_CODE93: case ZBAR_CODE93:
case ZBAR_CODE128: case ZBAR_CODE128:
return false; return false;
case ZBAR_COMPOSITE: case ZBAR_COMPOSITE:
case ZBAR_PDF417: case ZBAR_PDF417:
case ZBAR_QRCODE: case ZBAR_QRCODE:
case ZBAR_SQCODE: case ZBAR_SQCODE:
return true; return true;
default: default:
return false; return false;
} }
} }
@@ -101,7 +102,8 @@ map_coords(int *x, int *y, int width, int height, int rotation, bool mirrored)
} }
static MPZBarCode static MPZBarCode
process_symbol(const MPZBarImage *image, int width, int height, const zbar_symbol_t *symbol) process_symbol(const MPZBarImage *image, int width, int height,
const zbar_symbol_t *symbol)
{ {
if (image->rotation == 90 || image->rotation == 270) { if (image->rotation == 90 || image->rotation == 270) {
int tmp = width; int tmp = width;
@@ -145,13 +147,14 @@ process_symbol(const MPZBarImage *image, int width, int height, const zbar_symbo
} }
for (uint8_t i = 0; i < 4; ++i) { for (uint8_t i = 0; i < 4; ++i) {
map_coords(&code.bounds_x[i], &code.bounds_y[i], width, height, image->rotation, image->mirrored); map_coords(&code.bounds_x[i], &code.bounds_y[i], width, height,
image->rotation, image->mirrored);
} }
const char *data = zbar_symbol_get_data(symbol); const char *data = zbar_symbol_get_data(symbol);
unsigned int data_size = zbar_symbol_get_data_length(symbol); unsigned int data_size = zbar_symbol_get_data_length(symbol);
code.type = zbar_get_symbol_name(type); code.type = zbar_get_symbol_name(type);
code.data = strndup(data, data_size+1); code.data = strndup(data, data_size + 1);
code.data[data_size] = 0; code.data[data_size] = 0;
return code; return code;
@@ -162,10 +165,10 @@ process_image(MPPipeline *pipeline, MPZBarImage **_image)
{ {
MPZBarImage *image = *_image; MPZBarImage *image = *_image;
assert(image->pixel_format == MP_PIXEL_FMT_BGGR8 assert(image->pixel_format == MP_PIXEL_FMT_BGGR8 ||
|| image->pixel_format == MP_PIXEL_FMT_GBRG8 image->pixel_format == MP_PIXEL_FMT_GBRG8 ||
|| image->pixel_format == MP_PIXEL_FMT_GRBG8 image->pixel_format == MP_PIXEL_FMT_GRBG8 ||
|| image->pixel_format == MP_PIXEL_FMT_RGGB8); image->pixel_format == MP_PIXEL_FMT_RGGB8);
// Create a grayscale image for scanning from the current preview. // Create a grayscale image for scanning from the current preview.
// Rotate/mirror correctly. // Rotate/mirror correctly.
@@ -184,7 +187,8 @@ process_image(MPPipeline *pipeline, MPZBarImage **_image)
zbar_image_t *zbar_image = zbar_image_create(); zbar_image_t *zbar_image = zbar_image_create();
zbar_image_set_format(zbar_image, zbar_fourcc('Y', '8', '0', '0')); zbar_image_set_format(zbar_image, zbar_fourcc('Y', '8', '0', '0'));
zbar_image_set_size(zbar_image, width, height); zbar_image_set_size(zbar_image, width, height);
zbar_image_set_data(zbar_image, data, width * height * sizeof(uint8_t), zbar_image_free_data); zbar_image_set_data(zbar_image, data, width * height * sizeof(uint8_t),
zbar_image_free_data);
int res = zbar_scan_image(scanner, zbar_image); int res = zbar_scan_image(scanner, zbar_image);
assert(res >= 0); assert(res >= 0);
@@ -196,7 +200,8 @@ process_image(MPPipeline *pipeline, MPZBarImage **_image)
const zbar_symbol_t *symbol = zbar_image_first_symbol(zbar_image); const zbar_symbol_t *symbol = zbar_image_first_symbol(zbar_image);
for (int i = 0; i < MIN(res, 8); ++i) { for (int i = 0; i < MIN(res, 8); ++i) {
assert(symbol != NULL); assert(symbol != NULL);
result->codes[i] = process_symbol(image, width, height, symbol); result->codes[i] =
process_symbol(image, width, height, symbol);
symbol = zbar_symbol_next(symbol); symbol = zbar_symbol_next(symbol);
} }
@@ -227,12 +232,8 @@ mp_zbar_pipeline_process_image(MPZBarImage *image)
} }
MPZBarImage * MPZBarImage *
mp_zbar_image_new(uint8_t *data, mp_zbar_image_new(uint8_t *data, MPPixelFormat pixel_format, int width, int height,
MPPixelFormat pixel_format, int rotation, bool mirrored)
int width,
int height,
int rotation,
bool mirrored)
{ {
MPZBarImage *image = malloc(sizeof(MPZBarImage)); MPZBarImage *image = malloc(sizeof(MPZBarImage));
image->data = data; image->data = data;

View File

@@ -21,11 +21,7 @@ void mp_zbar_pipeline_stop();
void mp_zbar_pipeline_process_image(MPZBarImage *image); void mp_zbar_pipeline_process_image(MPZBarImage *image);
MPZBarImage *mp_zbar_image_new(uint8_t *data, MPZBarImage *mp_zbar_image_new(uint8_t *data, MPPixelFormat pixel_format, int width,
MPPixelFormat pixel_format, int height, int rotation, bool mirrored);
int width,
int height,
int rotation,
bool mirrored);
MPZBarImage *mp_zbar_image_ref(MPZBarImage *image); MPZBarImage *mp_zbar_image_ref(MPZBarImage *image);
void mp_zbar_image_unref(MPZBarImage *image); void mp_zbar_image_unref(MPZBarImage *image);

View File

@@ -175,9 +175,9 @@ main(int argc, char *argv[])
printf(" Failed to capture buffer\n"); printf(" Failed to capture buffer\n");
} }
size_t num_bytes = size_t num_bytes = mp_pixel_format_width_to_bytes(
mp_pixel_format_width_to_bytes(m->pixel_format, m->width) * m->pixel_format, m->width) *
m->height; m->height;
uint8_t *data = malloc(num_bytes); uint8_t *data = malloc(num_bytes);
memcpy(data, buffer.data, num_bytes); memcpy(data, buffer.data, num_bytes);