From 772db36877c456611022e89028eb4a210553ac1b Mon Sep 17 00:00:00 2001 From: Benjamin Schaaf Date: Sat, 13 Nov 2021 00:00:03 +1100 Subject: [PATCH] Make clang-format more aggressive clang-format always manages to mix spaces into tab-based indentation. Since we already require an exact tab-width of 8 it makes more sense to use spaces. --- .clang-format | 56 +- .gitlab-ci.yml | 6 - data/blit.frag | 2 +- data/blit.vert | 4 +- data/debayer.frag | 41 +- data/debayer.vert | 10 +- data/solid.frag | 2 +- data/solid.vert | 2 +- src/camera.c | 1903 ++++++++++++++++++++-------------------- src/camera.h | 66 +- src/camera_config.c | 432 ++++----- src/camera_config.h | 54 +- src/device.c | 493 +++++------ src/device.h | 28 +- src/flash.c | 240 ++--- src/gl_util.c | 358 ++++---- src/gl_util.h | 6 +- src/gles2_debayer.c | 186 ++-- src/gles2_debayer.h | 14 +- src/io_pipeline.c | 776 ++++++++-------- src/io_pipeline.h | 22 +- src/main.c | 1287 ++++++++++++++------------- src/main.h | 26 +- src/matrix.c | 28 +- src/pipeline.c | 149 ++-- src/pipeline.h | 13 +- src/process_pipeline.c | 1006 +++++++++++---------- src/process_pipeline.h | 28 +- src/zbar_pipeline.c | 358 ++++---- src/zbar_pipeline.h | 20 +- tools/camera_test.c | 303 +++---- tools/list_devices.c | 97 +- 32 files changed, 4155 insertions(+), 3861 deletions(-) diff --git a/.clang-format b/.clang-format index ccb07fa..7f788bf 100644 --- a/.clang-format +++ b/.clang-format @@ -13,7 +13,7 @@ AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false -#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 +AlignEscapedNewlines: Right AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false @@ -26,8 +26,8 @@ AlwaysBreakAfterDefinitionReturnType: All AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true +BinPackArguments: false +BinPackParameters: false BraceWrapping: AfterClass: false AfterControlStatement: false @@ -37,24 +37,24 @@ BraceWrapping: AfterObjCDeclaration: false AfterStruct: false AfterUnion: false - #AfterExternBlock: false # Unknown to clang-format-5.0 + AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false - #SplitEmptyFunction: true # Unknown to clang-format-4.0 - #SplitEmptyRecord: true # Unknown to clang-format-4.0 - #SplitEmptyNamespace: true # Unknown to clang-format-4.0 + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom -#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 +BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false -#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 +BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: false ColumnLimit: 85 CommentPragmas: '^ IWYU pragma:' -#CompactNamespaces: false # Unknown to clang-format-4.0 +CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 @@ -62,7 +62,7 @@ Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false -#FixNamespaceComments: false # Unknown to clang-format-4.0 +FixNamespaceComments: false # Taken from: # git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \ @@ -494,13 +494,13 @@ ForEachMacros: - 'xbc_node_for_each_key_value' - 'zorro_for_each_dev' -#IncludeBlocks: Preserve # Unknown to clang-format-5.0 +IncludeBlocks: Preserve IncludeCategories: - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false -#IndentPPDirectives: None # Unknown to clang-format-5.0 +IndentPPDirectives: None IndentWidth: 8 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave @@ -510,31 +510,31 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 +ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true # Taken from git's rules -#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0 -PenaltyBreakBeforeFirstCallParameter: 30 -PenaltyBreakComment: 10 -PenaltyBreakFirstLessLess: 0 -PenaltyBreakString: 10 -PenaltyExcessCharacter: 100 -PenaltyReturnTypeOnItsOwnLine: 60 +#PenaltyBreakAssignment: 10 +#PenaltyBreakBeforeFirstCallParameter: 30 +#PenaltyBreakComment: 10 +#PenaltyBreakFirstLessLess: 0 +#PenaltyBreakString: 10 +#PenaltyExcessCharacter: 100 +#PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right -ReflowComments: false -SortIncludes: false -#SortUsingDeclarations: false # Unknown to clang-format-4.0 +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 -#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements -#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 +SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false @@ -544,5 +544,5 @@ SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp03 TabWidth: 8 -UseTab: Always +UseTab: Never ... diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 97a5552..49089cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,3 @@ -.build_template: &build_definition - script: - - meson build - - ninja -C build - - ninja -C build test - build:debian: image: debian:bookworm-slim before_script: diff --git a/data/blit.frag b/data/blit.frag index 22c03d9..0d30d7a 100644 --- a/data/blit.frag +++ b/data/blit.frag @@ -9,5 +9,5 @@ varying vec2 uv; void main() { - gl_FragColor = vec4(texture2D(texture, uv).rgb, 1); + gl_FragColor = vec4(texture2D(texture, uv).rgb, 1); } diff --git a/data/blit.vert b/data/blit.vert index eb52585..0d4dc5e 100644 --- a/data/blit.vert +++ b/data/blit.vert @@ -12,7 +12,7 @@ varying vec2 uv; void main() { - uv = tex_coord; + uv = tex_coord; - gl_Position = vec4(transform * vec3(vert, 1), 1); + gl_Position = vec4(transform * vec3(vert, 1), 1); } diff --git a/data/debayer.frag b/data/debayer.frag index b720820..77b9097 100644 --- a/data/debayer.frag +++ b/data/debayer.frag @@ -13,30 +13,31 @@ varying vec2 bottom_right_uv; void main() { - // 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 - // they end up as 16-bit floats and that's not accurate enough. - vec4 samples = vec4(texture2D(texture, top_left_uv).r, - texture2D(texture, top_right_uv).r, - texture2D(texture, bottom_left_uv).r, - texture2D(texture, bottom_right_uv).r); + // 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 + // they end up as 16-bit floats and that's not accurate enough. + vec4 samples = vec4(texture2D(texture, top_left_uv).r, + texture2D(texture, top_right_uv).r, + texture2D(texture, bottom_left_uv).r, + texture2D(texture, bottom_right_uv).r); - // 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. - vec3 color = vec3(samples.w, (samples.y + samples.z) / 2.0, samples.x); + // 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. + vec3 color = vec3(samples.w, (samples.y + samples.z) / 2.0, samples.x); - // Some crude blacklevel correction to make the preview a bit nicer, this should be an uniform - vec3 corrected = color - 0.02; + // Some crude blacklevel correction to make the preview a bit nicer, this + // should be an uniform + vec3 corrected = color - 0.02; - // Apply the color matrices - //vec3 corrected = color_matrix * color2; + // Apply the color matrices + // vec3 corrected = color_matrix * color2; - // Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/ - vec3 srgb_color = - (vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected; + // Fast SRGB estimate. See https://mimosa-pudica.net/fast-gamma/ + vec3 srgb_color = + (vec3(1.138) * inversesqrt(corrected) - vec3(0.138)) * corrected; - // Slow SRGB estimate - // vec3 srgb_color = pow(color, vec3(1.0 / 2.2)); + // Slow SRGB estimate + // vec3 srgb_color = pow(color, vec3(1.0 / 2.2)); - gl_FragColor = vec4(srgb_color, 1); + gl_FragColor = vec4(srgb_color, 1); } diff --git a/data/debayer.vert b/data/debayer.vert index bb67269..9126c9d 100644 --- a/data/debayer.vert +++ b/data/debayer.vert @@ -16,10 +16,10 @@ varying vec2 bottom_right_uv; void main() { - top_left_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); - bottom_left_uv = vec2(bottom_right_uv.x, top_left_uv.y); + top_left_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); + bottom_left_uv = vec2(bottom_right_uv.x, top_left_uv.y); - gl_Position = vec4(transform * vec3(vert, 1), 1); + gl_Position = vec4(transform * vec3(vert, 1), 1); } diff --git a/data/solid.frag b/data/solid.frag index 16d3026..06b04f3 100644 --- a/data/solid.frag +++ b/data/solid.frag @@ -7,5 +7,5 @@ uniform vec4 color; void main() { - gl_FragColor = color; + gl_FragColor = color; } diff --git a/data/solid.vert b/data/solid.vert index 93a7c48..d83a7d4 100644 --- a/data/solid.vert +++ b/data/solid.vert @@ -7,5 +7,5 @@ attribute vec2 vert; void main() { - gl_Position = vec4(vert, 0, 1); + gl_Position = vec4(vert, 0, 1); } diff --git a/src/camera.c b/src/camera.c index e90b0ce..f429b73 100644 --- a/src/camera.c +++ b/src/camera.c @@ -13,1360 +13,1375 @@ #define MAX_BG_TASKS 8 static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = { - "unsupported", "BGGR8", "GBRG8", "GRBG8", "RGGB8", "BGGR10P", - "GBRG10P", "GRBG10P", "RGGB10P", "UYVY", "YUYV", + "unsupported", "BGGR8", "GBRG8", "GRBG8", "RGGB8", "BGGR10P", + "GBRG10P", "GRBG10P", "RGGB10P", "UYVY", "YUYV", }; const char * mp_pixel_format_to_str(uint32_t pixel_format) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID"); - return pixel_format_names[pixel_format]; + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID"); + return pixel_format_names[pixel_format]; } MPPixelFormat mp_pixel_format_from_str(const char *name) { - for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { - if (strcasecmp(pixel_format_names[i], name) == 0) { - return i; - } - } - g_return_val_if_reached(MP_PIXEL_FMT_UNSUPPORTED); + for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { + if (strcasecmp(pixel_format_names[i], name) == 0) { + return i; + } + } + g_return_val_if_reached(MP_PIXEL_FMT_UNSUPPORTED); } static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = { - 0, - V4L2_PIX_FMT_SBGGR8, - V4L2_PIX_FMT_SGBRG8, - V4L2_PIX_FMT_SGRBG8, - V4L2_PIX_FMT_SRGGB8, - V4L2_PIX_FMT_SBGGR10P, - V4L2_PIX_FMT_SGBRG10P, - V4L2_PIX_FMT_SGRBG10P, - V4L2_PIX_FMT_SRGGB10P, - V4L2_PIX_FMT_UYVY, - V4L2_PIX_FMT_YUYV, + 0, + V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGBRG8, + V4L2_PIX_FMT_SGRBG8, + V4L2_PIX_FMT_SRGGB8, + V4L2_PIX_FMT_SBGGR10P, + V4L2_PIX_FMT_SGBRG10P, + V4L2_PIX_FMT_SGRBG10P, + V4L2_PIX_FMT_SRGGB10P, + V4L2_PIX_FMT_UYVY, + V4L2_PIX_FMT_YUYV, }; uint32_t mp_pixel_format_to_v4l_pixel_format(MPPixelFormat pixel_format) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - return pixel_format_v4l_pixel_formats[pixel_format]; + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + return pixel_format_v4l_pixel_formats[pixel_format]; } MPPixelFormat mp_pixel_format_from_v4l_pixel_format(uint32_t v4l_pixel_format) { - for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { - if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) { - return i; - } - } - return MP_PIXEL_FMT_UNSUPPORTED; + for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { + if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) { + return i; + } + } + return MP_PIXEL_FMT_UNSUPPORTED; } static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = { - 0, - MEDIA_BUS_FMT_SBGGR8_1X8, - MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8, - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, - MEDIA_BUS_FMT_UYVY8_2X8, - MEDIA_BUS_FMT_YUYV8_2X8, + 0, + MEDIA_BUS_FMT_SBGGR8_1X8, + MEDIA_BUS_FMT_SGBRG8_1X8, + MEDIA_BUS_FMT_SGRBG8_1X8, + MEDIA_BUS_FMT_SRGGB8_1X8, + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_UYVY8_2X8, + MEDIA_BUS_FMT_YUYV8_2X8, }; uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - return pixel_format_v4l_bus_codes[pixel_format]; + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + return pixel_format_v4l_bus_codes[pixel_format]; } MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code) { - for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { - if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) { - return i; - } - } - return MP_PIXEL_FMT_UNSUPPORTED; + for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) { + if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) { + return i; + } + } + return MP_PIXEL_FMT_UNSUPPORTED; } uint32_t mp_pixel_format_bits_per_pixel(MPPixelFormat pixel_format) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - switch (pixel_format) { - case MP_PIXEL_FMT_BGGR8: - case MP_PIXEL_FMT_GBRG8: - case MP_PIXEL_FMT_GRBG8: - case MP_PIXEL_FMT_RGGB8: - return 8; - case MP_PIXEL_FMT_BGGR10P: - case MP_PIXEL_FMT_GBRG10P: - case MP_PIXEL_FMT_GRBG10P: - case MP_PIXEL_FMT_RGGB10P: - return 10; - case MP_PIXEL_FMT_UYVY: - case MP_PIXEL_FMT_YUYV: - return 16; - default: - return 0; - } + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + switch (pixel_format) { + case MP_PIXEL_FMT_BGGR8: + case MP_PIXEL_FMT_GBRG8: + case MP_PIXEL_FMT_GRBG8: + case MP_PIXEL_FMT_RGGB8: + return 8; + case MP_PIXEL_FMT_BGGR10P: + case MP_PIXEL_FMT_GBRG10P: + case MP_PIXEL_FMT_GRBG10P: + case MP_PIXEL_FMT_RGGB10P: + return 10; + case MP_PIXEL_FMT_UYVY: + case MP_PIXEL_FMT_YUYV: + return 16; + default: + return 0; + } } uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - switch (pixel_format) { - case MP_PIXEL_FMT_BGGR8: - case MP_PIXEL_FMT_GBRG8: - case MP_PIXEL_FMT_GRBG8: - case MP_PIXEL_FMT_RGGB8: - case MP_PIXEL_FMT_UYVY: - case MP_PIXEL_FMT_YUYV: - return 8; - case MP_PIXEL_FMT_GBRG10P: - case MP_PIXEL_FMT_GRBG10P: - case MP_PIXEL_FMT_RGGB10P: - case MP_PIXEL_FMT_BGGR10P: - return 10; - default: - return 0; - } + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + switch (pixel_format) { + case MP_PIXEL_FMT_BGGR8: + case MP_PIXEL_FMT_GBRG8: + case MP_PIXEL_FMT_GRBG8: + case MP_PIXEL_FMT_RGGB8: + case MP_PIXEL_FMT_UYVY: + case MP_PIXEL_FMT_YUYV: + return 8; + case MP_PIXEL_FMT_GBRG10P: + case MP_PIXEL_FMT_GRBG10P: + case MP_PIXEL_FMT_RGGB10P: + case MP_PIXEL_FMT_BGGR10P: + return 10; + default: + return 0; + } } uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width) { - uint32_t bits_per_pixel = mp_pixel_format_bits_per_pixel(pixel_format); - uint64_t bits_per_width = width * (uint64_t)bits_per_pixel; + uint32_t bits_per_pixel = mp_pixel_format_bits_per_pixel(pixel_format); + uint64_t bits_per_width = width * (uint64_t)bits_per_pixel; - uint64_t remainder = bits_per_width % 8; - if (remainder == 0) - return bits_per_width / 8; + uint64_t remainder = bits_per_width % 8; + if (remainder == 0) + return bits_per_width / 8; - return (bits_per_width + 8 - remainder) / 8; + return (bits_per_width + 8 - remainder) / 8; } uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - switch (pixel_format) { - case MP_PIXEL_FMT_BGGR8: - case MP_PIXEL_FMT_GBRG8: - case MP_PIXEL_FMT_GRBG8: - case MP_PIXEL_FMT_RGGB8: - return width / 2; - case MP_PIXEL_FMT_BGGR10P: - case MP_PIXEL_FMT_GBRG10P: - case MP_PIXEL_FMT_GRBG10P: - case MP_PIXEL_FMT_RGGB10P: - return width / 2 * 5; - case MP_PIXEL_FMT_UYVY: - case MP_PIXEL_FMT_YUYV: - return width; - default: - return 0; - } + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + switch (pixel_format) { + case MP_PIXEL_FMT_BGGR8: + case MP_PIXEL_FMT_GBRG8: + case MP_PIXEL_FMT_GRBG8: + case MP_PIXEL_FMT_RGGB8: + return width / 2; + case MP_PIXEL_FMT_BGGR10P: + case MP_PIXEL_FMT_GBRG10P: + case MP_PIXEL_FMT_GRBG10P: + case MP_PIXEL_FMT_RGGB10P: + return width / 2 * 5; + case MP_PIXEL_FMT_UYVY: + case MP_PIXEL_FMT_YUYV: + return width; + default: + return 0; + } } uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t height) { - g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); - switch (pixel_format) { - case MP_PIXEL_FMT_BGGR8: - case MP_PIXEL_FMT_GBRG8: - case MP_PIXEL_FMT_GRBG8: - case MP_PIXEL_FMT_RGGB8: - case MP_PIXEL_FMT_BGGR10P: - case MP_PIXEL_FMT_GBRG10P: - case MP_PIXEL_FMT_GRBG10P: - case MP_PIXEL_FMT_RGGB10P: - return height / 2; - case MP_PIXEL_FMT_UYVY: - case MP_PIXEL_FMT_YUYV: - return height; - default: - return 0; - } + g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0); + switch (pixel_format) { + case MP_PIXEL_FMT_BGGR8: + case MP_PIXEL_FMT_GBRG8: + case MP_PIXEL_FMT_GRBG8: + case MP_PIXEL_FMT_RGGB8: + case MP_PIXEL_FMT_BGGR10P: + case MP_PIXEL_FMT_GBRG10P: + case MP_PIXEL_FMT_GRBG10P: + case MP_PIXEL_FMT_RGGB10P: + return height / 2; + case MP_PIXEL_FMT_UYVY: + case MP_PIXEL_FMT_YUYV: + return height; + default: + return 0; + } } bool mp_camera_mode_is_equivalent(const MPCameraMode *m1, const MPCameraMode *m2) { - return m1->pixel_format == m2->pixel_format && - m1->frame_interval.numerator == m2->frame_interval.numerator && - m1->frame_interval.denominator == m2->frame_interval.denominator && - m1->width == m2->width && m1->height == m2->height; + return m1->pixel_format == m2->pixel_format && + m1->frame_interval.numerator == m2->frame_interval.numerator && + m1->frame_interval.denominator == m2->frame_interval.denominator && + m1->width == m2->width && m1->height == m2->height; } static void errno_printerr(const char *s) { - g_printerr("MPCamera: %s error %d, %s\n", s, errno, strerror(errno)); + g_printerr("MPCamera: %s error %d, %s\n", s, errno, strerror(errno)); } static int xioctl(int fd, int request, void *arg) { - int r; - do { - r = ioctl(fd, request, arg); - } while (r == -1 && errno == EINTR); - return r; + int r; + do { + r = ioctl(fd, request, arg); + } while (r == -1 && errno == EINTR); + return r; } struct video_buffer { - uint32_t length; - uint8_t *data; - int fd; + uint32_t length; + uint8_t *data; + int fd; }; struct _MPCamera { - int video_fd; - int subdev_fd; + int video_fd; + int subdev_fd; - bool has_set_mode; - MPCameraMode current_mode; + bool has_set_mode; + MPCameraMode current_mode; - struct video_buffer buffers[MAX_VIDEO_BUFFERS]; - uint32_t num_buffers; + struct video_buffer buffers[MAX_VIDEO_BUFFERS]; + uint32_t num_buffers; - // keeping track of background task child-PIDs for cleanup code - int child_bg_pids[MAX_BG_TASKS]; + // keeping track of background task child-PIDs for cleanup code + int child_bg_pids[MAX_BG_TASKS]; - bool use_mplane; + bool use_mplane; }; MPCamera * mp_camera_new(int video_fd, int subdev_fd) { - g_return_val_if_fail(video_fd != -1, NULL); + g_return_val_if_fail(video_fd != -1, NULL); - // Query capabilities - struct v4l2_capability cap; - if (xioctl(video_fd, VIDIOC_QUERYCAP, &cap) == -1) { - return NULL; - } + // Query capabilities + struct v4l2_capability cap; + if (xioctl(video_fd, VIDIOC_QUERYCAP, &cap) == -1) { + return NULL; + } - // Check whether this is a video capture device - bool use_mplane; - if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) { - use_mplane = true; - printf("!!\n"); - } else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { - use_mplane = false; - } else { - return NULL; - } + // Check whether this is a video capture device + bool use_mplane; + if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) { + use_mplane = true; + printf("!!\n"); + } else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { + use_mplane = false; + } else { + return NULL; + } - MPCamera *camera = malloc(sizeof(MPCamera)); - camera->video_fd = video_fd; - camera->subdev_fd = subdev_fd; - camera->has_set_mode = false; - camera->num_buffers = 0; - camera->use_mplane = use_mplane; - memset(camera->child_bg_pids, 0, - sizeof(camera->child_bg_pids[0]) * MAX_BG_TASKS); - return camera; + MPCamera *camera = malloc(sizeof(MPCamera)); + camera->video_fd = video_fd; + camera->subdev_fd = subdev_fd; + camera->has_set_mode = false; + camera->num_buffers = 0; + camera->use_mplane = use_mplane; + memset(camera->child_bg_pids, + 0, + sizeof(camera->child_bg_pids[0]) * MAX_BG_TASKS); + return camera; } void mp_camera_free(MPCamera *camera) { - mp_camera_wait_bg_tasks(camera); + mp_camera_wait_bg_tasks(camera); - g_warn_if_fail(camera->num_buffers == 0); - if (camera->num_buffers != 0) { - mp_camera_stop_capture(camera); - } + g_warn_if_fail(camera->num_buffers == 0); + if (camera->num_buffers != 0) { + mp_camera_stop_capture(camera); + } - free(camera); + free(camera); } void mp_camera_add_bg_task(MPCamera *camera, pid_t pid) { - int status; - while (true) { - for (size_t i = 0; i < MAX_BG_TASKS; ++i) { - if (camera->child_bg_pids[i] == 0) { - camera->child_bg_pids[i] = pid; - return; - } else { - // error == -1, still running == 0 - if (waitpid(camera->child_bg_pids[i], &status, - WNOHANG) <= 0) - continue; // consider errored wait still running + int status; + while (true) { + for (size_t i = 0; i < MAX_BG_TASKS; ++i) { + if (camera->child_bg_pids[i] == 0) { + camera->child_bg_pids[i] = pid; + return; + } else { + // error == -1, still running == 0 + if (waitpid(camera->child_bg_pids[i], + &status, + WNOHANG) <= 0) + continue; // consider errored wait still + // running - if (WIFEXITED(status)) { - // replace exited - camera->child_bg_pids[i] = pid; - return; - } - } - } + if (WIFEXITED(status)) { + // replace exited + camera->child_bg_pids[i] = pid; + return; + } + } + } - // wait for any status change on child processes - pid_t changed = waitpid(-1, &status, 0); - if (WIFEXITED(status)) { - // some child exited - for (size_t i = 0; i < MAX_BG_TASKS; ++i) { - if (camera->child_bg_pids[i] == changed) { - camera->child_bg_pids[i] = pid; - return; - } - } - } + // wait for any status change on child processes + pid_t changed = waitpid(-1, &status, 0); + if (WIFEXITED(status)) { + // some child exited + for (size_t i = 0; i < MAX_BG_TASKS; ++i) { + if (camera->child_bg_pids[i] == changed) { + camera->child_bg_pids[i] = pid; + return; + } + } + } - // no luck, repeat and check if something exited maybe - } + // no luck, repeat and check if something exited maybe + } } void mp_camera_wait_bg_tasks(MPCamera *camera) { - for (size_t i = 0; i < MAX_BG_TASKS; ++i) { - if (camera->child_bg_pids[i] != 0) { - // ignore errors - waitpid(camera->child_bg_pids[i], NULL, 0); - } - } + for (size_t i = 0; i < MAX_BG_TASKS; ++i) { + if (camera->child_bg_pids[i] != 0) { + // ignore errors + waitpid(camera->child_bg_pids[i], NULL, 0); + } + } } bool mp_camera_check_task_complete(MPCamera *camera, pid_t pid) { - // this method is potentially unsafe because pid could already be reused at - // this point, but extremely unlikely so we won't implement this. - int status; + // this method is potentially unsafe because pid could already be reused at + // this point, but extremely unlikely so we won't implement this. + int status; - if (pid == 0) - return true; + if (pid == 0) + return true; - // ignore errors (-1), no exit == 0 - int pidchange = waitpid(pid, &status, WNOHANG); - if (pidchange == -1) // error or exists and runs - return false; + // ignore errors (-1), no exit == 0 + int pidchange = waitpid(pid, &status, WNOHANG); + if (pidchange == -1) // error or exists and runs + return false; - if (WIFEXITED(status)) { - for (size_t i = 0; i < MAX_BG_TASKS; ++i) { - if (camera->child_bg_pids[i] == pid) { - camera->child_bg_pids[i] = 0; - break; - } - } - return true; - } else { - return false; - } + if (WIFEXITED(status)) { + for (size_t i = 0; i < MAX_BG_TASKS; ++i) { + if (camera->child_bg_pids[i] == pid) { + camera->child_bg_pids[i] = 0; + break; + } + } + return true; + } else { + return false; + } } bool mp_camera_is_subdev(MPCamera *camera) { - return camera->subdev_fd != -1; + return camera->subdev_fd != -1; } int mp_camera_get_video_fd(MPCamera *camera) { - return camera->video_fd; + return camera->video_fd; } int mp_camera_get_subdev_fd(MPCamera *camera) { - return camera->subdev_fd; + return camera->subdev_fd; } static bool camera_mode_impl(MPCamera *camera, int request, MPCameraMode *mode) { - uint32_t pixfmt = mp_pixel_format_from_v4l_pixel_format(mode->pixel_format); - struct v4l2_format fmt = {}; - if (camera->use_mplane) { - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - fmt.fmt.pix_mp.width = mode->width; - fmt.fmt.pix_mp.height = mode->height; - fmt.fmt.pix_mp.pixelformat = pixfmt; - fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; - } else { - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = mode->width; - fmt.fmt.pix.height = mode->height; - fmt.fmt.pix.pixelformat = pixfmt; - fmt.fmt.pix.field = V4L2_FIELD_ANY; - } + uint32_t pixfmt = mp_pixel_format_from_v4l_pixel_format(mode->pixel_format); + struct v4l2_format fmt = {}; + if (camera->use_mplane) { + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + fmt.fmt.pix_mp.width = mode->width; + fmt.fmt.pix_mp.height = mode->height; + fmt.fmt.pix_mp.pixelformat = pixfmt; + fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; + } else { + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = mode->width; + fmt.fmt.pix.height = mode->height; + fmt.fmt.pix.pixelformat = pixfmt; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + } - if (xioctl(camera->video_fd, request, &fmt) == -1) { - return false; - } + if (xioctl(camera->video_fd, request, &fmt) == -1) { + return false; + } - if (camera->use_mplane) { - mode->width = fmt.fmt.pix_mp.width; - mode->height = fmt.fmt.pix_mp.height; - mode->pixel_format = mp_pixel_format_from_v4l_pixel_format( - fmt.fmt.pix_mp.pixelformat); - } else { - mode->width = fmt.fmt.pix.width; - mode->height = fmt.fmt.pix.height; - mode->pixel_format = mp_pixel_format_from_v4l_pixel_format( - fmt.fmt.pix.pixelformat); - } + if (camera->use_mplane) { + mode->width = fmt.fmt.pix_mp.width; + mode->height = fmt.fmt.pix_mp.height; + mode->pixel_format = mp_pixel_format_from_v4l_pixel_format( + fmt.fmt.pix_mp.pixelformat); + } else { + mode->width = fmt.fmt.pix.width; + mode->height = fmt.fmt.pix.height; + mode->pixel_format = mp_pixel_format_from_v4l_pixel_format( + fmt.fmt.pix.pixelformat); + } - return true; + return true; } bool mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode) { - if (!camera_mode_impl(camera, VIDIOC_TRY_FMT, mode)) { - errno_printerr("VIDIOC_S_FMT"); - return false; - } - return true; + if (!camera_mode_impl(camera, VIDIOC_TRY_FMT, mode)) { + errno_printerr("VIDIOC_S_FMT"); + return false; + } + return true; } const MPCameraMode * mp_camera_get_mode(const MPCamera *camera) { - return &camera->current_mode; + return &camera->current_mode; } bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode) { - // Set the mode in the subdev the camera is one - if (mp_camera_is_subdev(camera)) { - struct v4l2_subdev_frame_interval interval = {}; - interval.pad = 0; - interval.interval = mode->frame_interval; - if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, - &interval) == -1) { - errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); - return false; - } + // Set the mode in the subdev the camera is one + if (mp_camera_is_subdev(camera)) { + struct v4l2_subdev_frame_interval interval = {}; + interval.pad = 0; + interval.interval = mode->frame_interval; + if (xioctl(camera->subdev_fd, + VIDIOC_SUBDEV_S_FRAME_INTERVAL, + &interval) == -1) { + errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); + return false; + } - bool did_set_frame_rate = interval.interval.numerator == - mode->frame_interval.numerator && - interval.interval.denominator == - mode->frame_interval.denominator; + bool did_set_frame_rate = interval.interval.numerator == + mode->frame_interval.numerator && + interval.interval.denominator == + mode->frame_interval.denominator; - struct v4l2_subdev_format fmt = {}; - fmt.pad = 0; - fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - fmt.format.width = mode->width; - fmt.format.height = mode->height; - fmt.format.code = - mp_pixel_format_to_v4l_bus_code(mode->pixel_format); - fmt.format.field = V4L2_FIELD_ANY; - if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) { - errno_printerr("VIDIOC_SUBDEV_S_FMT"); - return false; - } + struct v4l2_subdev_format fmt = {}; + fmt.pad = 0; + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + fmt.format.width = mode->width; + fmt.format.height = mode->height; + fmt.format.code = + mp_pixel_format_to_v4l_bus_code(mode->pixel_format); + fmt.format.field = V4L2_FIELD_ANY; + if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) { + errno_printerr("VIDIOC_SUBDEV_S_FMT"); + return false; + } - // Some drivers like ov5640 don't allow you to set the frame format with - // too high a frame-rate, but that means the frame-rate won't be set - // after the format change. So we need to try again here if we didn't - // succeed before. Ideally we'd be able to set both at once. - if (!did_set_frame_rate) { - interval.interval = mode->frame_interval; - if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, - &interval) == -1) { - errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); - } - } + // Some drivers like ov5640 don't allow you to set the frame format + // with too high a frame-rate, but that means the frame-rate won't be + // set after the format change. So we need to try again here if we + // didn't succeed before. Ideally we'd be able to set both at once. + if (!did_set_frame_rate) { + interval.interval = mode->frame_interval; + if (xioctl(camera->subdev_fd, + VIDIOC_SUBDEV_S_FRAME_INTERVAL, + &interval) == -1) { + errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); + } + } - // Update the mode - mode->pixel_format = - mp_pixel_format_from_v4l_bus_code(fmt.format.code); - mode->frame_interval = interval.interval; - mode->width = fmt.format.width; - mode->height = fmt.format.height; - } + // Update the mode + mode->pixel_format = + mp_pixel_format_from_v4l_bus_code(fmt.format.code); + mode->frame_interval = interval.interval; + mode->width = fmt.format.width; + mode->height = fmt.format.height; + } - // Set the mode for the video device - { - if (!camera_mode_impl(camera, VIDIOC_S_FMT, mode)) { - errno_printerr("VIDIOC_S_FMT"); - return false; - } - } + // Set the mode for the video device + { + if (!camera_mode_impl(camera, VIDIOC_S_FMT, mode)) { + errno_printerr("VIDIOC_S_FMT"); + return false; + } + } - camera->has_set_mode = true; - camera->current_mode = *mode; + camera->has_set_mode = true; + camera->current_mode = *mode; - return true; + return true; } bool mp_camera_start_capture(MPCamera *camera) { - g_return_val_if_fail(camera->has_set_mode, false); - g_return_val_if_fail(camera->num_buffers == 0, false); + g_return_val_if_fail(camera->has_set_mode, false); + g_return_val_if_fail(camera->num_buffers == 0, false); - enum v4l2_buf_type buftype = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (camera->use_mplane) { - buftype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - } + enum v4l2_buf_type buftype = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (camera->use_mplane) { + buftype = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + } - // Start by requesting buffers - struct v4l2_requestbuffers req = {}; - req.count = MAX_VIDEO_BUFFERS; - req.type = buftype; - req.memory = V4L2_MEMORY_MMAP; + // Start by requesting buffers + struct v4l2_requestbuffers req = {}; + req.count = MAX_VIDEO_BUFFERS; + req.type = buftype; + req.memory = V4L2_MEMORY_MMAP; - if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { - errno_printerr("VIDIOC_REQBUFS"); - return false; - } + if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { + errno_printerr("VIDIOC_REQBUFS"); + return false; + } - if (req.count < 2) { - g_printerr( - "Insufficient buffer memory. Only %d buffers available.\n", - req.count); - goto error; - } + if (req.count < 2) { + g_printerr( + "Insufficient buffer memory. Only %d buffers available.\n", + req.count); + goto error; + } - for (uint32_t i = 0; i < req.count; ++i) { - // Query each buffer and mmap it - struct v4l2_buffer buf = { - .type = buftype, - .memory = V4L2_MEMORY_MMAP, - .index = i, - }; + for (uint32_t i = 0; i < req.count; ++i) { + // Query each buffer and mmap it + struct v4l2_buffer buf = { + .type = buftype, + .memory = V4L2_MEMORY_MMAP, + .index = i, + }; - struct v4l2_plane planes[1]; - if (camera->use_mplane) { - buf.m.planes = planes; - buf.length = 1; - } + struct v4l2_plane planes[1]; + if (camera->use_mplane) { + buf.m.planes = planes; + buf.length = 1; + } - if (xioctl(camera->video_fd, VIDIOC_QUERYBUF, &buf) == -1) { - errno_printerr("VIDIOC_QUERYBUF"); - break; - } + if (xioctl(camera->video_fd, VIDIOC_QUERYBUF, &buf) == -1) { + errno_printerr("VIDIOC_QUERYBUF"); + break; + } - if (camera->use_mplane) { - camera->buffers[i].length = planes[0].length; - camera->buffers[i].data = - mmap(NULL, planes[0].length, PROT_READ, MAP_SHARED, - camera->video_fd, planes[0].m.mem_offset); - } else { - camera->buffers[i].length = buf.length; - camera->buffers[i].data = - mmap(NULL, buf.length, PROT_READ, MAP_SHARED, - camera->video_fd, buf.m.offset); - } + if (camera->use_mplane) { + camera->buffers[i].length = planes[0].length; + camera->buffers[i].data = mmap(NULL, + planes[0].length, + PROT_READ, + MAP_SHARED, + camera->video_fd, + planes[0].m.mem_offset); + } else { + camera->buffers[i].length = buf.length; + camera->buffers[i].data = mmap(NULL, + buf.length, + PROT_READ, + MAP_SHARED, + camera->video_fd, + buf.m.offset); + } - if (camera->buffers[i].data == MAP_FAILED) { - errno_printerr("mmap"); - break; - } + if (camera->buffers[i].data == MAP_FAILED) { + errno_printerr("mmap"); + break; + } - struct v4l2_exportbuffer expbuf = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .index = i, - }; - if (xioctl(camera->video_fd, VIDIOC_EXPBUF, &expbuf) == -1) { - errno_printerr("VIDIOC_EXPBUF"); - break; - } + struct v4l2_exportbuffer expbuf = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .index = i, + }; + if (xioctl(camera->video_fd, VIDIOC_EXPBUF, &expbuf) == -1) { + errno_printerr("VIDIOC_EXPBUF"); + break; + } - camera->buffers[i].fd = expbuf.fd; + camera->buffers[i].fd = expbuf.fd; - ++camera->num_buffers; - } + ++camera->num_buffers; + } - if (camera->num_buffers != req.count) { - g_printerr("Unable to map all buffers\n"); - goto error; - } + if (camera->num_buffers != req.count) { + g_printerr("Unable to map all buffers\n"); + goto error; + } - for (uint32_t i = 0; i < camera->num_buffers; ++i) { - struct v4l2_buffer buf = { - .type = buftype, - .memory = V4L2_MEMORY_MMAP, - .index = i, - }; + for (uint32_t i = 0; i < camera->num_buffers; ++i) { + struct v4l2_buffer buf = { + .type = buftype, + .memory = V4L2_MEMORY_MMAP, + .index = i, + }; - struct v4l2_plane planes[1]; - if (camera->use_mplane) { - buf.m.planes = planes; - buf.length = 1; - } + struct v4l2_plane planes[1]; + if (camera->use_mplane) { + buf.m.planes = planes; + buf.length = 1; + } - // Queue the buffer for capture - if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { - errno_printerr("VIDIOC_QBUF"); - goto error; - } - } + // Queue the buffer for capture + if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { + errno_printerr("VIDIOC_QBUF"); + goto error; + } + } - // Start capture - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(camera->video_fd, VIDIOC_STREAMON, &type) == -1) { - errno_printerr("VIDIOC_STREAMON"); - goto error; - } + // Start capture + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(camera->video_fd, VIDIOC_STREAMON, &type) == -1) { + errno_printerr("VIDIOC_STREAMON"); + goto error; + } - return true; + return true; error: - // Unmap any mapped buffers - assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); - for (uint32_t i = 0; i < camera->num_buffers; ++i) { - if (munmap(camera->buffers[i].data, camera->buffers[i].length) == - -1) { - errno_printerr("munmap"); - } + // Unmap any mapped buffers + assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); + for (uint32_t i = 0; i < camera->num_buffers; ++i) { + if (munmap(camera->buffers[i].data, camera->buffers[i].length) == + -1) { + errno_printerr("munmap"); + } - if (close(camera->buffers[i].fd) == -1) { - errno_printerr("close"); - } - } + if (close(camera->buffers[i].fd) == -1) { + errno_printerr("close"); + } + } - // Reset allocated buffers - { - struct v4l2_requestbuffers req = {}; - req.count = 0; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; + // Reset allocated buffers + { + struct v4l2_requestbuffers req = {}; + req.count = 0; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; - if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { - errno_printerr("VIDIOC_REQBUFS"); - } - } + if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { + errno_printerr("VIDIOC_REQBUFS"); + } + } - return false; + return false; } bool mp_camera_stop_capture(MPCamera *camera) { - g_return_val_if_fail(camera->num_buffers > 0, false); + g_return_val_if_fail(camera->num_buffers > 0, false); - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(camera->video_fd, VIDIOC_STREAMOFF, &type) == -1) { - errno_printerr("VIDIOC_STREAMOFF"); - } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(camera->video_fd, VIDIOC_STREAMOFF, &type) == -1) { + errno_printerr("VIDIOC_STREAMOFF"); + } - assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); - for (int i = 0; i < camera->num_buffers; ++i) { - if (munmap(camera->buffers[i].data, camera->buffers[i].length) == - -1) { - errno_printerr("munmap"); - } + assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); + for (int i = 0; i < camera->num_buffers; ++i) { + if (munmap(camera->buffers[i].data, camera->buffers[i].length) == + -1) { + errno_printerr("munmap"); + } - if (close(camera->buffers[i].fd) == -1) { - errno_printerr("close"); - } - } + if (close(camera->buffers[i].fd) == -1) { + errno_printerr("close"); + } + } - camera->num_buffers = 0; + camera->num_buffers = 0; - struct v4l2_requestbuffers req = {}; - req.count = 0; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { - errno_printerr("VIDIOC_REQBUFS"); - } + struct v4l2_requestbuffers req = {}; + req.count = 0; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if (xioctl(camera->video_fd, VIDIOC_REQBUFS, &req) == -1) { + errno_printerr("VIDIOC_REQBUFS"); + } - return true; + return true; } bool mp_camera_is_capturing(MPCamera *camera) { - return camera->num_buffers > 0; + return camera->num_buffers > 0; } bool mp_camera_capture_buffer(MPCamera *camera, MPBuffer *buffer) { - struct v4l2_buffer buf = {}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; + struct v4l2_buffer buf = {}; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; - struct v4l2_plane planes[1]; - if (camera->use_mplane) { - buf.m.planes = planes; - buf.length = 1; - } + struct v4l2_plane planes[1]; + if (camera->use_mplane) { + buf.m.planes = planes; + buf.length = 1; + } - if (xioctl(camera->video_fd, VIDIOC_DQBUF, &buf) == -1) { - switch (errno) { - case EAGAIN: - return true; - case EIO: - /* Could ignore EIO, see spec. */ - /* fallthrough */ - default: - errno_printerr("VIDIOC_DQBUF"); - exit(1); - return false; - } - } + if (xioctl(camera->video_fd, VIDIOC_DQBUF, &buf) == -1) { + switch (errno) { + case EAGAIN: + return true; + case EIO: + /* Could ignore EIO, see spec. */ + /* fallthrough */ + default: + errno_printerr("VIDIOC_DQBUF"); + exit(1); + return false; + } + } - uint32_t pixel_format = camera->current_mode.pixel_format; - uint32_t width = camera->current_mode.width; - uint32_t height = camera->current_mode.height; + uint32_t pixel_format = camera->current_mode.pixel_format; + uint32_t width = camera->current_mode.width; + uint32_t height = camera->current_mode.height; - uint32_t bytesused; - if (camera->use_mplane) { - bytesused = planes[0].bytesused; - } else { - bytesused = buf.bytesused; - } + uint32_t bytesused; + if (camera->use_mplane) { + bytesused = planes[0].bytesused; + } else { + bytesused = buf.bytesused; + } - assert(bytesused == - mp_pixel_format_width_to_bytes(pixel_format, width) * height); - assert(bytesused == camera->buffers[buf.index].length); + assert(bytesused == + mp_pixel_format_width_to_bytes(pixel_format, width) * height); + assert(bytesused == camera->buffers[buf.index].length); - buffer->index = buf.index; - buffer->data = camera->buffers[buf.index].data; - buffer->fd = camera->buffers[buf.index].fd; + buffer->index = buf.index; + buffer->data = camera->buffers[buf.index].data; + buffer->fd = camera->buffers[buf.index].fd; - return true; + return true; } bool mp_camera_release_buffer(MPCamera *camera, uint32_t buffer_index) { - struct v4l2_buffer buf = {}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = buffer_index; - if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { - errno_printerr("VIDIOC_QBUF"); - return false; - } - return true; + struct v4l2_buffer buf = {}; + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buffer_index; + if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { + errno_printerr("VIDIOC_QBUF"); + return false; + } + return true; } struct _MPCameraModeList { - MPCameraMode mode; - MPCameraModeList *next; + MPCameraMode mode; + MPCameraModeList *next; }; static MPCameraModeList * get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *)) { - MPCameraModeList *item = NULL; + MPCameraModeList *item = NULL; - for (uint32_t fmt_index = 0;; ++fmt_index) { - struct v4l2_subdev_mbus_code_enum fmt = {}; - fmt.index = fmt_index; - fmt.pad = 0; - fmt.which = V4L2_SUBDEV_FORMAT_TRY; - if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) == - -1) { - if (errno != EINVAL) { - errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE"); - } - break; - } + for (uint32_t fmt_index = 0;; ++fmt_index) { + struct v4l2_subdev_mbus_code_enum fmt = {}; + fmt.index = fmt_index; + fmt.pad = 0; + fmt.which = V4L2_SUBDEV_FORMAT_TRY; + if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) == + -1) { + if (errno != EINVAL) { + errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE"); + } + break; + } - // Skip unsupported formats - uint32_t format = mp_pixel_format_from_v4l_bus_code(fmt.code); - if (format == MP_PIXEL_FMT_UNSUPPORTED) { - continue; - } + // Skip unsupported formats + uint32_t format = mp_pixel_format_from_v4l_bus_code(fmt.code); + if (format == MP_PIXEL_FMT_UNSUPPORTED) { + continue; + } - for (uint32_t frame_index = 0;; ++frame_index) { - struct v4l2_subdev_frame_size_enum frame = {}; - frame.index = frame_index; - frame.pad = 0; - frame.code = fmt.code; - frame.which = V4L2_SUBDEV_FORMAT_TRY; - if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, - &frame) == -1) { - if (errno != EINVAL) { - errno_printerr( - "VIDIOC_SUBDEV_ENUM_FRAME_SIZE"); - } - break; - } + for (uint32_t frame_index = 0;; ++frame_index) { + struct v4l2_subdev_frame_size_enum frame = {}; + frame.index = frame_index; + frame.pad = 0; + frame.code = fmt.code; + frame.which = V4L2_SUBDEV_FORMAT_TRY; + if (xioctl(camera->subdev_fd, + VIDIOC_SUBDEV_ENUM_FRAME_SIZE, + &frame) == -1) { + if (errno != EINVAL) { + errno_printerr( + "VIDIOC_SUBDEV_ENUM_FRAME_SIZE"); + } + break; + } - // TODO: Handle other types - if (frame.min_width != frame.max_width || - frame.min_height != frame.max_height) { - break; - } + // TODO: Handle other types + if (frame.min_width != frame.max_width || + frame.min_height != frame.max_height) { + break; + } - for (uint32_t interval_index = 0;; ++interval_index) { - struct v4l2_subdev_frame_interval_enum interval = {}; - interval.index = interval_index; - interval.pad = 0; - interval.code = fmt.code; - interval.width = frame.max_width; - interval.height = frame.max_height; - interval.which = V4L2_SUBDEV_FORMAT_TRY; - if (xioctl(camera->subdev_fd, - VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, - &interval) == -1) { - if (errno != EINVAL) { - errno_printerr( - "VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL"); - } - break; - } + for (uint32_t interval_index = 0;; ++interval_index) { + struct v4l2_subdev_frame_interval_enum interval = {}; + interval.index = interval_index; + interval.pad = 0; + interval.code = fmt.code; + interval.width = frame.max_width; + interval.height = frame.max_height; + interval.which = V4L2_SUBDEV_FORMAT_TRY; + if (xioctl(camera->subdev_fd, + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, + &interval) == -1) { + if (errno != EINVAL) { + errno_printerr( + "VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL"); + } + break; + } - MPCameraMode mode = { - .pixel_format = format, - .frame_interval = interval.interval, - .width = frame.max_width, - .height = frame.max_height, - }; + MPCameraMode mode = { + .pixel_format = format, + .frame_interval = interval.interval, + .width = frame.max_width, + .height = frame.max_height, + }; - if (!check(camera, &mode)) { - continue; - } + if (!check(camera, &mode)) { + continue; + } - MPCameraModeList *new_item = - malloc(sizeof(MPCameraModeList)); - new_item->mode = mode; - new_item->next = item; - item = new_item; - } - } - } + MPCameraModeList *new_item = + malloc(sizeof(MPCameraModeList)); + new_item->mode = mode; + new_item->next = item; + item = new_item; + } + } + } - return item; + return item; } static MPCameraModeList * get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *)) { - MPCameraModeList *item = NULL; + MPCameraModeList *item = NULL; - for (uint32_t fmt_index = 0;; ++fmt_index) { - struct v4l2_fmtdesc fmt = {}; - fmt.index = fmt_index; - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(camera->video_fd, VIDIOC_ENUM_FMT, &fmt) == -1) { - if (errno != EINVAL) { - errno_printerr("VIDIOC_ENUM_FMT"); - } - break; - } + for (uint32_t fmt_index = 0;; ++fmt_index) { + struct v4l2_fmtdesc fmt = {}; + fmt.index = fmt_index; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(camera->video_fd, VIDIOC_ENUM_FMT, &fmt) == -1) { + if (errno != EINVAL) { + errno_printerr("VIDIOC_ENUM_FMT"); + } + break; + } - // Skip unsupported formats - uint32_t format = - mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat); - if (format == MP_PIXEL_FMT_UNSUPPORTED) { - continue; - } + // Skip unsupported formats + uint32_t format = + mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat); + if (format == MP_PIXEL_FMT_UNSUPPORTED) { + continue; + } - for (uint32_t frame_index = 0;; ++frame_index) { - struct v4l2_frmsizeenum frame = {}; - frame.index = frame_index; - frame.pixel_format = fmt.pixelformat; - if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMESIZES, - &frame) == -1) { - if (errno != EINVAL) { - errno_printerr("VIDIOC_ENUM_FRAMESIZES"); - } - break; - } + for (uint32_t frame_index = 0;; ++frame_index) { + struct v4l2_frmsizeenum frame = {}; + frame.index = frame_index; + frame.pixel_format = fmt.pixelformat; + if (xioctl(camera->video_fd, + VIDIOC_ENUM_FRAMESIZES, + &frame) == -1) { + if (errno != EINVAL) { + errno_printerr("VIDIOC_ENUM_FRAMESIZES"); + } + break; + } - // TODO: Handle other types - if (frame.type != V4L2_FRMSIZE_TYPE_DISCRETE) { - break; - } + // TODO: Handle other types + if (frame.type != V4L2_FRMSIZE_TYPE_DISCRETE) { + break; + } - for (uint32_t interval_index = 0;; ++interval_index) { - struct v4l2_frmivalenum interval = {}; - interval.index = interval_index; - interval.pixel_format = fmt.pixelformat; - interval.width = frame.discrete.width; - interval.height = frame.discrete.height; - if (xioctl(camera->video_fd, - VIDIOC_ENUM_FRAMEINTERVALS, - &interval) == -1) { - if (errno != EINVAL) { - errno_printerr( - "VIDIOC_ENUM_FRAMESIZES"); - } - break; - } + for (uint32_t interval_index = 0;; ++interval_index) { + struct v4l2_frmivalenum interval = {}; + interval.index = interval_index; + interval.pixel_format = fmt.pixelformat; + interval.width = frame.discrete.width; + interval.height = frame.discrete.height; + if (xioctl(camera->video_fd, + VIDIOC_ENUM_FRAMEINTERVALS, + &interval) == -1) { + if (errno != EINVAL) { + errno_printerr( + "VIDIOC_ENUM_FRAMESIZES"); + } + break; + } - // TODO: Handle other types - if (interval.type != V4L2_FRMIVAL_TYPE_DISCRETE) { - break; - } + // TODO: Handle other types + if (interval.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + break; + } - MPCameraMode mode = { - .pixel_format = format, - .frame_interval = interval.discrete, - .width = frame.discrete.width, - .height = frame.discrete.height, - }; + MPCameraMode mode = { + .pixel_format = format, + .frame_interval = interval.discrete, + .width = frame.discrete.width, + .height = frame.discrete.height, + }; - if (!check(camera, &mode)) { - continue; - } + if (!check(camera, &mode)) { + continue; + } - MPCameraModeList *new_item = - malloc(sizeof(MPCameraModeList)); - new_item->mode = mode; - new_item->next = item; - item = new_item; - } - } - } + MPCameraModeList *new_item = + malloc(sizeof(MPCameraModeList)); + new_item->mode = mode; + new_item->next = item; + item = new_item; + } + } + } - return item; + return item; } static bool all_modes(MPCamera *camera, MPCameraMode *mode) { - return true; + return true; } static bool available_modes(MPCamera *camera, MPCameraMode *mode) { - MPCameraMode attempt = *mode; - return mp_camera_try_mode(camera, &attempt) && - mp_camera_mode_is_equivalent(mode, &attempt); + MPCameraMode attempt = *mode; + return mp_camera_try_mode(camera, &attempt) && + mp_camera_mode_is_equivalent(mode, &attempt); } MPCameraModeList * mp_camera_list_supported_modes(MPCamera *camera) { - if (mp_camera_is_subdev(camera)) { - return get_subdev_modes(camera, all_modes); - } else { - return get_video_modes(camera, all_modes); - } + if (mp_camera_is_subdev(camera)) { + return get_subdev_modes(camera, all_modes); + } else { + return get_video_modes(camera, all_modes); + } } MPCameraModeList * mp_camera_list_available_modes(MPCamera *camera) { - if (mp_camera_is_subdev(camera)) { - return get_subdev_modes(camera, available_modes); - } else { - return get_video_modes(camera, available_modes); - } + if (mp_camera_is_subdev(camera)) { + return get_subdev_modes(camera, available_modes); + } else { + return get_video_modes(camera, available_modes); + } } MPCameraMode * mp_camera_mode_list_get(MPCameraModeList *list) { - g_return_val_if_fail(list, NULL); - return &list->mode; + g_return_val_if_fail(list, NULL); + return &list->mode; } MPCameraModeList * mp_camera_mode_list_next(MPCameraModeList *list) { - g_return_val_if_fail(list, NULL); - return list->next; + g_return_val_if_fail(list, NULL); + return list->next; } void mp_camera_mode_list_free(MPCameraModeList *list) { - while (list) { - MPCameraModeList *tmp = list; - list = tmp->next; - free(tmp); - } + while (list) { + MPCameraModeList *tmp = list; + list = tmp->next; + free(tmp); + } } struct int_str_pair { - uint32_t value; - const char *str; + uint32_t value; + const char *str; }; struct int_str_pair control_id_names[] = { - { V4L2_CID_BRIGHTNESS, "BRIGHTNESS" }, - { V4L2_CID_CONTRAST, "CONTRAST" }, - { V4L2_CID_SATURATION, "SATURATION" }, - { V4L2_CID_HUE, "HUE" }, - { V4L2_CID_AUDIO_VOLUME, "AUDIO_VOLUME" }, - { V4L2_CID_AUDIO_BALANCE, "AUDIO_BALANCE" }, - { V4L2_CID_AUDIO_BASS, "AUDIO_BASS" }, - { V4L2_CID_AUDIO_TREBLE, "AUDIO_TREBLE" }, - { V4L2_CID_AUDIO_MUTE, "AUDIO_MUTE" }, - { V4L2_CID_AUDIO_LOUDNESS, "AUDIO_LOUDNESS" }, - { V4L2_CID_BLACK_LEVEL, "BLACK_LEVEL" }, - { V4L2_CID_AUTO_WHITE_BALANCE, "AUTO_WHITE_BALANCE" }, - { V4L2_CID_DO_WHITE_BALANCE, "DO_WHITE_BALANCE" }, - { V4L2_CID_RED_BALANCE, "RED_BALANCE" }, - { V4L2_CID_BLUE_BALANCE, "BLUE_BALANCE" }, - { V4L2_CID_GAMMA, "GAMMA" }, - { V4L2_CID_WHITENESS, "WHITENESS" }, - { V4L2_CID_EXPOSURE, "EXPOSURE" }, - { V4L2_CID_AUTOGAIN, "AUTOGAIN" }, - { V4L2_CID_GAIN, "GAIN" }, - { V4L2_CID_HFLIP, "HFLIP" }, - { V4L2_CID_VFLIP, "VFLIP" }, - { V4L2_CID_POWER_LINE_FREQUENCY, "POWER_LINE_FREQUENCY" }, - { V4L2_CID_HUE_AUTO, "HUE_AUTO" }, - { V4L2_CID_WHITE_BALANCE_TEMPERATURE, "WHITE_BALANCE_TEMPERATURE" }, - { V4L2_CID_SHARPNESS, "SHARPNESS" }, - { V4L2_CID_BACKLIGHT_COMPENSATION, "BACKLIGHT_COMPENSATION" }, - { V4L2_CID_CHROMA_AGC, "CHROMA_AGC" }, - { V4L2_CID_COLOR_KILLER, "COLOR_KILLER" }, - { V4L2_CID_COLORFX, "COLORFX" }, - { V4L2_CID_AUTOBRIGHTNESS, "AUTOBRIGHTNESS" }, - { V4L2_CID_BAND_STOP_FILTER, "BAND_STOP_FILTER" }, - { V4L2_CID_ROTATE, "ROTATE" }, - { V4L2_CID_BG_COLOR, "BG_COLOR" }, - { V4L2_CID_CHROMA_GAIN, "CHROMA_GAIN" }, - { V4L2_CID_ILLUMINATORS_1, "ILLUMINATORS_1" }, - { V4L2_CID_ILLUMINATORS_2, "ILLUMINATORS_2" }, - { V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, "MIN_BUFFERS_FOR_CAPTURE" }, - { V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, "MIN_BUFFERS_FOR_OUTPUT" }, - { V4L2_CID_ALPHA_COMPONENT, "ALPHA_COMPONENT" }, - { V4L2_CID_COLORFX_CBCR, "COLORFX_CBCR" }, - { V4L2_CID_LASTP1, "LASTP1" }, - { V4L2_CID_USER_MEYE_BASE, "USER_MEYE_BASE" }, - { V4L2_CID_USER_BTTV_BASE, "USER_BTTV_BASE" }, - { V4L2_CID_USER_S2255_BASE, "USER_S2255_BASE" }, - { V4L2_CID_USER_SI476X_BASE, "USER_SI476X_BASE" }, - { V4L2_CID_USER_TI_VPE_BASE, "USER_TI_VPE_BASE" }, - { V4L2_CID_USER_SAA7134_BASE, "USER_SAA7134_BASE" }, - { V4L2_CID_USER_ADV7180_BASE, "USER_ADV7180_BASE" }, - { V4L2_CID_USER_TC358743_BASE, "USER_TC358743_BASE" }, - { V4L2_CID_USER_MAX217X_BASE, "USER_MAX217X_BASE" }, - { V4L2_CID_USER_IMX_BASE, "USER_IMX_BASE" }, - // { V4L2_CID_USER_ATMEL_ISC_BASE, "USER_ATMEL_ISC_BASE" }, - { V4L2_CID_CAMERA_CLASS_BASE, "CAMERA_CLASS_BASE" }, - { V4L2_CID_CAMERA_CLASS, "CAMERA_CLASS" }, - { V4L2_CID_EXPOSURE_AUTO, "EXPOSURE_AUTO" }, - { V4L2_CID_EXPOSURE_ABSOLUTE, "EXPOSURE_ABSOLUTE" }, - { V4L2_CID_EXPOSURE_AUTO_PRIORITY, "EXPOSURE_AUTO_PRIORITY" }, - { V4L2_CID_PAN_RELATIVE, "PAN_RELATIVE" }, - { V4L2_CID_TILT_RELATIVE, "TILT_RELATIVE" }, - { V4L2_CID_PAN_RESET, "PAN_RESET" }, - { V4L2_CID_TILT_RESET, "TILT_RESET" }, - { V4L2_CID_PAN_ABSOLUTE, "PAN_ABSOLUTE" }, - { V4L2_CID_TILT_ABSOLUTE, "TILT_ABSOLUTE" }, - { V4L2_CID_FOCUS_ABSOLUTE, "FOCUS_ABSOLUTE" }, - { V4L2_CID_FOCUS_RELATIVE, "FOCUS_RELATIVE" }, - { V4L2_CID_FOCUS_AUTO, "FOCUS_AUTO" }, - { V4L2_CID_ZOOM_ABSOLUTE, "ZOOM_ABSOLUTE" }, - { V4L2_CID_ZOOM_RELATIVE, "ZOOM_RELATIVE" }, - { V4L2_CID_ZOOM_CONTINUOUS, "ZOOM_CONTINUOUS" }, - { V4L2_CID_PRIVACY, "PRIVACY" }, - { V4L2_CID_IRIS_ABSOLUTE, "IRIS_ABSOLUTE" }, - { V4L2_CID_IRIS_RELATIVE, "IRIS_RELATIVE" }, - { V4L2_CID_AUTO_EXPOSURE_BIAS, "AUTO_EXPOSURE_BIAS" }, - { V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, "AUTO_N_PRESET_WHITE_BALANCE" }, - { V4L2_CID_WIDE_DYNAMIC_RANGE, "WIDE_DYNAMIC_RANGE" }, - { V4L2_CID_IMAGE_STABILIZATION, "IMAGE_STABILIZATION" }, - { V4L2_CID_ISO_SENSITIVITY, "ISO_SENSITIVITY" }, - { V4L2_CID_ISO_SENSITIVITY_AUTO, "ISO_SENSITIVITY_AUTO" }, - { V4L2_CID_EXPOSURE_METERING, "EXPOSURE_METERING" }, - { V4L2_CID_SCENE_MODE, "SCENE_MODE" }, - { V4L2_CID_3A_LOCK, "3A_LOCK" }, - { V4L2_CID_AUTO_FOCUS_START, "AUTO_FOCUS_START" }, - { V4L2_CID_AUTO_FOCUS_STOP, "AUTO_FOCUS_STOP" }, - { V4L2_CID_AUTO_FOCUS_STATUS, "AUTO_FOCUS_STATUS" }, - { V4L2_CID_AUTO_FOCUS_RANGE, "AUTO_FOCUS_RANGE" }, - { V4L2_CID_PAN_SPEED, "PAN_SPEED" }, - { V4L2_CID_TILT_SPEED, "TILT_SPEED" }, - // { V4L2_CID_CAMERA_ORIENTATION, "CAMERA_ORIENTATION" }, - // { V4L2_CID_CAMERA_SENSOR_ROTATION, "CAMERA_SENSOR_ROTATION" }, - { V4L2_CID_FLASH_LED_MODE, "FLASH_LED_MODE" }, - { V4L2_CID_FLASH_STROBE_SOURCE, "FLASH_STROBE_SOURCE" }, - { V4L2_CID_FLASH_STROBE, "FLASH_STROBE" }, - { V4L2_CID_FLASH_STROBE_STOP, "FLASH_STROBE_STOP" }, - { V4L2_CID_FLASH_STROBE_STATUS, "FLASH_STROBE_STATUS" }, - { V4L2_CID_FLASH_TIMEOUT, "FLASH_TIMEOUT" }, - { V4L2_CID_FLASH_INTENSITY, "FLASH_INTENSITY" }, - { V4L2_CID_FLASH_TORCH_INTENSITY, "FLASH_TORCH_INTENSITY" }, - { V4L2_CID_FLASH_INDICATOR_INTENSITY, "FLASH_INDICATOR_INTENSITY" }, - { V4L2_CID_FLASH_FAULT, "FLASH_FAULT" }, - { V4L2_CID_FLASH_CHARGE, "FLASH_CHARGE" }, - { V4L2_CID_FLASH_READY, "FLASH_READY" }, + { V4L2_CID_BRIGHTNESS, "BRIGHTNESS" }, + { V4L2_CID_CONTRAST, "CONTRAST" }, + { V4L2_CID_SATURATION, "SATURATION" }, + { V4L2_CID_HUE, "HUE" }, + { V4L2_CID_AUDIO_VOLUME, "AUDIO_VOLUME" }, + { V4L2_CID_AUDIO_BALANCE, "AUDIO_BALANCE" }, + { V4L2_CID_AUDIO_BASS, "AUDIO_BASS" }, + { V4L2_CID_AUDIO_TREBLE, "AUDIO_TREBLE" }, + { V4L2_CID_AUDIO_MUTE, "AUDIO_MUTE" }, + { V4L2_CID_AUDIO_LOUDNESS, "AUDIO_LOUDNESS" }, + { V4L2_CID_BLACK_LEVEL, "BLACK_LEVEL" }, + { V4L2_CID_AUTO_WHITE_BALANCE, "AUTO_WHITE_BALANCE" }, + { V4L2_CID_DO_WHITE_BALANCE, "DO_WHITE_BALANCE" }, + { V4L2_CID_RED_BALANCE, "RED_BALANCE" }, + { V4L2_CID_BLUE_BALANCE, "BLUE_BALANCE" }, + { V4L2_CID_GAMMA, "GAMMA" }, + { V4L2_CID_WHITENESS, "WHITENESS" }, + { V4L2_CID_EXPOSURE, "EXPOSURE" }, + { V4L2_CID_AUTOGAIN, "AUTOGAIN" }, + { V4L2_CID_GAIN, "GAIN" }, + { V4L2_CID_HFLIP, "HFLIP" }, + { V4L2_CID_VFLIP, "VFLIP" }, + { V4L2_CID_POWER_LINE_FREQUENCY, "POWER_LINE_FREQUENCY" }, + { V4L2_CID_HUE_AUTO, "HUE_AUTO" }, + { V4L2_CID_WHITE_BALANCE_TEMPERATURE, "WHITE_BALANCE_TEMPERATURE" }, + { V4L2_CID_SHARPNESS, "SHARPNESS" }, + { V4L2_CID_BACKLIGHT_COMPENSATION, "BACKLIGHT_COMPENSATION" }, + { V4L2_CID_CHROMA_AGC, "CHROMA_AGC" }, + { V4L2_CID_COLOR_KILLER, "COLOR_KILLER" }, + { V4L2_CID_COLORFX, "COLORFX" }, + { V4L2_CID_AUTOBRIGHTNESS, "AUTOBRIGHTNESS" }, + { V4L2_CID_BAND_STOP_FILTER, "BAND_STOP_FILTER" }, + { V4L2_CID_ROTATE, "ROTATE" }, + { V4L2_CID_BG_COLOR, "BG_COLOR" }, + { V4L2_CID_CHROMA_GAIN, "CHROMA_GAIN" }, + { V4L2_CID_ILLUMINATORS_1, "ILLUMINATORS_1" }, + { V4L2_CID_ILLUMINATORS_2, "ILLUMINATORS_2" }, + { V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, "MIN_BUFFERS_FOR_CAPTURE" }, + { V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, "MIN_BUFFERS_FOR_OUTPUT" }, + { V4L2_CID_ALPHA_COMPONENT, "ALPHA_COMPONENT" }, + { V4L2_CID_COLORFX_CBCR, "COLORFX_CBCR" }, + { V4L2_CID_LASTP1, "LASTP1" }, + { V4L2_CID_USER_MEYE_BASE, "USER_MEYE_BASE" }, + { V4L2_CID_USER_BTTV_BASE, "USER_BTTV_BASE" }, + { V4L2_CID_USER_S2255_BASE, "USER_S2255_BASE" }, + { V4L2_CID_USER_SI476X_BASE, "USER_SI476X_BASE" }, + { V4L2_CID_USER_TI_VPE_BASE, "USER_TI_VPE_BASE" }, + { V4L2_CID_USER_SAA7134_BASE, "USER_SAA7134_BASE" }, + { V4L2_CID_USER_ADV7180_BASE, "USER_ADV7180_BASE" }, + { V4L2_CID_USER_TC358743_BASE, "USER_TC358743_BASE" }, + { V4L2_CID_USER_MAX217X_BASE, "USER_MAX217X_BASE" }, + { V4L2_CID_USER_IMX_BASE, "USER_IMX_BASE" }, + // { V4L2_CID_USER_ATMEL_ISC_BASE, "USER_ATMEL_ISC_BASE" }, + { V4L2_CID_CAMERA_CLASS_BASE, "CAMERA_CLASS_BASE" }, + { V4L2_CID_CAMERA_CLASS, "CAMERA_CLASS" }, + { V4L2_CID_EXPOSURE_AUTO, "EXPOSURE_AUTO" }, + { V4L2_CID_EXPOSURE_ABSOLUTE, "EXPOSURE_ABSOLUTE" }, + { V4L2_CID_EXPOSURE_AUTO_PRIORITY, "EXPOSURE_AUTO_PRIORITY" }, + { V4L2_CID_PAN_RELATIVE, "PAN_RELATIVE" }, + { V4L2_CID_TILT_RELATIVE, "TILT_RELATIVE" }, + { V4L2_CID_PAN_RESET, "PAN_RESET" }, + { V4L2_CID_TILT_RESET, "TILT_RESET" }, + { V4L2_CID_PAN_ABSOLUTE, "PAN_ABSOLUTE" }, + { V4L2_CID_TILT_ABSOLUTE, "TILT_ABSOLUTE" }, + { V4L2_CID_FOCUS_ABSOLUTE, "FOCUS_ABSOLUTE" }, + { V4L2_CID_FOCUS_RELATIVE, "FOCUS_RELATIVE" }, + { V4L2_CID_FOCUS_AUTO, "FOCUS_AUTO" }, + { V4L2_CID_ZOOM_ABSOLUTE, "ZOOM_ABSOLUTE" }, + { V4L2_CID_ZOOM_RELATIVE, "ZOOM_RELATIVE" }, + { V4L2_CID_ZOOM_CONTINUOUS, "ZOOM_CONTINUOUS" }, + { V4L2_CID_PRIVACY, "PRIVACY" }, + { V4L2_CID_IRIS_ABSOLUTE, "IRIS_ABSOLUTE" }, + { V4L2_CID_IRIS_RELATIVE, "IRIS_RELATIVE" }, + { V4L2_CID_AUTO_EXPOSURE_BIAS, "AUTO_EXPOSURE_BIAS" }, + { V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, "AUTO_N_PRESET_WHITE_BALANCE" }, + { V4L2_CID_WIDE_DYNAMIC_RANGE, "WIDE_DYNAMIC_RANGE" }, + { V4L2_CID_IMAGE_STABILIZATION, "IMAGE_STABILIZATION" }, + { V4L2_CID_ISO_SENSITIVITY, "ISO_SENSITIVITY" }, + { V4L2_CID_ISO_SENSITIVITY_AUTO, "ISO_SENSITIVITY_AUTO" }, + { V4L2_CID_EXPOSURE_METERING, "EXPOSURE_METERING" }, + { V4L2_CID_SCENE_MODE, "SCENE_MODE" }, + { V4L2_CID_3A_LOCK, "3A_LOCK" }, + { V4L2_CID_AUTO_FOCUS_START, "AUTO_FOCUS_START" }, + { V4L2_CID_AUTO_FOCUS_STOP, "AUTO_FOCUS_STOP" }, + { V4L2_CID_AUTO_FOCUS_STATUS, "AUTO_FOCUS_STATUS" }, + { V4L2_CID_AUTO_FOCUS_RANGE, "AUTO_FOCUS_RANGE" }, + { V4L2_CID_PAN_SPEED, "PAN_SPEED" }, + { V4L2_CID_TILT_SPEED, "TILT_SPEED" }, + // { V4L2_CID_CAMERA_ORIENTATION, "CAMERA_ORIENTATION" }, + // { V4L2_CID_CAMERA_SENSOR_ROTATION, "CAMERA_SENSOR_ROTATION" }, + { V4L2_CID_FLASH_LED_MODE, "FLASH_LED_MODE" }, + { V4L2_CID_FLASH_STROBE_SOURCE, "FLASH_STROBE_SOURCE" }, + { V4L2_CID_FLASH_STROBE, "FLASH_STROBE" }, + { V4L2_CID_FLASH_STROBE_STOP, "FLASH_STROBE_STOP" }, + { V4L2_CID_FLASH_STROBE_STATUS, "FLASH_STROBE_STATUS" }, + { V4L2_CID_FLASH_TIMEOUT, "FLASH_TIMEOUT" }, + { V4L2_CID_FLASH_INTENSITY, "FLASH_INTENSITY" }, + { V4L2_CID_FLASH_TORCH_INTENSITY, "FLASH_TORCH_INTENSITY" }, + { V4L2_CID_FLASH_INDICATOR_INTENSITY, "FLASH_INDICATOR_INTENSITY" }, + { V4L2_CID_FLASH_FAULT, "FLASH_FAULT" }, + { V4L2_CID_FLASH_CHARGE, "FLASH_CHARGE" }, + { V4L2_CID_FLASH_READY, "FLASH_READY" }, }; const char * mp_control_id_to_str(uint32_t id) { - size_t size = sizeof(control_id_names) / sizeof(*control_id_names); + size_t size = sizeof(control_id_names) / sizeof(*control_id_names); - for (size_t i = 0; i < size; ++i) { - if (control_id_names[i].value == id) { - return control_id_names[i].str; - } - } + for (size_t i = 0; i < size; ++i) { + if (control_id_names[i].value == id) { + return control_id_names[i].str; + } + } - return "UNKNOWN"; + return "UNKNOWN"; } struct int_str_pair control_type_names[] = { - { V4L2_CTRL_TYPE_INTEGER, "INTEGER" }, - { V4L2_CTRL_TYPE_BOOLEAN, "BOOLEAN" }, - { V4L2_CTRL_TYPE_MENU, "MENU" }, - { V4L2_CTRL_TYPE_INTEGER_MENU, "INTEGER_MENU" }, - { V4L2_CTRL_TYPE_BITMASK, "BITMASK" }, - { V4L2_CTRL_TYPE_BUTTON, "BUTTON" }, - { V4L2_CTRL_TYPE_INTEGER64, "INTEGER64" }, - { V4L2_CTRL_TYPE_STRING, "STRING" }, - { V4L2_CTRL_TYPE_CTRL_CLASS, "CTRL_CLASS" }, - { V4L2_CTRL_TYPE_U8, "U8" }, - { V4L2_CTRL_TYPE_U16, "U16" }, - { V4L2_CTRL_TYPE_U32, "U32" }, - // { V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS, "MPEG2_SLICE_PARAMS" }, - // { V4L2_CTRL_TYPE_MPEG2_QUANTIZATION, "MPEG2_QUANTIZATION" }, - // { V4L2_CTRL_TYPE_AREA, "AREA" }, - // { V4L2_CTRL_TYPE_H264_SPS, "H264_SPS" }, - // { V4L2_CTRL_TYPE_H264_PPS, "H264_PPS" }, - // { V4L2_CTRL_TYPE_H264_SCALING_MATRIX, "H264_SCALING_MATRIX" }, - // { V4L2_CTRL_TYPE_H264_SLICE_PARAMS, "H264_SLICE_PARAMS" }, - // { V4L2_CTRL_TYPE_H264_DECODE_PARAMS, "H264_DECODE_PARAMS" }, - // { V4L2_CTRL_TYPE_HEVC_SPS, "HEVC_SPS" }, - // { V4L2_CTRL_TYPE_HEVC_PPS, "HEVC_PPS" }, - // { V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, "HEVC_SLICE_PARAMS" }, + { V4L2_CTRL_TYPE_INTEGER, "INTEGER" }, + { V4L2_CTRL_TYPE_BOOLEAN, "BOOLEAN" }, + { V4L2_CTRL_TYPE_MENU, "MENU" }, + { V4L2_CTRL_TYPE_INTEGER_MENU, "INTEGER_MENU" }, + { V4L2_CTRL_TYPE_BITMASK, "BITMASK" }, + { V4L2_CTRL_TYPE_BUTTON, "BUTTON" }, + { V4L2_CTRL_TYPE_INTEGER64, "INTEGER64" }, + { V4L2_CTRL_TYPE_STRING, "STRING" }, + { V4L2_CTRL_TYPE_CTRL_CLASS, "CTRL_CLASS" }, + { V4L2_CTRL_TYPE_U8, "U8" }, + { V4L2_CTRL_TYPE_U16, "U16" }, + { V4L2_CTRL_TYPE_U32, "U32" }, + // { V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS, "MPEG2_SLICE_PARAMS" }, + // { V4L2_CTRL_TYPE_MPEG2_QUANTIZATION, "MPEG2_QUANTIZATION" }, + // { V4L2_CTRL_TYPE_AREA, "AREA" }, + // { V4L2_CTRL_TYPE_H264_SPS, "H264_SPS" }, + // { V4L2_CTRL_TYPE_H264_PPS, "H264_PPS" }, + // { V4L2_CTRL_TYPE_H264_SCALING_MATRIX, "H264_SCALING_MATRIX" }, + // { V4L2_CTRL_TYPE_H264_SLICE_PARAMS, "H264_SLICE_PARAMS" }, + // { V4L2_CTRL_TYPE_H264_DECODE_PARAMS, "H264_DECODE_PARAMS" }, + // { V4L2_CTRL_TYPE_HEVC_SPS, "HEVC_SPS" }, + // { V4L2_CTRL_TYPE_HEVC_PPS, "HEVC_PPS" }, + // { V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, "HEVC_SLICE_PARAMS" }, }; const char * mp_control_type_to_str(uint32_t type) { - size_t size = sizeof(control_type_names) / sizeof(*control_type_names); + size_t size = sizeof(control_type_names) / sizeof(*control_type_names); - for (size_t i = 0; i < size; ++i) { - if (control_type_names[i].value == type) { - return control_type_names[i].str; - } - } + for (size_t i = 0; i < size; ++i) { + if (control_type_names[i].value == type) { + return control_type_names[i].str; + } + } - return "UNKNOWN"; + return "UNKNOWN"; } struct _MPControlList { - MPControl control; - MPControlList *next; + MPControl control; + MPControlList *next; }; static int control_fd(MPCamera *camera) { - if (camera->subdev_fd != -1) { - return camera->subdev_fd; - } - return camera->video_fd; + if (camera->subdev_fd != -1) { + return camera->subdev_fd; + } + return camera->video_fd; } MPControlList * mp_camera_list_controls(MPCamera *camera) { - MPControlList *item = NULL; + MPControlList *item = NULL; - struct v4l2_query_ext_ctrl ctrl = {}; - ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; - while (true) { - if (xioctl(control_fd(camera), VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) { - if (errno != EINVAL) { - errno_printerr("VIDIOC_QUERY_EXT_CTRL"); - } - break; - } + struct v4l2_query_ext_ctrl ctrl = {}; + ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; + while (true) { + if (xioctl(control_fd(camera), VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) { + if (errno != EINVAL) { + errno_printerr("VIDIOC_QUERY_EXT_CTRL"); + } + break; + } - MPControl control = { - .id = ctrl.id, - .type = ctrl.type, - .name = {}, - .min = ctrl.minimum, - .max = ctrl.maximum, - .step = ctrl.step, - .default_value = ctrl.default_value, - .flags = ctrl.flags, - .element_size = ctrl.elem_size, - .element_count = ctrl.elems, - .dimensions_count = ctrl.nr_of_dims, - .dimensions = {}, - }; + MPControl control = { + .id = ctrl.id, + .type = ctrl.type, + .name = {}, + .min = ctrl.minimum, + .max = ctrl.maximum, + .step = ctrl.step, + .default_value = ctrl.default_value, + .flags = ctrl.flags, + .element_size = ctrl.elem_size, + .element_count = ctrl.elems, + .dimensions_count = ctrl.nr_of_dims, + .dimensions = {}, + }; - strcpy(control.name, ctrl.name); - memcpy(control.dimensions, ctrl.dims, - sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); + strcpy(control.name, ctrl.name); + memcpy(control.dimensions, + ctrl.dims, + sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); - MPControlList *new_item = malloc(sizeof(MPControlList)); - new_item->control = control; - new_item->next = item; - item = new_item; + MPControlList *new_item = malloc(sizeof(MPControlList)); + new_item->control = control; + new_item->next = item; + item = new_item; - ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; - } + ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND; + } - return item; + return item; } MPControl * mp_control_list_get(MPControlList *list) { - g_return_val_if_fail(list, NULL); - return &list->control; + g_return_val_if_fail(list, NULL); + return &list->control; } MPControlList * mp_control_list_next(MPControlList *list) { - g_return_val_if_fail(list, NULL); - return list->next; + g_return_val_if_fail(list, NULL); + return list->next; } void mp_control_list_free(MPControlList *list) { - while (list) { - MPControlList *tmp = list; - list = tmp->next; - free(tmp); - } + while (list) { + MPControlList *tmp = list; + list = tmp->next; + free(tmp); + } } bool mp_camera_query_control(MPCamera *camera, uint32_t id, MPControl *control) { - struct v4l2_query_ext_ctrl ctrl = {}; - ctrl.id = id; - if (xioctl(control_fd(camera), VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) { - if (errno != EINVAL) { - errno_printerr("VIDIOC_QUERY_EXT_CTRL"); - } - return false; - } + struct v4l2_query_ext_ctrl ctrl = {}; + ctrl.id = id; + if (xioctl(control_fd(camera), VIDIOC_QUERY_EXT_CTRL, &ctrl) == -1) { + if (errno != EINVAL) { + errno_printerr("VIDIOC_QUERY_EXT_CTRL"); + } + return false; + } - if (control) { - control->id = ctrl.id; - control->type = ctrl.type; - strcpy(control->name, ctrl.name); - control->min = ctrl.minimum; - control->max = ctrl.maximum; - control->step = ctrl.step; - control->default_value = ctrl.default_value; - control->flags = ctrl.flags; - control->element_size = ctrl.elem_size; - control->element_count = ctrl.elems; - control->dimensions_count = ctrl.nr_of_dims; - memcpy(control->dimensions, ctrl.dims, - sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); - } - return true; + if (control) { + control->id = ctrl.id; + control->type = ctrl.type; + strcpy(control->name, ctrl.name); + control->min = ctrl.minimum; + control->max = ctrl.maximum; + control->step = ctrl.step; + control->default_value = ctrl.default_value; + control->flags = ctrl.flags; + control->element_size = ctrl.elem_size; + control->element_count = ctrl.elems; + control->dimensions_count = ctrl.nr_of_dims; + memcpy(control->dimensions, + ctrl.dims, + sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); + } + return true; } static bool control_impl_int32(MPCamera *camera, uint32_t id, int request, int32_t *value) { - struct v4l2_ext_control ctrl = {}; - ctrl.id = id; - ctrl.value = *value; + struct v4l2_ext_control ctrl = {}; + ctrl.id = id; + ctrl.value = *value; - struct v4l2_ext_controls ctrls = { - .ctrl_class = 0, - .which = V4L2_CTRL_WHICH_CUR_VAL, - .count = 1, - .controls = &ctrl, - }; - if (xioctl(control_fd(camera), request, &ctrls) == -1) { - return false; - } + struct v4l2_ext_controls ctrls = { + .ctrl_class = 0, + .which = V4L2_CTRL_WHICH_CUR_VAL, + .count = 1, + .controls = &ctrl, + }; + if (xioctl(control_fd(camera), request, &ctrls) == -1) { + return false; + } - *value = ctrl.value; - return true; + *value = ctrl.value; + return true; } pid_t mp_camera_control_set_int32_bg(MPCamera *camera, uint32_t id, int32_t v) { - struct v4l2_ext_control ctrl = {}; - ctrl.id = id; - ctrl.value = v; + struct v4l2_ext_control ctrl = {}; + ctrl.id = id; + ctrl.value = v; - struct v4l2_ext_controls ctrls = { - .ctrl_class = 0, - .which = V4L2_CTRL_WHICH_CUR_VAL, - .count = 1, - .controls = &ctrl, - }; + struct v4l2_ext_controls ctrls = { + .ctrl_class = 0, + .which = V4L2_CTRL_WHICH_CUR_VAL, + .count = 1, + .controls = &ctrl, + }; - int fd = control_fd(camera); + int fd = control_fd(camera); - // fork only after all the memory has been read - pid_t pid = fork(); - if (pid == -1) { - return 0; // discard errors, nothing to do in parent process - } else if (pid != 0) { - // parent process adding pid to wait list (to clear zombie processes) - mp_camera_add_bg_task(camera, pid); - return pid; - } + // fork only after all the memory has been read + pid_t pid = fork(); + if (pid == -1) { + return 0; // discard errors, nothing to do in parent process + } else if (pid != 0) { + // parent process adding pid to wait list (to clear zombie processes) + mp_camera_add_bg_task(camera, pid); + return pid; + } - // ignore errors - xioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls); - // exit without calling exit handlers - _exit(0); + // ignore errors + xioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls); + // exit without calling exit handlers + _exit(0); } bool mp_camera_control_try_int32(MPCamera *camera, uint32_t id, int32_t *v) { - return control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, v); + return control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, v); } bool mp_camera_control_set_int32(MPCamera *camera, uint32_t id, int32_t v) { - return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &v); + return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &v); } int32_t mp_camera_control_get_int32(MPCamera *camera, uint32_t id) { - int32_t v = 0; - control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); - return v; + int32_t v = 0; + control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); + return v; } bool mp_camera_control_try_boolean(MPCamera *camera, uint32_t id, bool *v) { - int32_t value = *v; - bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value); - *v = value; - return s; + int32_t value = *v; + bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value); + *v = value; + return s; } bool mp_camera_control_set_bool(MPCamera *camera, uint32_t id, bool v) { - int32_t value = v; - return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value); + int32_t value = v; + return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value); } bool mp_camera_control_get_bool(MPCamera *camera, uint32_t id) { - int32_t v = false; - control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); - return v; + int32_t v = false; + control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); + return v; } pid_t mp_camera_control_set_bool_bg(MPCamera *camera, uint32_t id, bool v) { - int32_t value = v; - return mp_camera_control_set_int32_bg(camera, id, value); + int32_t value = v; + return mp_camera_control_set_int32_bg(camera, id, value); } diff --git a/src/camera.h b/src/camera.h index c15b254..5b8dc12 100644 --- a/src/camera.h +++ b/src/camera.h @@ -1,24 +1,24 @@ #pragma once #include -#include #include #include +#include typedef enum { - MP_PIXEL_FMT_UNSUPPORTED, - MP_PIXEL_FMT_BGGR8, - MP_PIXEL_FMT_GBRG8, - MP_PIXEL_FMT_GRBG8, - MP_PIXEL_FMT_RGGB8, - MP_PIXEL_FMT_BGGR10P, - MP_PIXEL_FMT_GBRG10P, - MP_PIXEL_FMT_GRBG10P, - MP_PIXEL_FMT_RGGB10P, - MP_PIXEL_FMT_UYVY, - MP_PIXEL_FMT_YUYV, + MP_PIXEL_FMT_UNSUPPORTED, + MP_PIXEL_FMT_BGGR8, + MP_PIXEL_FMT_GBRG8, + MP_PIXEL_FMT_GRBG8, + MP_PIXEL_FMT_RGGB8, + MP_PIXEL_FMT_BGGR10P, + MP_PIXEL_FMT_GBRG10P, + MP_PIXEL_FMT_GRBG10P, + MP_PIXEL_FMT_RGGB10P, + MP_PIXEL_FMT_UYVY, + MP_PIXEL_FMT_YUYV, - MP_PIXEL_FMT_MAX, + MP_PIXEL_FMT_MAX, } MPPixelFormat; const char *mp_pixel_format_to_str(MPPixelFormat pixel_format); @@ -34,23 +34,23 @@ uint32_t mp_pixel_format_pixel_depth(MPPixelFormat pixel_format); uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t width); uint32_t mp_pixel_format_width_to_colors(MPPixelFormat pixel_format, uint32_t width); uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, - uint32_t height); + uint32_t height); typedef struct { - MPPixelFormat pixel_format; + MPPixelFormat pixel_format; - struct v4l2_fract frame_interval; - uint32_t width; - uint32_t height; + struct v4l2_fract frame_interval; + uint32_t width; + uint32_t height; } MPCameraMode; bool mp_camera_mode_is_equivalent(const MPCameraMode *m1, const MPCameraMode *m2); typedef struct { - uint32_t index; + uint32_t index; - uint8_t *data; - int fd; + uint8_t *data; + int fd; } MPBuffer; typedef struct _MPCamera MPCamera; @@ -85,21 +85,21 @@ MPCameraModeList *mp_camera_mode_list_next(MPCameraModeList *list); void mp_camera_mode_list_free(MPCameraModeList *list); typedef struct { - uint32_t id; - uint32_t type; - char name[32]; + uint32_t id; + uint32_t type; + char name[32]; - int32_t min; - int32_t max; - int32_t step; - int32_t default_value; + int32_t min; + int32_t max; + int32_t step; + int32_t default_value; - uint32_t flags; + uint32_t flags; - uint32_t element_size; - uint32_t element_count; - uint32_t dimensions_count; - uint32_t dimensions[V4L2_CTRL_MAX_DIMS]; + uint32_t element_size; + uint32_t element_count; + uint32_t dimensions_count; + uint32_t dimensions[V4L2_CTRL_MAX_DIMS]; } MPControl; const char *mp_control_id_to_str(uint32_t id); diff --git a/src/camera_config.c b/src/camera_config.c index 7126286..5cb93f7 100644 --- a/src/camera_config.c +++ b/src/camera_config.c @@ -1,14 +1,14 @@ #include "camera_config.h" -#include "ini.h" #include "config.h" +#include "ini.h" #include "matrix.h" +#include +#include #include #include #include #include -#include -#include static struct mp_camera_config cameras[MP_MAX_CAMERAS]; static size_t num_cameras = 0; @@ -19,268 +19,284 @@ static char *exif_model; static bool find_config(char *conffile) { - char buf[512]; - FILE *fp; + char buf[512]; + FILE *fp; - if (access("/proc/device-tree/compatible", F_OK) != -1) { - // Reads to compatible string of the current device tree, looks like: - // pine64,pinephone-1.2\0allwinner,sun50i-a64\0 - fp = fopen("/proc/device-tree/compatible", "r"); - fgets(buf, 512, fp); - fclose(fp); + if (access("/proc/device-tree/compatible", F_OK) != -1) { + // Reads to compatible string of the current device tree, looks like: + // pine64,pinephone-1.2\0allwinner,sun50i-a64\0 + fp = fopen("/proc/device-tree/compatible", "r"); + fgets(buf, 512, fp); + fclose(fp); - // Check config/%dt.ini in the current working directory - sprintf(conffile, "config/%s.ini", buf); - if (access(conffile, F_OK) != -1) { - printf("Found config file at %s\n", conffile); - return true; - } + // Check config/%dt.ini in the current working directory + sprintf(conffile, "config/%s.ini", buf); + if (access(conffile, F_OK) != -1) { + printf("Found config file at %s\n", conffile); + return true; + } - // Check for a config file in XDG_CONFIG_HOME - sprintf(conffile, "%s/megapixels/config/%s.ini", - g_get_user_config_dir(), buf); - if (access(conffile, F_OK) != -1) { - printf("Found config file at %s\n", conffile); - return true; - } + // Check for a config file in XDG_CONFIG_HOME + sprintf(conffile, + "%s/megapixels/config/%s.ini", + g_get_user_config_dir(), + buf); + if (access(conffile, F_OK) != -1) { + printf("Found config file at %s\n", conffile); + return true; + } - // Check user overridden /etc/megapixels/config/$dt.ini - sprintf(conffile, "%s/megapixels/config/%s.ini", SYSCONFDIR, buf); - if (access(conffile, F_OK) != -1) { - printf("Found config file at %s\n", conffile); - return true; - } - // Check packaged /usr/share/megapixels/config/$dt.ini - sprintf(conffile, "%s/megapixels/config/%s.ini", DATADIR, buf); - if (access(conffile, F_OK) != -1) { - printf("Found config file at %s\n", conffile); - return true; - } - printf("%s not found\n", conffile); - } else { - printf("Could not read device name from device tree\n"); - } + // Check user overridden /etc/megapixels/config/$dt.ini + sprintf(conffile, "%s/megapixels/config/%s.ini", SYSCONFDIR, buf); + if (access(conffile, F_OK) != -1) { + printf("Found config file at %s\n", conffile); + return true; + } + // Check packaged /usr/share/megapixels/config/$dt.ini + sprintf(conffile, "%s/megapixels/config/%s.ini", DATADIR, buf); + if (access(conffile, F_OK) != -1) { + printf("Found config file at %s\n", conffile); + return true; + } + printf("%s not found\n", conffile); + } else { + printf("Could not read device name from device tree\n"); + } - // If all else fails, fall back to /etc/megapixels.ini - sprintf(conffile, "/etc/megapixels.ini"); - if (access(conffile, F_OK) != -1) { - printf("Found config file at %s\n", conffile); - return true; - } + // If all else fails, fall back to /etc/megapixels.ini + sprintf(conffile, "/etc/megapixels.ini"); + if (access(conffile, F_OK) != -1) { + printf("Found config file at %s\n", conffile); + return true; + } - return false; + return false; } static int strtoint(const char *nptr, char **endptr, int base) { - long x = strtol(nptr, endptr, base); - assert(x <= INT_MAX); - return (int)x; + long x = strtol(nptr, endptr, base); + assert(x <= INT_MAX); + return (int)x; } static bool -config_handle_camera_mode(const char *prefix, MPCameraMode *mode, const char *name, - const char *value) +config_handle_camera_mode(const char *prefix, + MPCameraMode *mode, + const char *name, + const char *value) { - int prefix_length = strlen(prefix); - if (strncmp(prefix, name, prefix_length) != 0) - return false; + int prefix_length = strlen(prefix); + if (strncmp(prefix, name, prefix_length) != 0) + return false; - name += prefix_length; + name += prefix_length; - if (strcmp(name, "width") == 0) { - mode->width = strtoint(value, NULL, 10); - } else if (strcmp(name, "height") == 0) { - mode->height = strtoint(value, NULL, 10); - } else if (strcmp(name, "rate") == 0) { - mode->frame_interval.numerator = 1; - mode->frame_interval.denominator = strtoint(value, NULL, 10); - } else if (strcmp(name, "fmt") == 0) { - mode->pixel_format = mp_pixel_format_from_str(value); - if (mode->pixel_format == MP_PIXEL_FMT_UNSUPPORTED) { - g_printerr("Unsupported pixelformat %s\n", value); - exit(1); - } - } else { - return false; - } - return true; + if (strcmp(name, "width") == 0) { + mode->width = strtoint(value, NULL, 10); + } else if (strcmp(name, "height") == 0) { + mode->height = strtoint(value, NULL, 10); + } else if (strcmp(name, "rate") == 0) { + mode->frame_interval.numerator = 1; + mode->frame_interval.denominator = strtoint(value, NULL, 10); + } else if (strcmp(name, "fmt") == 0) { + mode->pixel_format = mp_pixel_format_from_str(value); + if (mode->pixel_format == MP_PIXEL_FMT_UNSUPPORTED) { + g_printerr("Unsupported pixelformat %s\n", value); + exit(1); + } + } else { + return false; + } + return true; } static int -config_ini_handler(void *user, const char *section, const char *name, - const char *value) +config_ini_handler(void *user, + const char *section, + const char *name, + const char *value) { - if (strcmp(section, "device") == 0) { - if (strcmp(name, "make") == 0) { - exif_make = strdup(value); - } else if (strcmp(name, "model") == 0) { - exif_model = strdup(value); - } else { - g_printerr("Unknown key '%s' in [device]\n", name); - exit(1); - } - } else { - if (num_cameras == MP_MAX_CAMERAS) { - g_printerr("More cameras defined than NUM_CAMERAS\n"); - exit(1); - } + if (strcmp(section, "device") == 0) { + if (strcmp(name, "make") == 0) { + exif_make = strdup(value); + } else if (strcmp(name, "model") == 0) { + exif_model = strdup(value); + } else { + g_printerr("Unknown key '%s' in [device]\n", name); + exit(1); + } + } else { + if (num_cameras == MP_MAX_CAMERAS) { + g_printerr("More cameras defined than NUM_CAMERAS\n"); + exit(1); + } - size_t index = 0; - for (; index < num_cameras; ++index) { - if (strcmp(cameras[index].cfg_name, section) == 0) { - break; - } - } + size_t index = 0; + for (; index < num_cameras; ++index) { + if (strcmp(cameras[index].cfg_name, section) == 0) { + break; + } + } - if (index == num_cameras) { - printf("Adding camera %s from config\n", section); - ++num_cameras; + if (index == num_cameras) { + printf("Adding camera %s from config\n", section); + ++num_cameras; - cameras[index].index = index; - strcpy(cameras[index].cfg_name, section); - } + cameras[index].index = index; + strcpy(cameras[index].cfg_name, section); + } - struct mp_camera_config *cc = &cameras[index]; + struct mp_camera_config *cc = &cameras[index]; - if (config_handle_camera_mode("capture-", &cc->capture_mode, name, - value)) { - } else if (config_handle_camera_mode("preview-", &cc->preview_mode, - name, value)) { - } else if (strcmp(name, "rotate") == 0) { - cc->rotate = strtoint(value, NULL, 10); - } else if (strcmp(name, "mirrored") == 0) { - cc->mirrored = strcmp(value, "true") == 0; - } else if (strcmp(name, "driver") == 0) { - strcpy(cc->dev_name, value); - } else if (strcmp(name, "media-driver") == 0) { - strcpy(cc->media_dev_name, value); - } else if (strcmp(name, "media-links") == 0) { - char **linkdefs = g_strsplit(value, ",", 0); + if (config_handle_camera_mode( + "capture-", &cc->capture_mode, name, value)) { + } else if (config_handle_camera_mode( + "preview-", &cc->preview_mode, name, value)) { + } else if (strcmp(name, "rotate") == 0) { + cc->rotate = strtoint(value, NULL, 10); + } else if (strcmp(name, "mirrored") == 0) { + cc->mirrored = strcmp(value, "true") == 0; + } else if (strcmp(name, "driver") == 0) { + strcpy(cc->dev_name, value); + } else if (strcmp(name, "media-driver") == 0) { + strcpy(cc->media_dev_name, value); + } else if (strcmp(name, "media-links") == 0) { + char **linkdefs = g_strsplit(value, ",", 0); - for (int i = 0; i < MP_MAX_LINKS && linkdefs[i] != NULL; - ++i) { - char **linkdef = g_strsplit(linkdefs[i], "->", 2); - char **porta = g_strsplit(linkdef[0], ":", 2); - char **portb = g_strsplit(linkdef[1], ":", 2); + for (int i = 0; i < MP_MAX_LINKS && linkdefs[i] != NULL; + ++i) { + char **linkdef = g_strsplit(linkdefs[i], "->", 2); + char **porta = g_strsplit(linkdef[0], ":", 2); + char **portb = g_strsplit(linkdef[1], ":", 2); - strcpy(cc->media_links[i].source_name, porta[0]); - strcpy(cc->media_links[i].target_name, portb[0]); - cc->media_links[i].source_port = - strtoint(porta[1], NULL, 10); - cc->media_links[i].target_port = - strtoint(portb[1], NULL, 10); + strcpy(cc->media_links[i].source_name, porta[0]); + strcpy(cc->media_links[i].target_name, portb[0]); + cc->media_links[i].source_port = + strtoint(porta[1], NULL, 10); + cc->media_links[i].target_port = + strtoint(portb[1], NULL, 10); - g_strfreev(portb); - g_strfreev(porta); - g_strfreev(linkdef); - ++cc->num_media_links; - } - g_strfreev(linkdefs); - } else if (strcmp(name, "colormatrix") == 0) { - sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f", - cc->colormatrix + 0, cc->colormatrix + 1, - cc->colormatrix + 2, cc->colormatrix + 3, - cc->colormatrix + 4, cc->colormatrix + 5, - cc->colormatrix + 6, cc->colormatrix + 7, - cc->colormatrix + 8); - } else if (strcmp(name, "forwardmatrix") == 0) { - sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f", - cc->forwardmatrix + 0, cc->forwardmatrix + 1, - cc->forwardmatrix + 2, cc->forwardmatrix + 3, - cc->forwardmatrix + 4, cc->forwardmatrix + 5, - cc->forwardmatrix + 6, cc->forwardmatrix + 7, - cc->forwardmatrix + 8); - } else if (strcmp(name, "whitelevel") == 0) { - cc->whitelevel = strtoint(value, NULL, 10); - } else if (strcmp(name, "blacklevel") == 0) { - cc->blacklevel = strtoint(value, NULL, 10); - } else if (strcmp(name, "focallength") == 0) { - cc->focallength = strtof(value, NULL); - } else if (strcmp(name, "cropfactor") == 0) { - cc->cropfactor = strtof(value, NULL); - } else if (strcmp(name, "fnumber") == 0) { - cc->fnumber = strtod(value, NULL); - } else if (strcmp(name, "iso-min") == 0) { - cc->iso_min = strtod(value, NULL); - } else if (strcmp(name, "iso-max") == 0) { - cc->iso_max = strtod(value, NULL); - } else if (strcmp(name, "flash-path") == 0) { - strcpy(cc->flash_path, value); - cc->has_flash = true; - } else if (strcmp(name, "flash-display") == 0) { - cc->flash_display = strcmp(value, "true") == 0; + g_strfreev(portb); + g_strfreev(porta); + g_strfreev(linkdef); + ++cc->num_media_links; + } + g_strfreev(linkdefs); + } else if (strcmp(name, "colormatrix") == 0) { + sscanf(value, + "%f,%f,%f,%f,%f,%f,%f,%f,%f", + cc->colormatrix + 0, + cc->colormatrix + 1, + cc->colormatrix + 2, + cc->colormatrix + 3, + cc->colormatrix + 4, + cc->colormatrix + 5, + cc->colormatrix + 6, + cc->colormatrix + 7, + cc->colormatrix + 8); + } else if (strcmp(name, "forwardmatrix") == 0) { + sscanf(value, + "%f,%f,%f,%f,%f,%f,%f,%f,%f", + cc->forwardmatrix + 0, + cc->forwardmatrix + 1, + cc->forwardmatrix + 2, + cc->forwardmatrix + 3, + cc->forwardmatrix + 4, + cc->forwardmatrix + 5, + cc->forwardmatrix + 6, + cc->forwardmatrix + 7, + cc->forwardmatrix + 8); + } else if (strcmp(name, "whitelevel") == 0) { + cc->whitelevel = strtoint(value, NULL, 10); + } else if (strcmp(name, "blacklevel") == 0) { + cc->blacklevel = strtoint(value, NULL, 10); + } else if (strcmp(name, "focallength") == 0) { + cc->focallength = strtof(value, NULL); + } else if (strcmp(name, "cropfactor") == 0) { + cc->cropfactor = strtof(value, NULL); + } else if (strcmp(name, "fnumber") == 0) { + cc->fnumber = strtod(value, NULL); + } else if (strcmp(name, "iso-min") == 0) { + cc->iso_min = strtod(value, NULL); + } else if (strcmp(name, "iso-max") == 0) { + cc->iso_max = strtod(value, NULL); + } else if (strcmp(name, "flash-path") == 0) { + strcpy(cc->flash_path, value); + cc->has_flash = true; + } else if (strcmp(name, "flash-display") == 0) { + cc->flash_display = strcmp(value, "true") == 0; - if (cc->flash_display) { - cc->has_flash = true; - } - } else { - g_printerr("Unknown key '%s' in [%s]\n", name, section); - exit(1); - } - } - return 1; + if (cc->flash_display) { + cc->has_flash = true; + } + } else { + g_printerr("Unknown key '%s' in [%s]\n", name, section); + exit(1); + } + } + return 1; } void calculate_matrices() { - for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { - if (cameras[i].colormatrix != NULL && - cameras[i].forwardmatrix != NULL) { - multiply_matrices(cameras[i].colormatrix, - cameras[i].forwardmatrix, - cameras[i].previewmatrix); - } - } + for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { + if (cameras[i].colormatrix != NULL && + cameras[i].forwardmatrix != NULL) { + multiply_matrices(cameras[i].colormatrix, + cameras[i].forwardmatrix, + cameras[i].previewmatrix); + } + } } bool mp_load_config() { - char file[512]; - if (!find_config(file)) { - g_printerr("Could not find any config file\n"); - return false; - } + char file[512]; + if (!find_config(file)) { + g_printerr("Could not find any config file\n"); + return false; + } - int result = ini_parse(file, config_ini_handler, NULL); - if (result == -1) { - g_printerr("Config file not found\n"); - return false; - } - if (result == -2) { - g_printerr("Could not allocate memory to parse config file\n"); - return false; - } - if (result != 0) { - g_printerr("Could not parse config file\n"); - return false; - } + int result = ini_parse(file, config_ini_handler, NULL); + if (result == -1) { + g_printerr("Config file not found\n"); + return false; + } + if (result == -2) { + g_printerr("Could not allocate memory to parse config file\n"); + return false; + } + if (result != 0) { + g_printerr("Could not parse config file\n"); + return false; + } - calculate_matrices(); + calculate_matrices(); - return true; + return true; } const char * mp_get_device_make() { - return exif_make; + return exif_make; } const char * mp_get_device_model() { - return exif_model; + return exif_model; } const struct mp_camera_config * mp_get_camera_config(size_t index) { - if (index >= num_cameras) - return NULL; + if (index >= num_cameras) + return NULL; - return &cameras[index]; + return &cameras[index]; } diff --git a/src/camera_config.h b/src/camera_config.h index 564ca47..4964685 100644 --- a/src/camera_config.h +++ b/src/camera_config.h @@ -9,42 +9,42 @@ #define MP_MAX_LINKS 10 struct mp_media_link_config { - char source_name[100]; - char target_name[100]; - int source_port; - int target_port; + char source_name[100]; + char target_name[100]; + int source_port; + int target_port; }; struct mp_camera_config { - size_t index; + size_t index; - char cfg_name[100]; - char dev_name[260]; - char media_dev_name[260]; + char cfg_name[100]; + char dev_name[260]; + char media_dev_name[260]; - MPCameraMode capture_mode; - MPCameraMode preview_mode; - int rotate; - bool mirrored; + MPCameraMode capture_mode; + MPCameraMode preview_mode; + int rotate; + bool mirrored; - struct mp_media_link_config media_links[MP_MAX_LINKS]; - int num_media_links; + struct mp_media_link_config media_links[MP_MAX_LINKS]; + int num_media_links; - float colormatrix[9]; - float forwardmatrix[9]; - float previewmatrix[9]; - int blacklevel; - int whitelevel; + float colormatrix[9]; + float forwardmatrix[9]; + float previewmatrix[9]; + int blacklevel; + int whitelevel; - float focallength; - float cropfactor; - double fnumber; - int iso_min; - int iso_max; + float focallength; + float cropfactor; + double fnumber; + int iso_min; + int iso_max; - char flash_path[260]; - bool flash_display; - bool has_flash; + char flash_path[260]; + bool flash_display; + bool has_flash; }; bool mp_load_config(); diff --git a/src/device.c b/src/device.c index e8e6153..032ca94 100644 --- a/src/device.c +++ b/src/device.c @@ -11,453 +11,458 @@ bool mp_find_device_path(struct media_v2_intf_devnode devnode, char *path, int length) { - char uevent_path[256]; - snprintf(uevent_path, 256, "/sys/dev/char/%d:%d/uevent", devnode.major, - devnode.minor); + char uevent_path[256]; + snprintf(uevent_path, + 256, + "/sys/dev/char/%d:%d/uevent", + devnode.major, + devnode.minor); - FILE *f = fopen(uevent_path, "r"); - if (!f) { - return false; - } + FILE *f = fopen(uevent_path, "r"); + if (!f) { + return false; + } - char line[512]; - while (fgets(line, 512, f)) { - if (strncmp(line, "DEVNAME=", 8) == 0) { - // Drop newline - int length = strlen(line); - if (line[length - 1] == '\n') - line[length - 1] = '\0'; + char line[512]; + while (fgets(line, 512, f)) { + if (strncmp(line, "DEVNAME=", 8) == 0) { + // Drop newline + int length = strlen(line); + if (line[length - 1] == '\n') + line[length - 1] = '\0'; - snprintf(path, length, "/dev/%s", line + 8); - return true; - } - } + snprintf(path, length, "/dev/%s", line + 8); + return true; + } + } - fclose(f); + fclose(f); - return false; + return false; } struct _MPDevice { - int fd; + int fd; - struct media_device_info info; + struct media_device_info info; - struct media_v2_entity *entities; - size_t num_entities; - struct media_v2_interface *interfaces; - size_t num_interfaces; - struct media_v2_pad *pads; - size_t num_pads; - struct media_v2_link *links; - size_t num_links; + struct media_v2_entity *entities; + size_t num_entities; + struct media_v2_interface *interfaces; + size_t num_interfaces; + struct media_v2_pad *pads; + size_t num_pads; + struct media_v2_link *links; + size_t num_links; }; static void errno_printerr(const char *s) { - g_printerr("MPDevice: %s error %d, %s\n", s, errno, strerror(errno)); + g_printerr("MPDevice: %s error %d, %s\n", s, errno, strerror(errno)); } static int xioctl(int fd, int request, void *arg) { - int r; - do { - r = ioctl(fd, request, arg); - } while (r == -1 && errno == EINTR); - return r; + int r; + do { + r = ioctl(fd, request, arg); + } while (r == -1 && errno == EINTR); + return r; } MPDevice * mp_device_find(const char *driver_name) { - MPDeviceList *list = mp_device_list_new(); + MPDeviceList *list = mp_device_list_new(); - MPDevice *found_device = mp_device_list_find_remove(&list, driver_name); + MPDevice *found_device = mp_device_list_find_remove(&list, driver_name); - mp_device_list_free(list); + mp_device_list_free(list); - return found_device; + return found_device; } MPDevice * mp_device_open(const char *path) { - int fd = open(path, O_RDWR); - if (fd == -1) { - errno_printerr("open"); - return NULL; - } + int fd = open(path, O_RDWR); + if (fd == -1) { + errno_printerr("open"); + return NULL; + } - return mp_device_new(fd); + return mp_device_new(fd); } MPDevice * mp_device_new(int fd) { - // Get the topology of the media device - struct media_v2_topology topology = {}; - if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1 || - topology.num_entities == 0) { - close(fd); - return NULL; - } + // Get the topology of the media device + struct media_v2_topology topology = {}; + if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1 || + topology.num_entities == 0) { + close(fd); + return NULL; + } - // Create the device - MPDevice *device = calloc(1, sizeof(MPDevice)); - device->fd = fd; - device->entities = - calloc(topology.num_entities, sizeof(struct media_v2_entity)); - device->num_entities = topology.num_entities; - device->interfaces = - calloc(topology.num_interfaces, sizeof(struct media_v2_interface)); - device->num_interfaces = topology.num_interfaces; - device->pads = calloc(topology.num_pads, sizeof(struct media_v2_pad)); - device->num_pads = topology.num_pads; - device->links = calloc(topology.num_links, sizeof(struct media_v2_link)); - device->num_links = topology.num_links; + // Create the device + MPDevice *device = calloc(1, sizeof(MPDevice)); + device->fd = fd; + device->entities = + calloc(topology.num_entities, sizeof(struct media_v2_entity)); + device->num_entities = topology.num_entities; + device->interfaces = + calloc(topology.num_interfaces, sizeof(struct media_v2_interface)); + device->num_interfaces = topology.num_interfaces; + device->pads = calloc(topology.num_pads, sizeof(struct media_v2_pad)); + device->num_pads = topology.num_pads; + device->links = calloc(topology.num_links, sizeof(struct media_v2_link)); + device->num_links = topology.num_links; - // Get the actual devices and interfaces - topology.ptr_entities = (uint64_t)device->entities; - topology.ptr_interfaces = (uint64_t)device->interfaces; - topology.ptr_pads = (uint64_t)device->pads; - topology.ptr_links = (uint64_t)device->links; - if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1) { - errno_printerr("MEDIA_IOC_G_TOPOLOGY"); - mp_device_close(device); - return NULL; - } + // Get the actual devices and interfaces + topology.ptr_entities = (uint64_t)device->entities; + topology.ptr_interfaces = (uint64_t)device->interfaces; + topology.ptr_pads = (uint64_t)device->pads; + topology.ptr_links = (uint64_t)device->links; + if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1) { + errno_printerr("MEDIA_IOC_G_TOPOLOGY"); + mp_device_close(device); + return NULL; + } - // Get device info - if (xioctl(fd, MEDIA_IOC_DEVICE_INFO, &device->info) == -1) { - errno_printerr("MEDIA_IOC_DEVICE_INFO"); - mp_device_close(device); - return NULL; - } + // Get device info + if (xioctl(fd, MEDIA_IOC_DEVICE_INFO, &device->info) == -1) { + errno_printerr("MEDIA_IOC_DEVICE_INFO"); + mp_device_close(device); + return NULL; + } - return device; + return device; } void mp_device_close(MPDevice *device) { - close(device->fd); - free(device->entities); - free(device->interfaces); - free(device->pads); - free(device->links); - free(device); + close(device->fd); + free(device->entities); + free(device->interfaces); + free(device->pads); + free(device->links); + free(device); } bool -mp_device_setup_link(MPDevice *device, uint32_t source_pad_id, uint32_t sink_pad_id, - bool enabled) +mp_device_setup_link(MPDevice *device, + uint32_t source_pad_id, + uint32_t sink_pad_id, + bool enabled) { - const struct media_v2_pad *source_pad = - mp_device_get_pad(device, source_pad_id); - g_return_val_if_fail(source_pad, false); + const struct media_v2_pad *source_pad = + mp_device_get_pad(device, source_pad_id); + g_return_val_if_fail(source_pad, false); - const struct media_v2_pad *sink_pad = mp_device_get_pad(device, sink_pad_id); - g_return_val_if_fail(sink_pad, false); + const struct media_v2_pad *sink_pad = mp_device_get_pad(device, sink_pad_id); + g_return_val_if_fail(sink_pad, false); - struct media_link_desc link = {}; - link.flags = enabled ? MEDIA_LNK_FL_ENABLED : 0; - link.source.entity = source_pad->entity_id; - link.source.index = 0; - link.sink.entity = sink_pad->entity_id; - link.sink.index = 0; - if (xioctl(device->fd, MEDIA_IOC_SETUP_LINK, &link) == -1) { - errno_printerr("MEDIA_IOC_SETUP_LINK"); - return false; - } + struct media_link_desc link = {}; + link.flags = enabled ? MEDIA_LNK_FL_ENABLED : 0; + link.source.entity = source_pad->entity_id; + link.source.index = 0; + link.sink.entity = sink_pad->entity_id; + link.sink.index = 0; + if (xioctl(device->fd, MEDIA_IOC_SETUP_LINK, &link) == -1) { + errno_printerr("MEDIA_IOC_SETUP_LINK"); + return false; + } - return true; + return true; } const struct media_v2_entity * mp_device_find_entity(const MPDevice *device, const char *driver_name) { - int length = strlen(driver_name); + int length = strlen(driver_name); - // Find the entity from the name - for (uint32_t i = 0; i < device->num_entities; ++i) { - if (strncmp(device->entities[i].name, driver_name, length) == 0) { - return &device->entities[i]; - } - } - return NULL; + // Find the entity from the name + for (uint32_t i = 0; i < device->num_entities; ++i) { + if (strncmp(device->entities[i].name, driver_name, length) == 0) { + return &device->entities[i]; + } + } + return NULL; } const struct media_v2_entity * mp_device_find_entity_type(const MPDevice *device, const uint32_t type) { - // Find the entity from the entity type - for (uint32_t i = 0; i < device->num_entities; ++i) { - if (device->entities[i].function == type) { - return &device->entities[i]; - } - } - return NULL; + // Find the entity from the entity type + for (uint32_t i = 0; i < device->num_entities; ++i) { + if (device->entities[i].function == type) { + return &device->entities[i]; + } + } + return NULL; } const struct media_device_info * mp_device_get_info(const MPDevice *device) { - return &device->info; + return &device->info; } const struct media_v2_entity * mp_device_get_entity(const MPDevice *device, uint32_t id) { - for (int i = 0; i < device->num_entities; ++i) { - if (device->entities[i].id == id) { - return &device->entities[i]; - } - } - return NULL; + for (int i = 0; i < device->num_entities; ++i) { + if (device->entities[i].id == id) { + return &device->entities[i]; + } + } + return NULL; } const struct media_v2_entity * mp_device_get_entities(const MPDevice *device) { - return device->entities; + return device->entities; } size_t mp_device_get_num_entities(const MPDevice *device) { - return device->num_entities; + return device->num_entities; } const struct media_v2_interface * mp_device_find_entity_interface(const MPDevice *device, uint32_t entity_id) { - // Find the interface through the link - const struct media_v2_link *link = mp_device_find_link_to(device, entity_id); - if (!link) { - return NULL; - } - return mp_device_get_interface(device, link->source_id); + // Find the interface through the link + const struct media_v2_link *link = mp_device_find_link_to(device, entity_id); + if (!link) { + return NULL; + } + return mp_device_get_interface(device, link->source_id); } const struct media_v2_interface * mp_device_get_interface(const MPDevice *device, uint32_t id) { - for (int i = 0; i < device->num_interfaces; ++i) { - if (device->interfaces[i].id == id) { - return &device->interfaces[i]; - } - } - return NULL; + for (int i = 0; i < device->num_interfaces; ++i) { + if (device->interfaces[i].id == id) { + return &device->interfaces[i]; + } + } + return NULL; } const struct media_v2_interface * mp_device_get_interfaces(const MPDevice *device) { - return device->interfaces; + return device->interfaces; } size_t mp_device_get_num_interfaces(const MPDevice *device) { - return device->num_interfaces; + return device->num_interfaces; } const struct media_v2_pad * mp_device_get_pad_from_entity(const MPDevice *device, uint32_t entity_id) { - for (int i = 0; i < device->num_pads; ++i) { - if (device->pads[i].entity_id == entity_id) { - return &device->pads[i]; - } - } - return NULL; + for (int i = 0; i < device->num_pads; ++i) { + if (device->pads[i].entity_id == entity_id) { + return &device->pads[i]; + } + } + return NULL; } const struct media_v2_pad * mp_device_get_pad(const MPDevice *device, uint32_t id) { - for (int i = 0; i < device->num_pads; ++i) { - if (device->pads[i].id == id) { - return &device->pads[i]; - } - } - return NULL; + for (int i = 0; i < device->num_pads; ++i) { + if (device->pads[i].id == id) { + return &device->pads[i]; + } + } + return NULL; } const struct media_v2_pad * mp_device_get_pads(const MPDevice *device) { - return device->pads; + return device->pads; } size_t mp_device_get_num_pads(const MPDevice *device) { - return device->num_pads; + return device->num_pads; } const struct media_v2_link * mp_device_find_entity_link(const MPDevice *device, uint32_t entity_id) { - const struct media_v2_pad *pad = - mp_device_get_pad_from_entity(device, entity_id); - const struct media_v2_link *link = mp_device_find_link_to(device, pad->id); - if (link) { - return link; - } - return mp_device_find_link_from(device, pad->id); + const struct media_v2_pad *pad = + mp_device_get_pad_from_entity(device, entity_id); + const struct media_v2_link *link = mp_device_find_link_to(device, pad->id); + if (link) { + return link; + } + return mp_device_find_link_from(device, pad->id); } const struct media_v2_link * mp_device_find_link_from(const MPDevice *device, uint32_t source) { - for (int i = 0; i < device->num_links; ++i) { - if (device->links[i].source_id == source) { - return &device->links[i]; - } - } - return NULL; + for (int i = 0; i < device->num_links; ++i) { + if (device->links[i].source_id == source) { + return &device->links[i]; + } + } + return NULL; } const struct media_v2_link * mp_device_find_link_to(const MPDevice *device, uint32_t sink) { - for (int i = 0; i < device->num_links; ++i) { - if (device->links[i].sink_id == sink) { - return &device->links[i]; - } - } - return NULL; + for (int i = 0; i < device->num_links; ++i) { + if (device->links[i].sink_id == sink) { + return &device->links[i]; + } + } + return NULL; } const struct media_v2_link * mp_device_find_link_between(const MPDevice *device, uint32_t source, uint32_t sink) { - for (int i = 0; i < device->num_links; ++i) { - if (device->links[i].source_id == source && - device->links[i].sink_id == sink) { - return &device->links[i]; - } - } - return NULL; + for (int i = 0; i < device->num_links; ++i) { + if (device->links[i].source_id == source && + device->links[i].sink_id == sink) { + return &device->links[i]; + } + } + return NULL; } const struct media_v2_link * mp_device_get_link(const MPDevice *device, uint32_t id) { - for (int i = 0; i < device->num_links; ++i) { - if (device->links[i].id == id) { - return &device->links[i]; - } - } - return NULL; + for (int i = 0; i < device->num_links; ++i) { + if (device->links[i].id == id) { + return &device->links[i]; + } + } + return NULL; } const struct media_v2_link * mp_device_get_links(const MPDevice *device) { - return device->links; + return device->links; } size_t mp_device_get_num_links(const MPDevice *device) { - return device->num_links; + return device->num_links; } struct _MPDeviceList { - MPDevice *device; - MPDeviceList *next; + MPDevice *device; + MPDeviceList *next; }; MPDeviceList * mp_device_list_new() { - MPDeviceList *current = NULL; + MPDeviceList *current = NULL; - // Enumerate media device files - struct dirent *dir; - DIR *d = opendir("/dev"); - while ((dir = readdir(d)) != NULL) { - if (strncmp(dir->d_name, "media", 5) == 0) { - char path[261]; - snprintf(path, 261, "/dev/%s", dir->d_name); + // Enumerate media device files + struct dirent *dir; + DIR *d = opendir("/dev"); + while ((dir = readdir(d)) != NULL) { + if (strncmp(dir->d_name, "media", 5) == 0) { + char path[261]; + snprintf(path, 261, "/dev/%s", dir->d_name); - MPDevice *device = mp_device_open(path); + MPDevice *device = mp_device_open(path); - if (device) { - MPDeviceList *next = malloc(sizeof(MPDeviceList)); - next->device = device; - next->next = current; - current = next; - } - } - } - closedir(d); + if (device) { + MPDeviceList *next = malloc(sizeof(MPDeviceList)); + next->device = device; + next->next = current; + current = next; + } + } + } + closedir(d); - return current; + return current; } void mp_device_list_free(MPDeviceList *device_list) { - while (device_list) { - MPDeviceList *tmp = device_list; - device_list = tmp->next; + while (device_list) { + MPDeviceList *tmp = device_list; + device_list = tmp->next; - mp_device_close(tmp->device); - free(tmp); - } + mp_device_close(tmp->device); + free(tmp); + } } MPDevice * mp_device_list_find_remove(MPDeviceList **list, const char *driver_name) { - MPDevice *found_device = NULL; - int length = strlen(driver_name); + MPDevice *found_device = NULL; + int length = strlen(driver_name); - while (*list) { - MPDevice *device = mp_device_list_get(*list); - const struct media_device_info *info = mp_device_get_info(device); + while (*list) { + MPDevice *device = mp_device_list_get(*list); + const struct media_device_info *info = mp_device_get_info(device); - if (strncmp(info->driver, driver_name, length) == 0) { - found_device = mp_device_list_remove(list); - break; - } + if (strncmp(info->driver, driver_name, length) == 0) { + found_device = mp_device_list_remove(list); + break; + } - list = &(*list)->next; - } + list = &(*list)->next; + } - return found_device; + return found_device; } MPDevice * mp_device_list_remove(MPDeviceList **device_list) { - MPDevice *device = (*device_list)->device; + MPDevice *device = (*device_list)->device; - if ((*device_list)->next) { - MPDeviceList *tmp = (*device_list)->next; - **device_list = *tmp; - free(tmp); - } else { - free(*device_list); - *device_list = NULL; - } + if ((*device_list)->next) { + MPDeviceList *tmp = (*device_list)->next; + **device_list = *tmp; + free(tmp); + } else { + free(*device_list); + *device_list = NULL; + } - return device; + return device; } MPDevice * mp_device_list_get(const MPDeviceList *device_list) { - return device_list->device; + return device_list->device; } MPDeviceList * mp_device_list_next(const MPDeviceList *device_list) { - return device_list->next; + return device_list->next; } diff --git a/src/device.h b/src/device.h index c47a40d..9ea69f1 100644 --- a/src/device.h +++ b/src/device.h @@ -5,8 +5,8 @@ #include #include -bool mp_find_device_path(struct media_v2_intf_devnode devnode, char *path, - int length); +bool +mp_find_device_path(struct media_v2_intf_devnode devnode, char *path, int length); typedef struct _MPDevice MPDevice; @@ -15,35 +15,37 @@ MPDevice *mp_device_open(const char *path); MPDevice *mp_device_new(int fd); void mp_device_close(MPDevice *device); -bool mp_device_setup_link(MPDevice *device, uint32_t source_pad_id, - uint32_t sink_pad_id, bool enabled); +bool mp_device_setup_link(MPDevice *device, + uint32_t source_pad_id, + uint32_t sink_pad_id, + bool enabled); const struct media_device_info *mp_device_get_info(const MPDevice *device); const struct media_v2_entity *mp_device_find_entity(const MPDevice *device, - const char *driver_name); + const char *driver_name); const struct media_v2_entity *mp_device_find_entity_type(const MPDevice *device, - const uint32_t type); + const uint32_t type); const struct media_v2_entity *mp_device_get_entity(const MPDevice *device, - uint32_t id); + uint32_t id); const struct media_v2_entity *mp_device_get_entities(const MPDevice *device); size_t mp_device_get_num_entities(const MPDevice *device); const struct media_v2_interface * mp_device_find_entity_interface(const MPDevice *device, uint32_t entity_id); const struct media_v2_interface *mp_device_get_interface(const MPDevice *device, - uint32_t id); + uint32_t id); const struct media_v2_interface *mp_device_get_interfaces(const MPDevice *device); size_t mp_device_get_num_interfaces(const MPDevice *device); const struct media_v2_pad *mp_device_get_pad_from_entity(const MPDevice *device, - uint32_t entity_id); + uint32_t entity_id); const struct media_v2_pad *mp_device_get_pad(const MPDevice *device, uint32_t id); const struct media_v2_pad *mp_device_get_pads(const MPDevice *device); size_t mp_device_get_num_pads(const MPDevice *device); const struct media_v2_link *mp_device_find_entity_link(const MPDevice *device, - uint32_t entity_id); + uint32_t entity_id); const struct media_v2_link *mp_device_find_link_from(const MPDevice *device, - uint32_t source); + uint32_t source); const struct media_v2_link *mp_device_find_link_to(const MPDevice *device, - uint32_t sink); + uint32_t sink); const struct media_v2_link * mp_device_find_link_between(const MPDevice *device, uint32_t source, uint32_t sink); const struct media_v2_link *mp_device_get_link(const MPDevice *device, uint32_t id); @@ -56,7 +58,7 @@ MPDeviceList *mp_device_list_new(); void mp_device_list_free(MPDeviceList *device_list); MPDevice *mp_device_list_find_remove(MPDeviceList **device_list, - const char *driver_name); + const char *driver_name); MPDevice *mp_device_list_remove(MPDeviceList **device_list); MPDevice *mp_device_list_get(const MPDeviceList *device_list); diff --git a/src/flash.c b/src/flash.c index abadd82..11e3107 100644 --- a/src/flash.c +++ b/src/flash.c @@ -1,51 +1,51 @@ #include "flash.h" #include "gtk/gtk.h" -#include -#include #include #include +#include +#include typedef enum { - FLASH_TYPE_LED, - FLASH_TYPE_DISPLAY, + FLASH_TYPE_LED, + FLASH_TYPE_DISPLAY, } FlashType; typedef struct { - char path[260]; - int fd; + char path[260]; + int fd; } MPLEDFlash; typedef struct { } MPDisplayFlash; struct _MPFlash { - FlashType type; + FlashType type; - union { - MPLEDFlash led; - MPDisplayFlash display; - }; + union { + MPLEDFlash led; + MPDisplayFlash display; + }; }; MPFlash * mp_led_flash_from_path(const char *path) { - MPFlash *flash = malloc(sizeof(MPFlash)); - flash->type = FLASH_TYPE_LED; + MPFlash *flash = malloc(sizeof(MPFlash)); + flash->type = FLASH_TYPE_LED; - strncpy(flash->led.path, path, 259); + strncpy(flash->led.path, path, 259); - char mpath[275]; - snprintf(mpath, 275, "%s/flash_strobe", path); - flash->led.fd = open(mpath, O_WRONLY); - if (flash->led.fd == -1) { - g_printerr("Failed to open %s\n", mpath); - free(flash); - return NULL; - } + char mpath[275]; + snprintf(mpath, 275, "%s/flash_strobe", path); + flash->led.fd = open(mpath, O_WRONLY); + if (flash->led.fd == -1) { + g_printerr("Failed to open %s\n", mpath); + free(flash); + return NULL; + } - return flash; + return flash; } static GtkWidget *flash_window = NULL; @@ -55,160 +55,174 @@ static int dbus_old_brightness = 0; static void dbus_brightness_init(GObject *src, GAsyncResult *res, gpointer *user_data) { - GError *err = NULL; - dbus_brightness_proxy = g_dbus_proxy_new_finish(res, &err); - if (!dbus_brightness_proxy || err) { - printf("Failed to connect to dbus brightness service %s\n", - err->message); - g_object_unref(err); - return; - } + GError *err = NULL; + dbus_brightness_proxy = g_dbus_proxy_new_finish(res, &err); + if (!dbus_brightness_proxy || err) { + printf("Failed to connect to dbus brightness service %s\n", + err->message); + g_object_unref(err); + return; + } } void mp_flash_gtk_init(GDBusConnection *conn) { - g_dbus_proxy_new(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, - "org.gnome.SettingsDaemon.Power", - "/org/gnome/SettingsDaemon/Power", - "org.gnome.SettingsDaemon.Power.Screen", NULL, - (GAsyncReadyCallback)dbus_brightness_init, NULL); + g_dbus_proxy_new(conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.SettingsDaemon.Power", + "/org/gnome/SettingsDaemon/Power", + "org.gnome.SettingsDaemon.Power.Screen", + NULL, + (GAsyncReadyCallback)dbus_brightness_init, + NULL); - // Create a full screen full white window as a flash - GtkWidget *window = gtk_window_new(); - // gtk_window_set_accept_focus(GTK_WINDOW(flash->display.window), FALSE); - gtk_window_set_decorated(GTK_WINDOW(window), FALSE); - gtk_window_fullscreen(GTK_WINDOW(window)); + // Create a full screen full white window as a flash + GtkWidget *window = gtk_window_new(); + // gtk_window_set_accept_focus(GTK_WINDOW(flash->display.window), FALSE); + gtk_window_set_decorated(GTK_WINDOW(window), FALSE); + gtk_window_fullscreen(GTK_WINDOW(window)); - GtkStyleContext *context; - context = gtk_widget_get_style_context(window); - gtk_style_context_add_class(context, "flash"); + GtkStyleContext *context; + context = gtk_widget_get_style_context(window); + gtk_style_context_add_class(context, "flash"); - flash_window = window; + flash_window = window; } void mp_flash_gtk_clean() { - gtk_window_destroy(GTK_WINDOW(flash_window)); - g_object_unref(dbus_brightness_proxy); + gtk_window_destroy(GTK_WINDOW(flash_window)); + g_object_unref(dbus_brightness_proxy); } MPFlash * mp_create_display_flash() { - MPFlash *flash = malloc(sizeof(MPFlash)); - flash->type = FLASH_TYPE_DISPLAY; + MPFlash *flash = malloc(sizeof(MPFlash)); + flash->type = FLASH_TYPE_DISPLAY; - return flash; + return flash; } void mp_flash_free(MPFlash *flash) { - switch (flash->type) { - case FLASH_TYPE_LED: - close(flash->led.fd); - break; - case FLASH_TYPE_DISPLAY: - break; - } + switch (flash->type) { + case FLASH_TYPE_LED: + close(flash->led.fd); + break; + case FLASH_TYPE_DISPLAY: + break; + } - free(flash); + free(flash); } static void set_display_brightness(int brightness) { - g_dbus_proxy_call( - dbus_brightness_proxy, "org.freedesktop.DBus.Properties.Set", - g_variant_new("(ssv)", "org.gnome.SettingsDaemon.Power.Screen", - "Brightness", g_variant_new("i", brightness)), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + g_dbus_proxy_call(dbus_brightness_proxy, + "org.freedesktop.DBus.Properties.Set", + g_variant_new("(ssv)", + "org.gnome.SettingsDaemon.Power.Screen", + "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) { - GError *error = NULL; - GVariant *result = g_dbus_proxy_call_finish(proxy, res, &error); + GError *error = NULL; + GVariant *result = g_dbus_proxy_call_finish(proxy, res, &error); - if (!result) { - printf("Failed to get display brightness: %s\n", error->message); - g_object_unref(error); - return; - } + if (!result) { + printf("Failed to get display brightness: %s\n", error->message); + g_object_unref(error); + return; + } - GVariant *values = g_variant_get_child_value(result, 0); - if (g_variant_n_children(values) == 0) { - return; - } + GVariant *values = g_variant_get_child_value(result, 0); + if (g_variant_n_children(values) == 0) { + return; + } - GVariant *brightness = g_variant_get_child_value(values, 0); - dbus_old_brightness = g_variant_get_int32(brightness); + GVariant *brightness = g_variant_get_child_value(values, 0); + dbus_old_brightness = g_variant_get_int32(brightness); - g_variant_unref(result); + g_variant_unref(result); } static bool show_display_flash(MPFlash *flash) { - if (!flash_window) - return false; + if (!flash_window) + return false; - gtk_widget_show(flash_window); + gtk_widget_show(flash_window); - // First get brightness and then set brightness to 100% - if (!dbus_brightness_proxy) - return false; + // First get brightness and then set brightness to 100% + if (!dbus_brightness_proxy) + return false; - g_dbus_proxy_call( - dbus_brightness_proxy, "org.freedesktop.DBus.Properties.Get", - g_variant_new("(ss)", "org.gnome.SettingsDaemon.Power.Screen", - "Brightness"), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, - (GAsyncReadyCallback)brightness_received, NULL); + g_dbus_proxy_call(dbus_brightness_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new("(ss)", + "org.gnome.SettingsDaemon.Power.Screen", + "Brightness"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + (GAsyncReadyCallback)brightness_received, + NULL); - set_display_brightness(100); + set_display_brightness(100); - return false; + return false; } void mp_flash_enable(MPFlash *flash) { - switch (flash->type) { - case FLASH_TYPE_LED: - lseek(flash->led.fd, 0, SEEK_SET); - dprintf(flash->led.fd, "1\n"); - break; - case FLASH_TYPE_DISPLAY: - g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash); - break; - } + switch (flash->type) { + case FLASH_TYPE_LED: + lseek(flash->led.fd, 0, SEEK_SET); + dprintf(flash->led.fd, "1\n"); + break; + case FLASH_TYPE_DISPLAY: + g_main_context_invoke(NULL, (GSourceFunc)show_display_flash, flash); + break; + } } static bool hide_display_flash(MPFlash *flash) { - if (!flash_window) - return false; + if (!flash_window) + return false; - gtk_widget_hide(flash_window); - set_display_brightness(dbus_old_brightness); + gtk_widget_hide(flash_window); + set_display_brightness(dbus_old_brightness); - return false; + return false; } void mp_flash_disable(MPFlash *flash) { - switch (flash->type) { - case FLASH_TYPE_LED: - // Flash gets reset automatically - break; - case FLASH_TYPE_DISPLAY: - g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash); - break; - } + switch (flash->type) { + case FLASH_TYPE_LED: + // Flash gets reset automatically + break; + case FLASH_TYPE_DISPLAY: + g_main_context_invoke(NULL, (GSourceFunc)hide_display_flash, flash); + break; + } } diff --git a/src/gl_util.c b/src/gl_util.c index 0d46dd4..8fc6e0a 100644 --- a/src/gl_util.c +++ b/src/gl_util.c @@ -1,240 +1,256 @@ #include "gl_util.h" +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include void gl_util_check_error(const char *file, int line) { - GLenum error = glGetError(); + GLenum error = glGetError(); - const char *name; - switch (error) { - case GL_NO_ERROR: - return; // no error - case GL_INVALID_ENUM: - name = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - name = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - name = "GL_INVALID_OPERATION"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - name = "GL_INVALID_FRAMEBUFFER_OPERATION"; - break; - case GL_OUT_OF_MEMORY: - name = "GL_OUT_OF_MEMORY"; - break; - default: - name = "UNKNOWN ERROR!"; - break; - } + const char *name; + switch (error) { + case GL_NO_ERROR: + return; // no error + case GL_INVALID_ENUM: + name = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + name = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + name = "GL_INVALID_OPERATION"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + name = "GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + case GL_OUT_OF_MEMORY: + name = "GL_OUT_OF_MEMORY"; + break; + default: + name = "UNKNOWN ERROR!"; + break; + } - printf("GL error at %s:%d - %s\n", file, line, name); + printf("GL error at %s:%d - %s\n", file, line, name); - // raise(SIGTRAP); + // raise(SIGTRAP); } 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(); - assert(context); + GdkGLContext *context = gdk_gl_context_get_current(); + assert(context); - GLuint shader = glCreateShader(type); - if (shader == 0) { - return 0; - } + GLuint shader = glCreateShader(type); + if (shader == 0) { + return 0; + } - GBytes *bytes = g_resources_lookup_data(resource, 0, NULL); - if (!bytes) { - printf("Failed to load shader resource %s\n", resource); - return 0; - } + GBytes *bytes = g_resources_lookup_data(resource, 0, NULL); + if (!bytes) { + printf("Failed to load shader resource %s\n", resource); + return 0; + } - // Build #define for OpenGL context information - gboolean is_es = gdk_gl_context_get_use_es(context); - int major, minor; - gdk_gl_context_get_version(context, &major, &minor); - 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); + // Build #define for OpenGL context information + gboolean is_es = gdk_gl_context_get_use_es(context); + int major, minor; + gdk_gl_context_get_version(context, &major, &minor); + 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); - gsize glib_size = 0; - const GLchar *source = g_bytes_get_data(bytes, &glib_size); - if (glib_size == 0 || glib_size > INT_MAX) { - printf("Invalid size for resource\n"); - return 0; - } + gsize glib_size = 0; + const GLchar *source = g_bytes_get_data(bytes, &glib_size); + if (glib_size == 0 || glib_size > INT_MAX) { + printf("Invalid size for resource\n"); + return 0; + } - const GLchar **sources = malloc((num_extra + 1) * sizeof(GLchar *)); - GLint *sizes = malloc((num_extra + 1) * sizeof(GLint)); + const GLchar **sources = malloc((num_extra + 1) * sizeof(GLchar *)); + GLint *sizes = malloc((num_extra + 1) * sizeof(GLint)); - for (size_t i = 0; i < num_extra; ++i) { - sources[i] = extra_sources[i]; - sizes[i] = -1; - } - sources[num_extra] = source; - sizes[num_extra] = glib_size; + for (size_t i = 0; i < num_extra; ++i) { + sources[i] = extra_sources[i]; + sizes[i] = -1; + } + sources[num_extra] = source; + sizes[num_extra] = glib_size; - glShaderSource(shader, num_extra + 1, sources, sizes); - glCompileShader(shader); - check_gl(); + glShaderSource(shader, num_extra + 1, sources, sizes); + glCompileShader(shader); + check_gl(); - free(sources); - free(sizes); + free(sources); + free(sizes); - g_bytes_unref(bytes); + g_bytes_unref(bytes); - // Check compile status - GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (success == GL_FALSE) { - printf("Shader compilation failed for %s\n", resource); + // Check compile status + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (success == GL_FALSE) { + printf("Shader compilation failed for %s\n", resource); - glDeleteShader(shader); - return 0; - } + glDeleteShader(shader); + return 0; + } - GLint log_length; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); - if (log_length > 0) { - char *log = malloc(sizeof(char) * log_length); - glGetShaderInfoLog(shader, log_length - 1, &log_length, log); + GLint log_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) { + char *log = malloc(sizeof(char) * log_length); + glGetShaderInfoLog(shader, log_length - 1, &log_length, log); - printf("Shader %s log: %s\n", resource, log); - free(log); + printf("Shader %s log: %s\n", resource, log); + free(log); - glDeleteShader(shader); - return 0; - } + glDeleteShader(shader); + return 0; + } - return shader; + return shader; } GLuint gl_util_link_program(GLuint *shaders, size_t num_shaders) { - GLuint program = glCreateProgram(); + GLuint program = glCreateProgram(); - for (size_t i = 0; i < num_shaders; ++i) { - glAttachShader(program, shaders[i]); - } + for (size_t i = 0; i < num_shaders; ++i) { + glAttachShader(program, shaders[i]); + } - glLinkProgram(program); - check_gl(); + glLinkProgram(program); + check_gl(); - GLint success; - glGetProgramiv(program, GL_LINK_STATUS, &success); - if (success == GL_FALSE) { - printf("Program linking failed\n"); - } + GLint success; + glGetProgramiv(program, GL_LINK_STATUS, &success); + if (success == GL_FALSE) { + printf("Program linking failed\n"); + } - GLint log_length; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); - if (log_length > 0) { - char *log = malloc(sizeof(char) * log_length); - glGetProgramInfoLog(program, log_length - 1, &log_length, log); + GLint log_length; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); + if (log_length > 0) { + char *log = malloc(sizeof(char) * log_length); + glGetProgramInfoLog(program, log_length - 1, &log_length, log); - printf("Program log: %s\n", log); - free(log); - } - check_gl(); + printf("Program log: %s\n", log); + free(log); + } + check_gl(); - return program; + return program; } static const GLfloat quad_data[] = { - // Vertices - -1, - -1, - 1, - -1, - -1, - 1, - 1, - 1, - // Texcoords - 0, - 0, - 1, - 0, - 0, - 1, - 1, - 1, + // Vertices + -1, + -1, + 1, + -1, + -1, + 1, + 1, + 1, + // Texcoords + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, }; GLuint gl_util_new_quad() { - GdkGLContext *context = gdk_gl_context_get_current(); - assert(context); + GdkGLContext *context = gdk_gl_context_get_current(); + assert(context); - if (gdk_gl_context_get_use_es(context)) { - return 0; - } else { - GLuint buffer; - glGenBuffers(1, &buffer); + if (gdk_gl_context_get_use_es(context)) { + return 0; + } else { + GLuint buffer; + glGenBuffers(1, &buffer); - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, - GL_STATIC_DRAW); - check_gl(); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, + sizeof(quad_data), + quad_data, + GL_STATIC_DRAW); + check_gl(); - glBindBuffer(GL_ARRAY_BUFFER, 0); - check_gl(); + glBindBuffer(GL_ARRAY_BUFFER, 0); + check_gl(); - return buffer; - } + return buffer; + } } void gl_util_bind_quad(GLuint buffer) { - GdkGLContext *context = gdk_gl_context_get_current(); - assert(context); + GdkGLContext *context = gdk_gl_context_get_current(); + assert(context); - if (gdk_gl_context_get_use_es(context)) { - glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, - quad_data); - check_gl(); - glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); - check_gl(); + if (gdk_gl_context_get_use_es(context)) { + glVertexAttribPointer( + GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, quad_data); + check_gl(); + glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); + check_gl(); - glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, 0, 0, - quad_data + 8); - check_gl(); - glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); - check_gl(); - } else { - glBindBuffer(GL_ARRAY_BUFFER, buffer); - check_gl(); + glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, + 2, + GL_FLOAT, + 0, + 0, + quad_data + 8); + check_gl(); + glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); + check_gl(); + } else { + glBindBuffer(GL_ARRAY_BUFFER, buffer); + check_gl(); - glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, - GL_FALSE, 0, 0); - glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); - check_gl(); + glVertexAttribPointer( + GL_UTIL_VERTEX_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); + check_gl(); - glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, - GL_FALSE, 0, (void *)(8 * sizeof(float))); - glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); - check_gl(); - } + glVertexAttribPointer(GL_UTIL_TEX_COORD_ATTRIBUTE, + 2, + GL_FLOAT, + GL_FALSE, + 0, + (void *)(8 * sizeof(float))); + glEnableVertexAttribArray(GL_UTIL_TEX_COORD_ATTRIBUTE); + check_gl(); + } } void gl_util_draw_quad(GLuint buffer) { - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - check_gl(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + check_gl(); } diff --git a/src/gl_util.h b/src/gl_util.h index fd3e48a..135bb3e 100644 --- a/src/gl_util.h +++ b/src/gl_util.h @@ -9,8 +9,10 @@ #define check_gl() gl_util_check_error(__FILE__, __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_new_quad(); diff --git a/src/gles2_debayer.c b/src/gles2_debayer.c index 24540ef..7f5a9bd 100644 --- a/src/gles2_debayer.c +++ b/src/gles2_debayer.c @@ -8,142 +8,150 @@ #define TEX_COORD_ATTRIBUTE 1 struct _GLES2Debayer { - GLuint frame_buffer; - GLuint program; - GLuint uniform_transform; - GLuint uniform_pixel_size; - GLuint uniform_texture; - GLuint uniform_color_matrix; + GLuint frame_buffer; + GLuint program; + GLuint uniform_transform; + GLuint uniform_pixel_size; + GLuint uniform_texture; + GLuint uniform_color_matrix; - GLuint quad; + GLuint quad; }; GLES2Debayer * gles2_debayer_new(MPPixelFormat format) { - if (format != MP_PIXEL_FMT_BGGR8) { - return NULL; - } + if (format != MP_PIXEL_FMT_BGGR8) { + return NULL; + } - GLuint frame_buffer; - glGenFramebuffers(1, &frame_buffer); - check_gl(); + GLuint frame_buffer; + glGenFramebuffers(1, &frame_buffer); + check_gl(); - GLuint shaders[] = { - gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert", - GL_VERTEX_SHADER, NULL, 0), - gl_util_load_shader("/org/postmarketos/Megapixels/debayer.frag", - GL_FRAGMENT_SHADER, NULL, 0), - }; + GLuint shaders[] = { + gl_util_load_shader("/org/postmarketos/Megapixels/debayer.vert", + 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); - glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert"); - glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord"); - check_gl(); + GLuint program = gl_util_link_program(shaders, 2); + glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert"); + glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord"); + check_gl(); - GLES2Debayer *self = malloc(sizeof(GLES2Debayer)); - self->frame_buffer = frame_buffer; - self->program = program; + GLES2Debayer *self = malloc(sizeof(GLES2Debayer)); + self->frame_buffer = frame_buffer; + self->program = program; - self->uniform_transform = glGetUniformLocation(self->program, "transform"); - self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size"); - self->uniform_texture = glGetUniformLocation(self->program, "texture"); - self->uniform_color_matrix = - glGetUniformLocation(self->program, "color_matrix"); - check_gl(); + self->uniform_transform = glGetUniformLocation(self->program, "transform"); + self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size"); + self->uniform_texture = glGetUniformLocation(self->program, "texture"); + self->uniform_color_matrix = + glGetUniformLocation(self->program, "color_matrix"); + check_gl(); - self->quad = gl_util_new_quad(); + self->quad = gl_util_new_quad(); - return self; + return self; } void gles2_debayer_free(GLES2Debayer *self) { - glDeleteFramebuffers(1, &self->frame_buffer); + glDeleteFramebuffers(1, &self->frame_buffer); - glDeleteProgram(self->program); + glDeleteProgram(self->program); - free(self); + free(self); } void gles2_debayer_use(GLES2Debayer *self) { - glUseProgram(self->program); - check_gl(); + glUseProgram(self->program); + check_gl(); - gl_util_bind_quad(self->quad); + gl_util_bind_quad(self->quad); } void -gles2_debayer_configure(GLES2Debayer *self, const uint32_t dst_width, - const uint32_t dst_height, const uint32_t src_width, - const uint32_t src_height, const uint32_t rotation, - const bool mirrored, const float *colormatrix, - const uint8_t blacklevel) +gles2_debayer_configure(GLES2Debayer *self, + const uint32_t dst_width, + const uint32_t dst_height, + const uint32_t src_width, + const uint32_t src_height, + const uint32_t rotation, + const bool mirrored, + const float *colormatrix, + const uint8_t blacklevel) { - glViewport(0, 0, dst_width, dst_height); - check_gl(); + glViewport(0, 0, dst_width, dst_height); + check_gl(); - GLfloat rotation_list[4] = { 0, -1, 0, 1 }; - int rotation_index = 4 - rotation / 90; + GLfloat rotation_list[4] = { 0, -1, 0, 1 }; + int rotation_index = 4 - rotation / 90; - GLfloat sin_rot = rotation_list[rotation_index]; - GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4]; - GLfloat scale_x = mirrored ? 1 : -1; - GLfloat matrix[9] = { - // clang-format off + GLfloat sin_rot = rotation_list[rotation_index]; + GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4]; + GLfloat scale_x = mirrored ? 1 : -1; + GLfloat matrix[9] = { + // clang-format off cos_rot * scale_x, sin_rot, 0, -sin_rot * scale_x, cos_rot, 0, 0, 0, 1, - // clang-format on - }; - glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix); - check_gl(); + // clang-format on + }; + glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix); + check_gl(); - GLfloat pixel_size_x = 1.0f / src_width; - GLfloat pixel_size_y = 1.0f / src_height; - glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y); - check_gl(); + GLfloat pixel_size_x = 1.0f / src_width; + GLfloat pixel_size_y = 1.0f / src_height; + glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y); + check_gl(); - if (colormatrix) { - GLfloat transposed[9]; - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - transposed[i + j * 3] = colormatrix[j + i * 3]; + if (colormatrix) { + GLfloat transposed[9]; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + transposed[i + j * 3] = colormatrix[j + i * 3]; - glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, - transposed); - } else { - static const GLfloat identity[9] = { - // clang-format off + glUniformMatrix3fv( + self->uniform_color_matrix, 1, GL_FALSE, transposed); + } else { + static const GLfloat identity[9] = { + // clang-format off 1, 0, 0, 0, 1, 0, 0, 0, 1, - // clang-format on - }; - glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, - identity); - } - check_gl(); + // clang-format on + }; + glUniformMatrix3fv( + self->uniform_color_matrix, 1, GL_FALSE, identity); + } + check_gl(); } void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id) { - glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer); - glBindTexture(GL_TEXTURE_2D, dst_id); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - dst_id, 0); - check_gl(); + glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer); + glBindTexture(GL_TEXTURE_2D, dst_id); + glFramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0); + check_gl(); - assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, source_id); - glUniform1i(self->uniform_texture, 0); - check_gl(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, source_id); + glUniform1i(self->uniform_texture, 0); + check_gl(); - gl_util_draw_quad(self->quad); + gl_util_draw_quad(self->quad); } diff --git a/src/gles2_debayer.h b/src/gles2_debayer.h index 1b5f0d9..6984596 100644 --- a/src/gles2_debayer.h +++ b/src/gles2_debayer.h @@ -10,10 +10,14 @@ void gles2_debayer_free(GLES2Debayer *self); void gles2_debayer_use(GLES2Debayer *self); -void gles2_debayer_configure(GLES2Debayer *self, const uint32_t dst_width, - const uint32_t dst_height, const uint32_t src_width, - const uint32_t src_height, const uint32_t rotation, - const bool mirrored, const float *colormatrix, - const uint8_t blacklevel); +void gles2_debayer_configure(GLES2Debayer *self, + const uint32_t dst_width, + const uint32_t dst_height, + const uint32_t src_width, + const uint32_t src_height, + const uint32_t rotation, + const bool mirrored, + const float *colormatrix, + const uint8_t blacklevel); void gles2_debayer_process(GLES2Debayer *self, GLuint dst_id, GLuint source_id); diff --git a/src/io_pipeline.c b/src/io_pipeline.c index fa504cc..e40b9b7 100644 --- a/src/io_pipeline.c +++ b/src/io_pipeline.c @@ -14,51 +14,51 @@ #include struct media_link_info { - unsigned int source_entity_id; - unsigned int target_entity_id; - char source_fname[260]; - char target_fname[260]; + unsigned int source_entity_id; + unsigned int target_entity_id; + char source_fname[260]; + char target_fname[260]; }; struct camera_info { - size_t device_index; + size_t device_index; - unsigned int pad_id; + unsigned int pad_id; - char dev_fname[260]; - int fd; + char dev_fname[260]; + int fd; - MPCamera *camera; + MPCamera *camera; - MPFlash *flash; + MPFlash *flash; - int gain_ctrl; - int gain_max; + int gain_ctrl; + int gain_max; - bool has_auto_focus_continuous; - bool has_auto_focus_start; + bool has_auto_focus_continuous; + bool has_auto_focus_start; - // unsigned int entity_id; - // enum v4l2_buf_type type; + // unsigned int entity_id; + // enum v4l2_buf_type type; - // char media_dev_fname[260]; - // char video_dev_fname[260]; - // int media_fd; + // char media_dev_fname[260]; + // char video_dev_fname[260]; + // int media_fd; - // struct mp_media_link media_links[MP_MAX_LINKS]; - // int num_media_links; + // struct mp_media_link media_links[MP_MAX_LINKS]; + // int num_media_links; - // int gain_ctrl; + // int gain_ctrl; }; struct device_info { - const char *media_dev_name; // owned by camera config + const char *media_dev_name; // owned by camera config - MPDevice *device; + MPDevice *device; - unsigned int interface_pad_id; + unsigned int interface_pad_id; - int video_fd; + int video_fd; }; static struct camera_info cameras[MP_MAX_CAMERAS]; @@ -83,11 +83,11 @@ static int device_rotation; static bool save_dng; struct control_state { - bool gain_is_manual; - int gain; + bool gain_is_manual; + int gain; - bool exposure_is_manual; - int exposure; + bool exposure_is_manual; + int exposure; }; static struct control_state desired_controls = {}; @@ -103,288 +103,294 @@ static GSource *capture_source; static void setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config) { - // Find device info - size_t device_index = 0; - for (; device_index < num_devices; ++device_index) { - if (strcmp(config->media_dev_name, - devices[device_index].media_dev_name) == 0) { - break; - } - } + // Find device info + size_t device_index = 0; + for (; device_index < num_devices; ++device_index) { + if (strcmp(config->media_dev_name, + devices[device_index].media_dev_name) == 0) { + break; + } + } - if (device_index == num_devices) { - device_index = num_devices; + if (device_index == num_devices) { + device_index = num_devices; - // Initialize new device - struct device_info *info = &devices[device_index]; - info->media_dev_name = config->media_dev_name; - info->device = mp_device_list_find_remove(device_list, - info->media_dev_name); - if (!info->device) { - g_printerr("Could not find /dev/media* node matching '%s'\n", - info->media_dev_name); - exit(EXIT_FAILURE); - } + // Initialize new device + struct device_info *info = &devices[device_index]; + info->media_dev_name = config->media_dev_name; + info->device = mp_device_list_find_remove(device_list, + info->media_dev_name); + if (!info->device) { + g_printerr("Could not find /dev/media* node matching '%s'\n", + info->media_dev_name); + exit(EXIT_FAILURE); + } - const struct media_v2_entity *entity = - mp_device_find_entity_type(info->device, MEDIA_ENT_F_IO_V4L); - if (!entity) { - g_printerr("Could not find device video entity\n"); - exit(EXIT_FAILURE); - } + const struct media_v2_entity *entity = + mp_device_find_entity_type(info->device, MEDIA_ENT_F_IO_V4L); + if (!entity) { + g_printerr("Could not find device video entity\n"); + exit(EXIT_FAILURE); + } - const struct media_v2_pad *pad = - mp_device_get_pad_from_entity(info->device, entity->id); - info->interface_pad_id = pad->id; + const struct media_v2_pad *pad = + mp_device_get_pad_from_entity(info->device, entity->id); + info->interface_pad_id = pad->id; - const struct media_v2_interface *interface = - mp_device_find_entity_interface(info->device, entity->id); - char dev_name[260]; - if (!mp_find_device_path(interface->devnode, dev_name, 260)) { - g_printerr("Could not find video path\n"); - exit(EXIT_FAILURE); - } + const struct media_v2_interface *interface = + mp_device_find_entity_interface(info->device, entity->id); + char dev_name[260]; + if (!mp_find_device_path(interface->devnode, dev_name, 260)) { + g_printerr("Could not find video path\n"); + exit(EXIT_FAILURE); + } - info->video_fd = open(dev_name, O_RDWR); - if (info->video_fd == -1) { - g_printerr("Could not open %s: %s\n", dev_name, - strerror(errno)); - exit(EXIT_FAILURE); - } + info->video_fd = open(dev_name, O_RDWR); + if (info->video_fd == -1) { + g_printerr("Could not open %s: %s\n", + dev_name, + strerror(errno)); + exit(EXIT_FAILURE); + } - ++num_devices; - } + ++num_devices; + } - { - struct camera_info *info = &cameras[config->index]; - struct device_info *dev_info = &devices[device_index]; + { + struct camera_info *info = &cameras[config->index]; + struct device_info *dev_info = &devices[device_index]; - info->device_index = device_index; + info->device_index = device_index; - const struct media_v2_entity *entity = - mp_device_find_entity(dev_info->device, config->dev_name); - if (!entity) { - g_printerr("Could not find camera entity matching '%s'\n", - config->dev_name); - exit(EXIT_FAILURE); - } + const struct media_v2_entity *entity = + mp_device_find_entity(dev_info->device, config->dev_name); + if (!entity) { + g_printerr("Could not find camera entity matching '%s'\n", + config->dev_name); + exit(EXIT_FAILURE); + } - const struct media_v2_pad *pad = - mp_device_get_pad_from_entity(dev_info->device, entity->id); + const struct media_v2_pad *pad = + mp_device_get_pad_from_entity(dev_info->device, entity->id); - info->pad_id = pad->id; + info->pad_id = pad->id; - // Make sure the camera starts out as disabled - mp_device_setup_link(dev_info->device, info->pad_id, - dev_info->interface_pad_id, false); + // Make sure the camera starts out as disabled + mp_device_setup_link(dev_info->device, + info->pad_id, + dev_info->interface_pad_id, + false); - const struct media_v2_interface *interface = - mp_device_find_entity_interface(dev_info->device, - entity->id); + const struct media_v2_interface *interface = + mp_device_find_entity_interface(dev_info->device, + entity->id); - if (!mp_find_device_path(interface->devnode, info->dev_fname, 260)) { - g_printerr("Could not find camera device path\n"); - exit(EXIT_FAILURE); - } + if (!mp_find_device_path(interface->devnode, info->dev_fname, 260)) { + g_printerr("Could not find camera device path\n"); + exit(EXIT_FAILURE); + } - info->fd = open(info->dev_fname, O_RDWR); - if (info->fd == -1) { - g_printerr("Could not open %s: %s\n", info->dev_fname, - strerror(errno)); - exit(EXIT_FAILURE); - } + info->fd = open(info->dev_fname, O_RDWR); + if (info->fd == -1) { + g_printerr("Could not open %s: %s\n", + info->dev_fname, + strerror(errno)); + exit(EXIT_FAILURE); + } - info->camera = mp_camera_new(dev_info->video_fd, info->fd); + info->camera = mp_camera_new(dev_info->video_fd, info->fd); - // Start with the capture format, this works around a bug with - // the ov5640 driver where it won't allow setting the preview - // format initially. - MPCameraMode mode = config->capture_mode; - mp_camera_set_mode(info->camera, &mode); + // Start with the capture format, this works around a bug with + // the ov5640 driver where it won't allow setting the preview + // format initially. + MPCameraMode mode = config->capture_mode; + mp_camera_set_mode(info->camera, &mode); - // Trigger continuous auto focus if the sensor supports it - if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO, - NULL)) { - info->has_auto_focus_continuous = true; - mp_camera_control_set_bool_bg(info->camera, - V4L2_CID_FOCUS_AUTO, true); - } - if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_FOCUS_START, - NULL)) { - info->has_auto_focus_start = true; - } + // Trigger continuous auto focus if the sensor supports it + if (mp_camera_query_control( + info->camera, V4L2_CID_FOCUS_AUTO, NULL)) { + info->has_auto_focus_continuous = true; + mp_camera_control_set_bool_bg( + info->camera, V4L2_CID_FOCUS_AUTO, true); + } + if (mp_camera_query_control( + info->camera, V4L2_CID_AUTO_FOCUS_START, NULL)) { + info->has_auto_focus_start = true; + } - MPControl control; - if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) { - info->gain_ctrl = V4L2_CID_GAIN; - info->gain_max = control.max; - } else if (mp_camera_query_control( - info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) { - info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN; - info->gain_max = control.max; - } + MPControl control; + if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) { + info->gain_ctrl = V4L2_CID_GAIN; + info->gain_max = control.max; + } else if (mp_camera_query_control( + info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) { + info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN; + info->gain_max = control.max; + } - // Setup flash - if (config->flash_path[0]) { - info->flash = mp_led_flash_from_path(config->flash_path); - } else if (config->flash_display) { - info->flash = mp_create_display_flash(); - } else { - info->flash = NULL; - } - } + // Setup flash + if (config->flash_path[0]) { + info->flash = mp_led_flash_from_path(config->flash_path); + } else if (config->flash_display) { + info->flash = mp_create_display_flash(); + } else { + info->flash = NULL; + } + } } static void setup(MPPipeline *pipeline, const void *data) { - MPDeviceList *device_list = mp_device_list_new(); + MPDeviceList *device_list = mp_device_list_new(); - for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { - const struct mp_camera_config *config = mp_get_camera_config(i); - if (!config) { - break; - } + for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { + const struct mp_camera_config *config = mp_get_camera_config(i); + if (!config) { + break; + } - setup_camera(&device_list, config); - } + setup_camera(&device_list, config); + } - mp_device_list_free(device_list); + mp_device_list_free(device_list); } static void clean_cameras() { - for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { - struct camera_info *info = &cameras[i]; - if (info->camera) { - mp_camera_free(info->camera); - info->camera = NULL; - } - } + for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { + struct camera_info *info = &cameras[i]; + if (info->camera) { + mp_camera_free(info->camera); + info->camera = NULL; + } + } } void mp_io_pipeline_start() { - mp_process_pipeline_start(); + mp_process_pipeline_start(); - pipeline = mp_pipeline_new(); + pipeline = mp_pipeline_new(); - mp_pipeline_invoke(pipeline, setup, NULL, 0); + mp_pipeline_invoke(pipeline, setup, NULL, 0); } void mp_io_pipeline_stop() { - if (capture_source) { - g_source_destroy(capture_source); - } + if (capture_source) { + g_source_destroy(capture_source); + } - clean_cameras(); + clean_cameras(); - mp_pipeline_free(pipeline); + mp_pipeline_free(pipeline); - mp_process_pipeline_stop(); + mp_process_pipeline_stop(); } static void update_process_pipeline() { - struct camera_info *info = &cameras[camera->index]; + struct camera_info *info = &cameras[camera->index]; - // Grab the latest control values - if (!current_controls.gain_is_manual) { - current_controls.gain = - mp_camera_control_get_int32(info->camera, info->gain_ctrl); - } - if (!current_controls.exposure_is_manual) { - current_controls.exposure = - mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); - } + // Grab the latest control values + if (!current_controls.gain_is_manual) { + current_controls.gain = + mp_camera_control_get_int32(info->camera, info->gain_ctrl); + } + if (!current_controls.exposure_is_manual) { + current_controls.exposure = + mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); + } - struct mp_process_pipeline_state pipeline_state = { - .camera = camera, - .mode = mode, - .burst_length = burst_length, - .save_dng = save_dng, - .preview_width = preview_width, - .preview_height = preview_height, - .device_rotation = device_rotation, - .gain_is_manual = current_controls.gain_is_manual, - .gain = current_controls.gain, - .gain_max = info->gain_max, - .exposure_is_manual = current_controls.exposure_is_manual, - .exposure = current_controls.exposure, - .has_auto_focus_continuous = info->has_auto_focus_continuous, - .has_auto_focus_start = info->has_auto_focus_start, - }; - mp_process_pipeline_update_state(&pipeline_state); + struct mp_process_pipeline_state pipeline_state = { + .camera = camera, + .mode = mode, + .burst_length = burst_length, + .save_dng = save_dng, + .preview_width = preview_width, + .preview_height = preview_height, + .device_rotation = device_rotation, + .gain_is_manual = current_controls.gain_is_manual, + .gain = current_controls.gain, + .gain_max = info->gain_max, + .exposure_is_manual = current_controls.exposure_is_manual, + .exposure = current_controls.exposure, + .has_auto_focus_continuous = info->has_auto_focus_continuous, + .has_auto_focus_start = info->has_auto_focus_start, + }; + mp_process_pipeline_update_state(&pipeline_state); } static void focus(MPPipeline *pipeline, const void *data) { - want_focus = true; + want_focus = true; } void mp_io_pipeline_focus() { - mp_pipeline_invoke(pipeline, focus, NULL, 0); + mp_pipeline_invoke(pipeline, focus, NULL, 0); } static void capture(MPPipeline *pipeline, const void *data) { - struct camera_info *info = &cameras[camera->index]; + struct camera_info *info = &cameras[camera->index]; - captures_remaining = burst_length; + captures_remaining = burst_length; - // Disable the autogain/exposure while taking the burst - mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0); - mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, - V4L2_EXPOSURE_MANUAL); + // Disable the autogain/exposure while taking the burst + mp_camera_control_set_int32(info->camera, V4L2_CID_AUTOGAIN, 0); + mp_camera_control_set_int32( + info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL); - // Change camera mode for capturing - mp_process_pipeline_sync(); - mp_camera_stop_capture(info->camera); + // Change camera mode for capturing + mp_process_pipeline_sync(); + mp_camera_stop_capture(info->camera); - mode = camera->capture_mode; - mp_camera_set_mode(info->camera, &mode); - just_switched_mode = true; + mode = camera->capture_mode; + mp_camera_set_mode(info->camera, &mode); + just_switched_mode = true; - mp_camera_start_capture(info->camera); + mp_camera_start_capture(info->camera); - // Enable flash - if (info->flash && flash_enabled) { - mp_flash_enable(info->flash); - } + // Enable flash + if (info->flash && flash_enabled) { + mp_flash_enable(info->flash); + } - update_process_pipeline(); + update_process_pipeline(); - mp_process_pipeline_capture(); + mp_process_pipeline_capture(); } void mp_io_pipeline_capture() { - mp_pipeline_invoke(pipeline, capture, NULL, 0); + mp_pipeline_invoke(pipeline, capture, NULL, 0); } static void release_buffer(MPPipeline *pipeline, const uint32_t *buffer_index) { - struct camera_info *info = &cameras[camera->index]; + struct camera_info *info = &cameras[camera->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) { - 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; @@ -392,228 +398,238 @@ static pid_t start_focus_task = 0; static void start_focus(struct camera_info *info) { - // only run 1 manual focus at once - if (!mp_camera_check_task_complete(info->camera, start_focus_task) || - !mp_camera_check_task_complete(info->camera, focus_continuous_task)) - return; + // only run 1 manual focus at once + if (!mp_camera_check_task_complete(info->camera, start_focus_task) || + !mp_camera_check_task_complete(info->camera, focus_continuous_task)) + return; - if (info->has_auto_focus_continuous) { - focus_continuous_task = mp_camera_control_set_bool_bg( - info->camera, V4L2_CID_FOCUS_AUTO, 1); - } else if (info->has_auto_focus_start) { - start_focus_task = mp_camera_control_set_bool_bg( - info->camera, V4L2_CID_AUTO_FOCUS_START, 1); - } + if (info->has_auto_focus_continuous) { + focus_continuous_task = mp_camera_control_set_bool_bg( + info->camera, V4L2_CID_FOCUS_AUTO, 1); + } else if (info->has_auto_focus_start) { + start_focus_task = mp_camera_control_set_bool_bg( + info->camera, V4L2_CID_AUTO_FOCUS_START, 1); + } } static void update_controls() { - // Don't update controls while capturing - if (captures_remaining > 0) { - return; - } + // Don't update controls while capturing + if (captures_remaining > 0) { + return; + } - struct camera_info *info = &cameras[camera->index]; + struct camera_info *info = &cameras[camera->index]; - if (want_focus) { - start_focus(info); - want_focus = false; - } + if (want_focus) { + start_focus(info); + want_focus = false; + } - if (current_controls.gain_is_manual != desired_controls.gain_is_manual) { - mp_camera_control_set_bool_bg(info->camera, V4L2_CID_AUTOGAIN, - !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, + !desired_controls.gain_is_manual); + } - if (desired_controls.gain_is_manual && - current_controls.gain != desired_controls.gain) { - mp_camera_control_set_int32_bg(info->camera, info->gain_ctrl, - desired_controls.gain); - } + if (desired_controls.gain_is_manual && + current_controls.gain != desired_controls.gain) { + mp_camera_control_set_int32_bg( + info->camera, info->gain_ctrl, desired_controls.gain); + } - if (current_controls.exposure_is_manual != - desired_controls.exposure_is_manual) { - mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE_AUTO, - desired_controls.exposure_is_manual ? - V4L2_EXPOSURE_MANUAL : - V4L2_EXPOSURE_AUTO); - } + if (current_controls.exposure_is_manual != + desired_controls.exposure_is_manual) { + mp_camera_control_set_int32_bg(info->camera, + V4L2_CID_EXPOSURE_AUTO, + desired_controls.exposure_is_manual ? + V4L2_EXPOSURE_MANUAL : + V4L2_EXPOSURE_AUTO); + } - if (desired_controls.exposure_is_manual && - current_controls.exposure != desired_controls.exposure) { - mp_camera_control_set_int32_bg(info->camera, V4L2_CID_EXPOSURE, - desired_controls.exposure); - } + if (desired_controls.exposure_is_manual && + current_controls.exposure != desired_controls.exposure) { + mp_camera_control_set_int32_bg( + info->camera, V4L2_CID_EXPOSURE, desired_controls.exposure); + } - current_controls = desired_controls; + current_controls = desired_controls; } static void on_frame(MPBuffer buffer, void *_data) { - // Only update controls right after a frame was captured - update_controls(); + // Only update controls right after a frame was captured + update_controls(); - // When the mode is switched while capturing we get a couple blank frames, - // presumably from buffers made ready during the switch. Ignore these. - if (just_switched_mode) { - if (blank_frame_count < 20) { - // Only check a 10x10 area - size_t test_size = - MIN(10, mode.width) * MIN(10, mode.height); + // When the mode is switched while capturing we get a couple blank frames, + // presumably from buffers made ready during the switch. Ignore these. + if (just_switched_mode) { + if (blank_frame_count < 20) { + // Only check a 10x10 area + size_t test_size = + MIN(10, mode.width) * MIN(10, mode.height); - bool image_is_blank = true; - for (size_t i = 0; i < test_size; ++i) { - if (buffer.data[i] != 0) { - image_is_blank = false; - } - } + bool image_is_blank = true; + for (size_t i = 0; i < test_size; ++i) { + if (buffer.data[i] != 0) { + image_is_blank = false; + } + } - if (image_is_blank) { - ++blank_frame_count; - return; - } - } else { - printf("Blank image limit reached, resulting capture may be blank\n"); - } + if (image_is_blank) { + ++blank_frame_count; + return; + } + } else { + printf("Blank image limit reached, resulting capture may be blank\n"); + } - just_switched_mode = false; - blank_frame_count = 0; - } + just_switched_mode = false; + blank_frame_count = 0; + } - // Send the image off for processing - mp_process_pipeline_process_image(buffer); + // Send the image off for processing + mp_process_pipeline_process_image(buffer); - if (captures_remaining > 0) { - --captures_remaining; + if (captures_remaining > 0) { + --captures_remaining; - if (captures_remaining == 0) { - struct camera_info *info = &cameras[camera->index]; + if (captures_remaining == 0) { + struct camera_info *info = &cameras[camera->index]; - // Restore the auto exposure and gain if needed - if (!current_controls.exposure_is_manual) { - mp_camera_control_set_int32_bg( - info->camera, V4L2_CID_EXPOSURE_AUTO, - V4L2_EXPOSURE_AUTO); - } + // Restore the auto exposure and gain if needed + if (!current_controls.exposure_is_manual) { + mp_camera_control_set_int32_bg( + info->camera, + V4L2_CID_EXPOSURE_AUTO, + V4L2_EXPOSURE_AUTO); + } - if (!current_controls.gain_is_manual) { - mp_camera_control_set_bool_bg( - info->camera, V4L2_CID_AUTOGAIN, true); - } + if (!current_controls.gain_is_manual) { + mp_camera_control_set_bool_bg( + info->camera, V4L2_CID_AUTOGAIN, true); + } - // Go back to preview mode - mp_process_pipeline_sync(); - mp_camera_stop_capture(info->camera); + // Go back to preview mode + mp_process_pipeline_sync(); + mp_camera_stop_capture(info->camera); - mode = camera->preview_mode; - mp_camera_set_mode(info->camera, &mode); - just_switched_mode = true; + mode = camera->preview_mode; + mp_camera_set_mode(info->camera, &mode); + just_switched_mode = true; - mp_camera_start_capture(info->camera); + mp_camera_start_capture(info->camera); - // Disable flash - if (info->flash) { - mp_flash_disable(info->flash); - } + // Disable flash + if (info->flash) { + mp_flash_disable(info->flash); + } - update_process_pipeline(); - } - } + update_process_pipeline(); + } + } } static void update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state) { - // Make sure the state isn't updated more than it needs to be by checking - // whether this state change actually changes anything. - bool has_changed = false; + // Make sure the state isn't updated more than it needs to be by checking + // whether this state change actually changes anything. + bool has_changed = false; - if (camera != state->camera) { - has_changed = true; + if (camera != state->camera) { + has_changed = true; - if (camera) { - struct camera_info *info = &cameras[camera->index]; - struct device_info *dev_info = &devices[info->device_index]; + if (camera) { + struct camera_info *info = &cameras[camera->index]; + struct device_info *dev_info = &devices[info->device_index]; - mp_process_pipeline_sync(); - mp_camera_stop_capture(info->camera); - mp_device_setup_link(dev_info->device, info->pad_id, - dev_info->interface_pad_id, false); - } + mp_process_pipeline_sync(); + mp_camera_stop_capture(info->camera); + mp_device_setup_link(dev_info->device, + info->pad_id, + dev_info->interface_pad_id, + false); + } - if (capture_source) { - g_source_destroy(capture_source); - capture_source = NULL; - } + if (capture_source) { + g_source_destroy(capture_source); + capture_source = NULL; + } - camera = state->camera; + camera = state->camera; - if (camera) { - struct camera_info *info = &cameras[camera->index]; - struct device_info *dev_info = &devices[info->device_index]; + if (camera) { + struct camera_info *info = &cameras[camera->index]; + struct device_info *dev_info = &devices[info->device_index]; - mp_device_setup_link(dev_info->device, info->pad_id, - dev_info->interface_pad_id, true); + mp_device_setup_link(dev_info->device, + info->pad_id, + dev_info->interface_pad_id, + true); - mode = camera->preview_mode; - mp_camera_set_mode(info->camera, &mode); + mode = camera->preview_mode; + mp_camera_set_mode(info->camera, &mode); - mp_camera_start_capture(info->camera); - capture_source = mp_pipeline_add_capture_source( - pipeline, info->camera, on_frame, NULL); + mp_camera_start_capture(info->camera); + capture_source = mp_pipeline_add_capture_source( + pipeline, info->camera, on_frame, NULL); - current_controls.gain_is_manual = - mp_camera_control_get_bool(info->camera, - V4L2_CID_AUTOGAIN) == 0; - current_controls.gain = mp_camera_control_get_int32( - info->camera, info->gain_ctrl); + current_controls.gain_is_manual = + mp_camera_control_get_bool(info->camera, + V4L2_CID_AUTOGAIN) == 0; + current_controls.gain = mp_camera_control_get_int32( + info->camera, info->gain_ctrl); - current_controls.exposure_is_manual = - mp_camera_control_get_int32( - info->camera, V4L2_CID_EXPOSURE_AUTO) == - V4L2_EXPOSURE_MANUAL; - current_controls.exposure = mp_camera_control_get_int32( - info->camera, V4L2_CID_EXPOSURE); - } - } + current_controls.exposure_is_manual = + mp_camera_control_get_int32( + info->camera, V4L2_CID_EXPOSURE_AUTO) == + V4L2_EXPOSURE_MANUAL; + current_controls.exposure = mp_camera_control_get_int32( + info->camera, V4L2_CID_EXPOSURE); + } + } - has_changed = has_changed || burst_length != state->burst_length || - preview_width != state->preview_width || - preview_height != state->preview_height || - device_rotation != state->device_rotation; + has_changed = has_changed || burst_length != state->burst_length || + preview_width != state->preview_width || + preview_height != state->preview_height || + device_rotation != state->device_rotation; - burst_length = state->burst_length; - preview_width = state->preview_width; - preview_height = state->preview_height; - device_rotation = state->device_rotation; - save_dng = state->save_dng; + burst_length = state->burst_length; + preview_width = state->preview_width; + preview_height = state->preview_height; + device_rotation = state->device_rotation; + save_dng = state->save_dng; - if (camera) { - struct control_state previous_desired = desired_controls; + if (camera) { + struct control_state previous_desired = desired_controls; - desired_controls.gain_is_manual = state->gain_is_manual; - desired_controls.gain = state->gain; - desired_controls.exposure_is_manual = state->exposure_is_manual; - desired_controls.exposure = state->exposure; + desired_controls.gain_is_manual = state->gain_is_manual; + desired_controls.gain = state->gain; + desired_controls.exposure_is_manual = state->exposure_is_manual; + desired_controls.exposure = state->exposure; - has_changed = has_changed || - memcmp(&previous_desired, &desired_controls, - sizeof(struct control_state)) != 0 || - flash_enabled != state->flash_enabled; + has_changed = has_changed || + memcmp(&previous_desired, + &desired_controls, + sizeof(struct control_state)) != 0 || + flash_enabled != state->flash_enabled; - flash_enabled = state->flash_enabled; - } + flash_enabled = state->flash_enabled; + } - assert(has_changed); + assert(has_changed); - update_process_pipeline(); + update_process_pipeline(); } void mp_io_pipeline_update_state(const struct mp_io_pipeline_state *state) { - mp_pipeline_invoke(pipeline, (MPPipelineCallback)update_state, state, - sizeof(struct mp_io_pipeline_state)); + mp_pipeline_invoke(pipeline, + (MPPipelineCallback)update_state, + state, + sizeof(struct mp_io_pipeline_state)); } diff --git a/src/io_pipeline.h b/src/io_pipeline.h index 6e5ff28..cecb2dc 100644 --- a/src/io_pipeline.h +++ b/src/io_pipeline.h @@ -3,23 +3,23 @@ #include "camera_config.h" struct mp_io_pipeline_state { - const struct mp_camera_config *camera; + const struct mp_camera_config *camera; - int burst_length; + int burst_length; - int preview_width; - int preview_height; + int preview_width; + int preview_height; - int device_rotation; + int device_rotation; - bool gain_is_manual; - int gain; + bool gain_is_manual; + int gain; - bool exposure_is_manual; - int exposure; + bool exposure_is_manual; + int exposure; - bool save_dng; - bool flash_enabled; + bool save_dng; + bool flash_enabled; }; void mp_io_pipeline_start(); diff --git a/src/main.c b/src/main.c index fb71019..5dbf6ba 100644 --- a/src/main.c +++ b/src/main.c @@ -83,154 +83,166 @@ GSettings *settings; int remap(int value, int input_min, int input_max, int output_min, int output_max) { - const long long factor = 1000000000; - long long output_spread = output_max - output_min; - long long input_spread = input_max - input_min; + const long long factor = 1000000000; + long long output_spread = output_max - output_min; + long long input_spread = input_max - input_min; - long long zero_value = value - input_min; - zero_value *= factor; - long long percentage = zero_value / input_spread; + long long zero_value = value - input_min; + zero_value *= factor; + long long percentage = zero_value / input_spread; - long long zero_output = percentage * output_spread / factor; + long long zero_output = percentage * output_spread / factor; - long long result = output_min + zero_output; - return (int)result; + long long result = output_min + zero_output; + return (int)result; } static void update_io_pipeline() { - struct mp_io_pipeline_state io_state = { - .camera = camera, - .burst_length = burst_length, - .preview_width = preview_width, - .preview_height = preview_height, - .device_rotation = device_rotation, - .gain_is_manual = gain_is_manual, - .gain = gain, - .exposure_is_manual = exposure_is_manual, - .exposure = exposure, - .save_dng = setting_save_dng, - .flash_enabled = flash_enabled, - }; - mp_io_pipeline_update_state(&io_state); + struct mp_io_pipeline_state io_state = { + .camera = camera, + .burst_length = burst_length, + .preview_width = preview_width, + .preview_height = preview_height, + .device_rotation = device_rotation, + .gain_is_manual = gain_is_manual, + .gain = gain, + .exposure_is_manual = exposure_is_manual, + .exposure = exposure, + .save_dng = setting_save_dng, + .flash_enabled = flash_enabled, + }; + mp_io_pipeline_update_state(&io_state); - // Make the right settings available for the camera - gtk_widget_set_visible(flash_button, camera->has_flash); + // Make the right settings available for the camera + gtk_widget_set_visible(flash_button, camera->has_flash); } static bool update_state(const struct mp_main_state *state) { - if (!camera_is_initialized) { - camera_is_initialized = true; - } + if (!camera_is_initialized) { + camera_is_initialized = true; + } - if (camera == state->camera) { - mode = state->mode; + if (camera == state->camera) { + mode = state->mode; - if (!gain_is_manual) { - gain = state->gain; - } - gain_max = state->gain_max; + if (!gain_is_manual) { + gain = state->gain; + } + gain_max = state->gain_max; - if (!exposure_is_manual) { - exposure = state->exposure; - } + if (!exposure_is_manual) { + exposure = state->exposure; + } - has_auto_focus_continuous = state->has_auto_focus_continuous; - has_auto_focus_start = state->has_auto_focus_start; - } + has_auto_focus_continuous = state->has_auto_focus_continuous; + has_auto_focus_start = state->has_auto_focus_start; + } - preview_buffer_width = state->image_width; - preview_buffer_height = state->image_height; + preview_buffer_width = state->image_width; + preview_buffer_height = state->image_height; - return false; + return false; } void mp_main_update_state(const struct mp_main_state *state) { - struct mp_main_state *state_copy = malloc(sizeof(struct mp_main_state)); - *state_copy = *state; + struct mp_main_state *state_copy = malloc(sizeof(struct mp_main_state)); + *state_copy = *state; - g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)update_state, state_copy, free); + g_main_context_invoke_full(g_main_context_default(), + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)update_state, + state_copy, + free); } static bool set_zbar_result(MPZBarScanResult *result) { - if (zbar_result) { - for (uint8_t i = 0; i < zbar_result->size; ++i) { - free(zbar_result->codes[i].data); - } + if (zbar_result) { + for (uint8_t i = 0; i < zbar_result->size; ++i) { + free(zbar_result->codes[i].data); + } - free(zbar_result); - } + free(zbar_result); + } - zbar_result = result; - gtk_widget_queue_draw(preview); + zbar_result = result; + gtk_widget_queue_draw(preview); - return false; + return false; } void mp_main_set_zbar_result(MPZBarScanResult *result) { - g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)set_zbar_result, result, NULL); + g_main_context_invoke_full(g_main_context_default(), + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)set_zbar_result, + result, + NULL); } static bool set_preview(MPProcessPipelineBuffer *buffer) { - if (current_preview_buffer) { - mp_process_pipeline_buffer_unref(current_preview_buffer); - } - current_preview_buffer = buffer; - gtk_widget_queue_draw(preview); - return false; + if (current_preview_buffer) { + mp_process_pipeline_buffer_unref(current_preview_buffer); + } + current_preview_buffer = buffer; + gtk_widget_queue_draw(preview); + return false; } void mp_main_set_preview(MPProcessPipelineBuffer *buffer) { - g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)set_preview, buffer, NULL); + g_main_context_invoke_full(g_main_context_default(), + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)set_preview, + buffer, + NULL); } struct capture_completed_args { - GdkTexture *thumb; - char *fname; + GdkTexture *thumb; + char *fname; }; static bool capture_completed(struct capture_completed_args *args) { - strncpy(last_path, args->fname, 259); + strncpy(last_path, args->fname, 259); - gtk_image_set_from_paintable(GTK_IMAGE(thumb_last), - GDK_PAINTABLE(args->thumb)); + gtk_image_set_from_paintable(GTK_IMAGE(thumb_last), + GDK_PAINTABLE(args->thumb)); - gtk_spinner_stop(GTK_SPINNER(process_spinner)); - gtk_stack_set_visible_child(GTK_STACK(open_last_stack), thumb_last); + gtk_spinner_stop(GTK_SPINNER(process_spinner)); + gtk_stack_set_visible_child(GTK_STACK(open_last_stack), thumb_last); - g_object_unref(args->thumb); - g_free(args->fname); + g_object_unref(args->thumb); + g_free(args->fname); - return false; + return false; } void mp_main_capture_completed(GdkTexture *thumb, const char *fname) { - struct capture_completed_args *args = - malloc(sizeof(struct capture_completed_args)); - args->thumb = thumb; - args->fname = g_strdup(fname); - g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)capture_completed, args, free); + struct capture_completed_args *args = + malloc(sizeof(struct capture_completed_args)); + args->thumb = thumb; + args->fname = g_strdup(fname); + g_main_context_invoke_full(g_main_context_default(), + G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)capture_completed, + args, + free); } static GLuint blit_program; @@ -243,767 +255,852 @@ static GLuint quad; static void preview_realize(GtkGLArea *area) { - gtk_gl_area_make_current(area); + gtk_gl_area_make_current(area); - if (gtk_gl_area_get_error(area) != NULL) { - return; - } + if (gtk_gl_area_get_error(area) != NULL) { + return; + } - // Make a VAO for OpenGL - if (!gtk_gl_area_get_use_es(area)) { - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - check_gl(); - } + // Make a VAO for OpenGL + if (!gtk_gl_area_get_use_es(area)) { + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + check_gl(); + } - 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.frag", - GL_FRAGMENT_SHADER, NULL, 0), - }; + 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.frag", + GL_FRAGMENT_SHADER, + NULL, + 0), + }; - blit_program = gl_util_link_program(blit_shaders, 2); - glBindAttribLocation(blit_program, GL_UTIL_VERTEX_ATTRIBUTE, "vert"); - glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord"); - check_gl(); + blit_program = gl_util_link_program(blit_shaders, 2); + glBindAttribLocation(blit_program, GL_UTIL_VERTEX_ATTRIBUTE, "vert"); + glBindAttribLocation(blit_program, GL_UTIL_TEX_COORD_ATTRIBUTE, "tex_coord"); + check_gl(); - blit_uniform_transform = glGetUniformLocation(blit_program, "transform"); - blit_uniform_texture = glGetUniformLocation(blit_program, "texture"); + blit_uniform_transform = glGetUniformLocation(blit_program, "transform"); + blit_uniform_texture = glGetUniformLocation(blit_program, "texture"); - 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.frag", - GL_FRAGMENT_SHADER, NULL, 0), - }; + 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.frag", + GL_FRAGMENT_SHADER, + NULL, + 0), + }; - solid_program = gl_util_link_program(solid_shaders, 2); - glBindAttribLocation(solid_program, GL_UTIL_VERTEX_ATTRIBUTE, "vert"); - check_gl(); + solid_program = gl_util_link_program(solid_shaders, 2); + glBindAttribLocation(solid_program, GL_UTIL_VERTEX_ATTRIBUTE, "vert"); + check_gl(); - solid_uniform_color = glGetUniformLocation(solid_program, "color"); + solid_uniform_color = glGetUniformLocation(solid_program, "color"); - quad = gl_util_new_quad(); + quad = gl_util_new_quad(); } static void position_preview(float *offset_x, float *offset_y, float *size_x, float *size_y) { - int buffer_width, buffer_height; - if (device_rotation == 0 || device_rotation == 180) { - buffer_width = preview_buffer_width; - buffer_height = preview_buffer_height; - } else { - buffer_width = preview_buffer_height; - buffer_height = preview_buffer_width; - } + int buffer_width, buffer_height; + if (device_rotation == 0 || device_rotation == 180) { + buffer_width = preview_buffer_width; + buffer_height = preview_buffer_height; + } else { + buffer_width = preview_buffer_height; + buffer_height = preview_buffer_width; + } - int scale_factor = gtk_widget_get_scale_factor(preview); - int top_height = - 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 scale_factor = gtk_widget_get_scale_factor(preview); + int top_height = + 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; - 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_y = scale * buffer_height; + *size_x = scale * buffer_width; + *size_y = scale * buffer_height; - *offset_x = (preview_width - *size_x) / 2.0; + *offset_x = (preview_width - *size_x) / 2.0; - if (*size_y > inner_height) { - *offset_y = (preview_height - *size_y) / 2.0; - } else { - *offset_y = top_height + (inner_height - *size_y) / 2.0; - } + if (*size_y > inner_height) { + *offset_y = (preview_height - *size_y) / 2.0; + } else { + *offset_y = top_height + (inner_height - *size_y) / 2.0; + } } static gboolean preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data) { - if (gtk_gl_area_get_error(area) != NULL) { - return FALSE; - } + if (gtk_gl_area_get_error(area) != NULL) { + return FALSE; + } - if (!camera_is_initialized) { - return FALSE; - } + if (!camera_is_initialized) { + return FALSE; + } #ifdef RENDERDOC - if (rdoc_api) { - rdoc_api->StartFrameCapture(NULL, NULL); - } + if (rdoc_api) { + rdoc_api->StartFrameCapture(NULL, NULL); + } #endif - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); - float offset_x, offset_y, size_x, size_y; - position_preview(&offset_x, &offset_y, &size_x, &size_y); - glViewport(offset_x, preview_height - size_y - 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); + glViewport(offset_x, preview_height - size_y - offset_y, size_x, size_y); - if (current_preview_buffer) { - glUseProgram(blit_program); + if (current_preview_buffer) { + glUseProgram(blit_program); - GLfloat rotation_list[4] = { 0, -1, 0, 1 }; - int rotation_index = device_rotation / 90; + GLfloat rotation_list[4] = { 0, -1, 0, 1 }; + int rotation_index = device_rotation / 90; - GLfloat sin_rot = rotation_list[rotation_index]; - GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4]; - GLfloat matrix[9] = { - // clang-format off + GLfloat sin_rot = rotation_list[rotation_index]; + GLfloat cos_rot = rotation_list[(4 + rotation_index - 1) % 4]; + GLfloat matrix[9] = { + // clang-format off cos_rot, sin_rot, 0, -sin_rot, cos_rot, 0, 0, 0, 1, - // clang-format on - }; - glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix); - check_gl(); + // clang-format on + }; + glUniformMatrix3fv(blit_uniform_transform, 1, GL_FALSE, matrix); + check_gl(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, - mp_process_pipeline_buffer_get_texture_id( - current_preview_buffer)); - glUniform1i(blit_uniform_texture, 0); - check_gl(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, + mp_process_pipeline_buffer_get_texture_id( + current_preview_buffer)); + glUniform1i(blit_uniform_texture, 0); + check_gl(); - gl_util_bind_quad(quad); - gl_util_draw_quad(quad); - } + gl_util_bind_quad(quad); + gl_util_draw_quad(quad); + } - if (zbar_result) { - GLuint buffer; - if (!gtk_gl_area_get_use_es(area)) { - glGenBuffers(1, &buffer); - glBindBuffer(GL_ARRAY_BUFFER, buffer); - check_gl(); - } + if (zbar_result) { + GLuint buffer; + if (!gtk_gl_area_get_use_es(area)) { + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + check_gl(); + } - glUseProgram(solid_program); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glUseProgram(solid_program); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUniform4f(solid_uniform_color, 1, 0, 0, 0.5); + glUniform4f(solid_uniform_color, 1, 0, 0, 0.5); - for (uint8_t i = 0; i < zbar_result->size; ++i) { - MPZBarCode *code = &zbar_result->codes[i]; + for (uint8_t i = 0; i < zbar_result->size; ++i) { + MPZBarCode *code = &zbar_result->codes[i]; - GLfloat vertices[] = { - code->bounds_x[0], code->bounds_y[0], - code->bounds_x[1], code->bounds_y[1], - code->bounds_x[3], code->bounds_y[3], - code->bounds_x[2], code->bounds_y[2], - }; + GLfloat vertices[] = { + code->bounds_x[0], code->bounds_y[0], + code->bounds_x[1], code->bounds_y[1], + code->bounds_x[3], code->bounds_y[3], + code->bounds_x[2], code->bounds_y[2], + }; - for (int i = 0; i < 4; ++i) { - vertices[i * 2] = - 2 * vertices[i * 2] / preview_buffer_width - - 1.0; - vertices[i * 2 + 1] = - 1.0 - 2 * vertices[i * 2 + 1] / - preview_buffer_height; - } + for (int i = 0; i < 4; ++i) { + vertices[i * 2] = + 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)) { - glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, - GL_FLOAT, 0, 0, vertices); - check_gl(); - glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); - check_gl(); - } else { - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), - vertices, GL_STREAM_DRAW); - check_gl(); + if (gtk_gl_area_get_use_es(area)) { + glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, + 2, + GL_FLOAT, + 0, + 0, + vertices); + check_gl(); + glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); + check_gl(); + } else { + glBufferData(GL_ARRAY_BUFFER, + sizeof(vertices), + vertices, + GL_STREAM_DRAW); + check_gl(); - glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, 2, - GL_FLOAT, GL_FALSE, 0, 0); - glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); - check_gl(); - } + glVertexAttribPointer(GL_UTIL_VERTEX_ATTRIBUTE, + 2, + GL_FLOAT, + GL_FALSE, + 0, + 0); + glEnableVertexAttribArray(GL_UTIL_VERTEX_ATTRIBUTE); + check_gl(); + } - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - check_gl(); - } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + check_gl(); + } - glDisable(GL_BLEND); - glBindBuffer(GL_ARRAY_BUFFER, 0); - } + glDisable(GL_BLEND); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } - glFlush(); + glFlush(); #ifdef RENDERDOC - if (rdoc_api) { - rdoc_api->EndFrameCapture(NULL, NULL); - } + if (rdoc_api) { + rdoc_api->EndFrameCapture(NULL, NULL); + } #endif - return FALSE; + return FALSE; } static gboolean preview_resize(GtkWidget *widget, int width, int height, gpointer data) { - if (preview_width != width || preview_height != height) { - preview_width = width; - preview_height = height; - update_io_pipeline(); - } + if (preview_width != width || preview_height != height) { + preview_width = width; + preview_height = height; + update_io_pipeline(); + } - return TRUE; + return TRUE; } void run_open_last_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - char uri[275]; - GError *error = NULL; + char uri[275]; + GError *error = NULL; - if (strlen(last_path) == 0) { - return; - } - sprintf(uri, "file://%s", last_path); - 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); - } + if (strlen(last_path) == 0) { + return; + } + sprintf(uri, "file://%s", last_path); + 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); + } } void run_open_photos_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - char uri[270]; - GError *error = NULL; - sprintf(uri, "file://%s", g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)); - if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) { - g_printerr("Could not launch image viewer: %s\n", error->message); - } + char uri[270]; + GError *error = NULL; + sprintf(uri, "file://%s", g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)); + if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) { + g_printerr("Could not launch image viewer: %s\n", error->message); + } } void run_capture_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - gtk_spinner_start(GTK_SPINNER(process_spinner)); - gtk_stack_set_visible_child(GTK_STACK(open_last_stack), process_spinner); - mp_io_pipeline_capture(); + gtk_spinner_start(GTK_SPINNER(process_spinner)); + gtk_stack_set_visible_child(GTK_STACK(open_last_stack), process_spinner); + mp_io_pipeline_capture(); } void run_about_action(GSimpleAction *action, GVariant *param, GApplication *app) { - gtk_show_about_dialog(NULL, "program-name", "Megapixels", "title", - "Megapixels", "logo-icon-name", - "org.postmarketos.Megapixels", "comments", - "The postmarketOS camera application", "website", - "https://sr.ht/~martijnbraam/megapixels", "version", - VERSION, "license-type", GTK_LICENSE_GPL_3_0_ONLY, - NULL); + gtk_show_about_dialog(NULL, + "program-name", + "Megapixels", + "title", + "Megapixels", + "logo-icon-name", + "org.postmarketos.Megapixels", + "comments", + "The postmarketOS camera application", + "website", + "https://sr.ht/~martijnbraam/megapixels", + "version", + VERSION, + "license-type", + GTK_LICENSE_GPL_3_0_ONLY, + NULL); } void run_quit_action(GSimpleAction *action, GVariant *param, GApplication *app) { - g_application_quit(app); + g_application_quit(app); } static bool check_point_inside_bounds(int x, int y, int *bounds_x, int *bounds_y) { - bool right = false, left = false, top = false, bottom = false; + bool right = false, left = false, top = false, bottom = false; - for (int i = 0; i < 4; ++i) { - if (x <= bounds_x[i]) - left = true; - if (x >= bounds_x[i]) - right = true; - if (y <= bounds_y[i]) - top = true; - if (y >= bounds_y[i]) - bottom = true; - } + for (int i = 0; i < 4; ++i) { + if (x <= bounds_x[i]) + left = true; + if (x >= bounds_x[i]) + right = true; + if (y <= bounds_y[i]) + top = true; + if (y >= bounds_y[i]) + bottom = true; + } - return right && left && top && bottom; + return right && left && top && bottom; } static void on_zbar_dialog_response(GtkDialog *dialog, int response, char *data) { - GError *error = NULL; - switch (response) { - case GTK_RESPONSE_YES: - if (!g_app_info_launch_default_for_uri(data, NULL, &error)) { - g_printerr("Could not launch application: %s\n", - 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: - break; - default: - g_printerr("Wrong dialog response: %d\n", response); - } + GError *error = NULL; + switch (response) { + case GTK_RESPONSE_YES: + if (!g_app_info_launch_default_for_uri(data, NULL, &error)) { + g_printerr("Could not launch application: %s\n", + 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: + break; + default: + g_printerr("Wrong dialog response: %d\n", response); + } - g_free(data); - gtk_window_destroy(GTK_WINDOW(dialog)); + g_free(data); + gtk_window_destroy(GTK_WINDOW(dialog)); } static void on_zbar_code_tapped(GtkWidget *widget, const MPZBarCode *code) { - GtkWidget *dialog; - GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; - bool data_is_url = - g_uri_is_valid(code->data, G_URI_FLAGS_PARSE_RELAXED, NULL); + GtkWidget *dialog; + GtkDialogFlags flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; + bool data_is_url = + 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) { - dialog = gtk_message_dialog_new( - GTK_WINDOW(gtk_widget_get_root(widget)), flags, - GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, - "Found a URL '%s' encoded in a %s.", code->data, code->type); - gtk_dialog_add_buttons(GTK_DIALOG(dialog), "_Open URL", - GTK_RESPONSE_YES, NULL); - } else { - dialog = gtk_message_dialog_new( - GTK_WINDOW(gtk_widget_get_root(widget)), flags, - GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, - "Found data encoded in a %s.", code->type); - gtk_message_dialog_format_secondary_markup( - GTK_MESSAGE_DIALOG(dialog), "%s", code->data); - } - gtk_dialog_add_buttons(GTK_DIALOG(dialog), "_Copy", GTK_RESPONSE_ACCEPT, - "_Cancel", GTK_RESPONSE_CANCEL, NULL); + if (data_is_url) { + dialog = gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_root(widget)), + flags, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "Found a URL '%s' encoded in a %s.", + code->data, + code->type); + gtk_dialog_add_buttons( + GTK_DIALOG(dialog), "_Open URL", GTK_RESPONSE_YES, NULL); + } else { + dialog = gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_root(widget)), + flags, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "Found data encoded in a %s.", + code->type); + gtk_message_dialog_format_secondary_markup( + GTK_MESSAGE_DIALOG(dialog), "%s", code->data); + } + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + "_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)); } static void preview_pressed(GtkGestureClick *gesture, int n_press, double x, double y) { - GtkWidget *widget = - gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); - int scale_factor = gtk_widget_get_scale_factor(widget); + GtkWidget *widget = + gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); + int scale_factor = gtk_widget_get_scale_factor(widget); - // Tapped zbar result - if (zbar_result) { - // Transform the event coordinates to the image - float offset_x, offset_y, size_x, size_y; - position_preview(&offset_x, &offset_y, &size_x, &size_y); + // Tapped zbar result + if (zbar_result) { + // Transform the event coordinates to the image + float 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_y = (y - offset_y) * scale_factor / size_y * - preview_buffer_height; + int zbar_x = (x - offset_x) * scale_factor / size_x * + 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) { - MPZBarCode *code = &zbar_result->codes[i]; + for (uint8_t i = 0; i < zbar_result->size; ++i) { + MPZBarCode *code = &zbar_result->codes[i]; - if (check_point_inside_bounds(zbar_x, zbar_y, code->bounds_x, - code->bounds_y)) { - on_zbar_code_tapped(widget, code); - return; - } - } - } + if (check_point_inside_bounds(zbar_x, + zbar_y, + code->bounds_x, + code->bounds_y)) { + on_zbar_code_tapped(widget, code); + return; + } + } + } - // Tapped preview image itself, try focussing - if (has_auto_focus_start) { - mp_io_pipeline_focus(); - } + // Tapped preview image itself, try focussing + if (has_auto_focus_start) { + mp_io_pipeline_focus(); + } } static void run_camera_switch_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - size_t next_index = camera->index + 1; - const struct mp_camera_config *next_camera = - mp_get_camera_config(next_index); + size_t next_index = camera->index + 1; + const struct mp_camera_config *next_camera = + mp_get_camera_config(next_index); - if (!next_camera) { - next_index = 0; - next_camera = mp_get_camera_config(next_index); - } + if (!next_camera) { + next_index = 0; + next_camera = mp_get_camera_config(next_index); + } - camera = next_camera; - update_io_pipeline(); + camera = next_camera; + update_io_pipeline(); } static void run_open_settings_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - gtk_stack_set_visible_child_name(GTK_STACK(main_stack), "settings"); + gtk_stack_set_visible_child_name(GTK_STACK(main_stack), "settings"); } static void run_close_settings_action(GSimpleAction *action, GVariant *param, gpointer user_data) { - gtk_stack_set_visible_child_name(GTK_STACK(main_stack), "main"); + gtk_stack_set_visible_child_name(GTK_STACK(main_stack), "main"); - // Update settings - bool save_dng = g_settings_get_boolean(settings, "save-raw"); + // Update settings + bool save_dng = g_settings_get_boolean(settings, "save-raw"); - if (save_dng != setting_save_dng) { - setting_save_dng = save_dng; - update_io_pipeline(); - } + if (save_dng != setting_save_dng) { + setting_save_dng = save_dng; + update_io_pipeline(); + } } static void on_controls_scale_changed(GtkAdjustment *adjustment, void (*set_fn)(double)) { - set_fn(gtk_adjustment_get_value(adjustment)); + set_fn(gtk_adjustment_get_value(adjustment)); } static void update_value(GtkAdjustment *adjustment, GtkLabel *label) { - char buf[12]; - snprintf(buf, 12, "%.0f", gtk_adjustment_get_value(adjustment)); - gtk_label_set_label(label, buf); + char buf[12]; + snprintf(buf, 12, "%.0f", gtk_adjustment_get_value(adjustment)); + gtk_label_set_label(label, buf); } static void on_auto_controls_toggled(GtkToggleButton *button, void (*set_auto_fn)(bool)) { - set_auto_fn(gtk_toggle_button_get_active(button)); + set_auto_fn(gtk_toggle_button_get_active(button)); } static void 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 -open_controls(GtkWidget *parent, const char *title_name, double min_value, - double max_value, double current, bool auto_enabled, - void (*set_fn)(double), void (*set_auto_fn)(bool)) +open_controls(GtkWidget *parent, + const char *title_name, + double min_value, + double max_value, + double current, + bool auto_enabled, + void (*set_fn)(double), + void (*set_auto_fn)(bool)) { - GtkBuilder *builder = gtk_builder_new_from_resource( - "/org/postmarketos/Megapixels/controls-popover.ui"); - GtkPopover *popover = - GTK_POPOVER(gtk_builder_get_object(builder, "controls")); - GtkScale *scale = GTK_SCALE(gtk_builder_get_object(builder, "scale")); - GtkLabel *title = GTK_LABEL(gtk_builder_get_object(builder, "title")); - GtkLabel *value_label = - GTK_LABEL(gtk_builder_get_object(builder, "value-label")); - GtkToggleButton *auto_button = - GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "auto-button")); + GtkBuilder *builder = gtk_builder_new_from_resource( + "/org/postmarketos/Megapixels/controls-popover.ui"); + GtkPopover *popover = + GTK_POPOVER(gtk_builder_get_object(builder, "controls")); + GtkScale *scale = GTK_SCALE(gtk_builder_get_object(builder, "scale")); + GtkLabel *title = GTK_LABEL(gtk_builder_get_object(builder, "title")); + GtkLabel *value_label = + 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); - GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(scale)); - gtk_adjustment_set_lower(adjustment, min_value); - gtk_adjustment_set_upper(adjustment, max_value); - gtk_adjustment_set_value(adjustment, current); - update_value(adjustment, value_label); + GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(scale)); + gtk_adjustment_set_lower(adjustment, min_value); + gtk_adjustment_set_upper(adjustment, max_value); + gtk_adjustment_set_value(adjustment, current); + update_value(adjustment, value_label); - gtk_toggle_button_set_active(auto_button, auto_enabled); - update_scale(auto_button, scale); + gtk_toggle_button_set_active(auto_button, auto_enabled); + 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_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(adjustment, + "value-changed", + G_CALLBACK(on_controls_scale_changed), + set_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); - gtk_widget_set_parent(GTK_WIDGET(popover), parent); - gtk_popover_popup(popover); - // g_object_unref(popover); + gtk_widget_set_parent(GTK_WIDGET(popover), parent); + gtk_popover_popup(popover); + // g_object_unref(popover); } static void set_gain(double value) { - if (gain != (int)value) { - gain = value; - update_io_pipeline(); - } + if (gain != (int)value) { + gain = value; + update_io_pipeline(); + } } static void set_gain_auto(bool is_auto) { - if (gain_is_manual != !is_auto) { - gain_is_manual = !is_auto; - update_io_pipeline(); - } + if (gain_is_manual != !is_auto) { + gain_is_manual = !is_auto; + update_io_pipeline(); + } } static void 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 set_shutter(double value) { - int new_exposure = (int)(value / 360.0 * camera->capture_mode.height); - if (new_exposure != exposure) { - exposure = new_exposure; - update_io_pipeline(); - } + int new_exposure = (int)(value / 360.0 * camera->capture_mode.height); + if (new_exposure != exposure) { + exposure = new_exposure; + update_io_pipeline(); + } } static void set_shutter_auto(bool is_auto) { - if (exposure_is_manual != !is_auto) { - exposure_is_manual = !is_auto; - update_io_pipeline(); - } + if (exposure_is_manual != !is_auto) { + exposure_is_manual = !is_auto; + update_io_pipeline(); + } } static void 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 flash_button_clicked(GtkWidget *button, gpointer user_data) { - flash_enabled = !flash_enabled; - update_io_pipeline(); + flash_enabled = !flash_enabled; + update_io_pipeline(); - const char *icon_name = - flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic"; - gtk_button_set_icon_name(GTK_BUTTON(button), icon_name); + const char *icon_name = + flash_enabled ? "flash-enabled-symbolic" : "flash-disabled-symbolic"; + gtk_button_set_icon_name(GTK_BUTTON(button), icon_name); } static void on_realize(GtkWidget *window, gpointer *data) { - GtkNative *native = gtk_widget_get_native(window); - mp_process_pipeline_init_gl(gtk_native_get_surface(native)); + GtkNative *native = gtk_widget_get_native(window); + mp_process_pipeline_init_gl(gtk_native_get_surface(native)); - camera = mp_get_camera_config(0); - update_io_pipeline(); + camera = mp_get_camera_config(0); + update_io_pipeline(); } static GSimpleAction * create_simple_action(GtkApplication *app, const char *name, GCallback callback) { - GSimpleAction *action = g_simple_action_new(name, NULL); - g_signal_connect(action, "activate", callback, app); - g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(action)); - return action; + GSimpleAction *action = g_simple_action_new(name, NULL); + g_signal_connect(action, "activate", callback, app); + g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(action)); + return action; } static void update_ui_rotation() { - if (device_rotation == 0 || device_rotation == 180) { - // Portrait - gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL); - gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), - GTK_ORIENTATION_VERTICAL); + if (device_rotation == 0 || device_rotation == 180) { + // Portrait + gtk_widget_set_halign(preview_top_box, GTK_ALIGN_FILL); + gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), + GTK_ORIENTATION_VERTICAL); - gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_FILL); - gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), - GTK_ORIENTATION_HORIZONTAL); + gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_FILL); + gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), + GTK_ORIENTATION_HORIZONTAL); - if (device_rotation == 0) { - gtk_widget_set_valign(preview_top_box, GTK_ALIGN_START); - gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_END); - } else { - gtk_widget_set_valign(preview_top_box, GTK_ALIGN_END); - gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_START); - } - } else { - // Landscape - gtk_widget_set_valign(preview_top_box, GTK_ALIGN_FILL); - gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), - GTK_ORIENTATION_HORIZONTAL); + if (device_rotation == 0) { + gtk_widget_set_valign(preview_top_box, GTK_ALIGN_START); + gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_END); + } else { + gtk_widget_set_valign(preview_top_box, GTK_ALIGN_END); + gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_START); + } + } else { + // Landscape + gtk_widget_set_valign(preview_top_box, GTK_ALIGN_FILL); + gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_top_box), + GTK_ORIENTATION_HORIZONTAL); - gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_FILL); - gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), - GTK_ORIENTATION_VERTICAL); + gtk_widget_set_valign(preview_bottom_box, GTK_ALIGN_FILL); + gtk_orientable_set_orientation(GTK_ORIENTABLE(preview_bottom_box), + GTK_ORIENTATION_VERTICAL); - if (device_rotation == 90) { - gtk_widget_set_halign(preview_top_box, GTK_ALIGN_END); - gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_START); - } else { - gtk_widget_set_halign(preview_top_box, GTK_ALIGN_START); - gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_END); - } - } + if (device_rotation == 90) { + gtk_widget_set_halign(preview_top_box, GTK_ALIGN_END); + gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_START); + } else { + gtk_widget_set_halign(preview_top_box, GTK_ALIGN_START); + gtk_widget_set_halign(preview_bottom_box, GTK_ALIGN_END); + } + } } static void display_config_received(GDBusConnection *conn, GAsyncResult *res, gpointer user_data) { - GError *error = NULL; - GVariant *result = g_dbus_connection_call_finish(conn, res, &error); + GError *error = NULL; + GVariant *result = g_dbus_connection_call_finish(conn, res, &error); - if (!result) { - printf("Failed to get display configuration: %s\n", error->message); - g_object_unref(error); - return; - } + if (!result) { + printf("Failed to get display configuration: %s\n", error->message); + g_object_unref(error); + return; + } - GVariant *configs = g_variant_get_child_value(result, 1); - if (g_variant_n_children(configs) == 0) { - return; - } + GVariant *configs = g_variant_get_child_value(result, 1); + if (g_variant_n_children(configs) == 0) { + return; + } - GVariant *config = g_variant_get_child_value(configs, 0); - GVariant *rot_config = g_variant_get_child_value(config, 7); - uint32_t rotation_index = g_variant_get_uint32(rot_config); + GVariant *config = g_variant_get_child_value(configs, 0); + GVariant *rot_config = g_variant_get_child_value(config, 7); + uint32_t rotation_index = g_variant_get_uint32(rot_config); - assert(rotation_index < 4); - int new_rotation = rotation_index * 90; + assert(rotation_index < 4); + int new_rotation = rotation_index * 90; - if (new_rotation != device_rotation) { - device_rotation = new_rotation; - update_io_pipeline(); - update_ui_rotation(); - } + if (new_rotation != device_rotation) { + device_rotation = new_rotation; + update_io_pipeline(); + update_ui_rotation(); + } - g_variant_unref(result); + g_variant_unref(result); } static void update_screen_rotation(GDBusConnection *conn) { - g_dbus_connection_call(conn, "org.gnome.Mutter.DisplayConfig", - "/org/gnome/Mutter/DisplayConfig", - "org.gnome.Mutter.DisplayConfig", "GetResources", - NULL, NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, - (GAsyncReadyCallback)display_config_received, NULL); + g_dbus_connection_call(conn, + "org.gnome.Mutter.DisplayConfig", + "/org/gnome/Mutter/DisplayConfig", + "org.gnome.Mutter.DisplayConfig", + "GetResources", + NULL, + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + NULL, + (GAsyncReadyCallback)display_config_received, + NULL); } static void -on_screen_rotate(GDBusConnection *conn, const gchar *sender_name, - const gchar *object_path, const gchar *interface_name, - const gchar *signal_name, GVariant *parameters, gpointer user_data) +on_screen_rotate(GDBusConnection *conn, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { - update_screen_rotation(conn); + update_screen_rotation(conn); } static void activate(GtkApplication *app, gpointer data) { - g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", - TRUE, NULL); + g_object_set(gtk_settings_get_default(), + "gtk-application-prefer-dark-theme", + TRUE, + NULL); - GdkDisplay *display = gdk_display_get_default(); - GtkIconTheme *icon_theme = gtk_icon_theme_get_for_display(display); - gtk_icon_theme_add_resource_path(icon_theme, "/org/postmarketos/Megapixels"); + GdkDisplay *display = gdk_display_get_default(); + GtkIconTheme *icon_theme = gtk_icon_theme_get_for_display(display); + gtk_icon_theme_add_resource_path(icon_theme, "/org/postmarketos/Megapixels"); - GtkCssProvider *provider = gtk_css_provider_new(); - gtk_css_provider_load_from_resource( - provider, "/org/postmarketos/Megapixels/camera.css"); - gtk_style_context_add_provider_for_display( - display, GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + GtkCssProvider *provider = gtk_css_provider_new(); + gtk_css_provider_load_from_resource( + provider, "/org/postmarketos/Megapixels/camera.css"); + gtk_style_context_add_provider_for_display( + display, + GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - GtkBuilder *builder = gtk_builder_new_from_resource( - "/org/postmarketos/Megapixels/camera.ui"); + GtkBuilder *builder = gtk_builder_new_from_resource( + "/org/postmarketos/Megapixels/camera.ui"); - GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); - GtkWidget *iso_button = - GTK_WIDGET(gtk_builder_get_object(builder, "iso-controls-button")); - GtkWidget *shutter_button = GTK_WIDGET( - 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")); - main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_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")); - process_spinner = - GTK_WIDGET(gtk_builder_get_object(builder, "process_spinner")); - scanned_codes = GTK_WIDGET(gtk_builder_get_object(builder, "scanned-codes")); - preview_top_box = GTK_WIDGET(gtk_builder_get_object(builder, "top-box")); - preview_bottom_box = - GTK_WIDGET(gtk_builder_get_object(builder, "bottom-box")); + GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); + GtkWidget *iso_button = + GTK_WIDGET(gtk_builder_get_object(builder, "iso-controls-button")); + GtkWidget *shutter_button = GTK_WIDGET( + 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")); + main_stack = GTK_WIDGET(gtk_builder_get_object(builder, "main_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")); + process_spinner = + GTK_WIDGET(gtk_builder_get_object(builder, "process_spinner")); + scanned_codes = GTK_WIDGET(gtk_builder_get_object(builder, "scanned-codes")); + preview_top_box = GTK_WIDGET(gtk_builder_get_object(builder, "top-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); - g_signal_connect(preview, "realize", G_CALLBACK(preview_realize), NULL); - g_signal_connect(preview, "render", G_CALLBACK(preview_draw), NULL); - g_signal_connect(preview, "resize", G_CALLBACK(preview_resize), NULL); - GtkGesture *click = gtk_gesture_click_new(); - g_signal_connect(click, "pressed", G_CALLBACK(preview_pressed), NULL); - gtk_widget_add_controller(preview, GTK_EVENT_CONTROLLER(click)); + g_signal_connect(preview, "realize", G_CALLBACK(preview_realize), NULL); + g_signal_connect(preview, "render", G_CALLBACK(preview_draw), NULL); + g_signal_connect(preview, "resize", G_CALLBACK(preview_resize), NULL); + GtkGesture *click = gtk_gesture_click_new(); + g_signal_connect(click, "pressed", G_CALLBACK(preview_pressed), NULL); + gtk_widget_add_controller(preview, GTK_EVENT_CONTROLLER(click)); - 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(flash_button, "clicked", G_CALLBACK(flash_button_clicked), - 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( + flash_button, "clicked", G_CALLBACK(flash_button_clicked), NULL); - // Setup actions - 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, "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-photos", G_CALLBACK(run_open_photos_action)); - create_simple_action(app, "about", G_CALLBACK(run_about_action)); - create_simple_action(app, "quit", G_CALLBACK(run_quit_action)); + // Setup actions + 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, "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-photos", G_CALLBACK(run_open_photos_action)); + create_simple_action(app, "about", G_CALLBACK(run_about_action)); + create_simple_action(app, "quit", G_CALLBACK(run_quit_action)); - // Setup shortcuts - const char *capture_accels[] = { "space", NULL }; - gtk_application_set_accels_for_action(app, "app.capture", capture_accels); + // Setup shortcuts + const char *capture_accels[] = { "space", NULL }; + gtk_application_set_accels_for_action(app, "app.capture", capture_accels); - const char *quit_accels[] = { "q", "w", NULL }; - gtk_application_set_accels_for_action(app, "app.quit", quit_accels); + const char *quit_accels[] = { "q", "w", NULL }; + gtk_application_set_accels_for_action(app, "app.quit", quit_accels); - // Setup settings - settings = g_settings_new("org.postmarketos.Megapixels"); - g_settings_bind(settings, "save-raw", setting_dng_button, "active", - G_SETTINGS_BIND_DEFAULT); + // Setup settings + settings = g_settings_new("org.postmarketos.Megapixels"); + 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 - GDBusConnection *conn = - g_application_get_dbus_connection(G_APPLICATION(app)); - g_dbus_connection_signal_subscribe( - conn, NULL, "org.gnome.Mutter.DisplayConfig", "MonitorsChanged", - "/org/gnome/Mutter/DisplayConfig", NULL, G_DBUS_SIGNAL_FLAGS_NONE, - &on_screen_rotate, NULL, NULL); - update_screen_rotation(conn); + // Listen for phosh rotation + GDBusConnection *conn = + g_application_get_dbus_connection(G_APPLICATION(app)); + g_dbus_connection_signal_subscribe(conn, + NULL, + "org.gnome.Mutter.DisplayConfig", + "MonitorsChanged", + "/org/gnome/Mutter/DisplayConfig", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + &on_screen_rotate, + NULL, + NULL); + update_screen_rotation(conn); - // Initialize display flash - mp_flash_gtk_init(conn); + // Initialize display flash + mp_flash_gtk_init(conn); - mp_io_pipeline_start(); + mp_io_pipeline_start(); - gtk_application_add_window(app, GTK_WINDOW(window)); - gtk_widget_show(window); + gtk_application_add_window(app, GTK_WINDOW(window)); + gtk_widget_show(window); } static void shutdown(GApplication *app, gpointer data) { - // Only do cleanup in development, let the OS clean up otherwise + // Only do cleanup in development, let the OS clean up otherwise #ifdef DEBUG - mp_io_pipeline_stop(); - mp_flash_gtk_clean(); + mp_io_pipeline_stop(); + mp_flash_gtk_clean(); #endif } @@ -1011,31 +1108,31 @@ int main(int argc, char *argv[]) { #ifdef RENDERDOC - { - void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD); - if (mod) { - pRENDERDOC_GetAPI RENDERDOC_GetAPI = - (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI"); - int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, - (void **)&rdoc_api); - assert(ret == 1); - } else { - printf("Renderdoc not found\n"); - } - } + { + void *mod = dlopen("librenderdoc.so", RTLD_NOW | RTLD_NOLOAD); + if (mod) { + pRENDERDOC_GetAPI RENDERDOC_GetAPI = + (pRENDERDOC_GetAPI)dlsym(mod, "RENDERDOC_GetAPI"); + int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, + (void **)&rdoc_api); + assert(ret == 1); + } else { + printf("Renderdoc not found\n"); + } + } #endif - if (!mp_load_config()) - return 1; + if (!mp_load_config()) + return 1; - setenv("LC_NUMERIC", "C", 1); + setenv("LC_NUMERIC", "C", 1); - GtkApplication *app = gtk_application_new("org.postmarketos.Megapixels", 0); + GtkApplication *app = gtk_application_new("org.postmarketos.Megapixels", 0); - g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); - g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), NULL); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + g_signal_connect(app, "shutdown", G_CALLBACK(shutdown), NULL); - g_application_run(G_APPLICATION(app), argc, argv); + g_application_run(G_APPLICATION(app), argc, argv); - return 0; + return 0; } diff --git a/src/main.h b/src/main.h index bbebca9..6c8f4be 100644 --- a/src/main.h +++ b/src/main.h @@ -1,26 +1,26 @@ #pragma once #include "camera_config.h" -#include "zbar_pipeline.h" -#include "process_pipeline.h" #include "gtk/gtk.h" +#include "process_pipeline.h" +#include "zbar_pipeline.h" struct mp_main_state { - const struct mp_camera_config *camera; - MPCameraMode mode; + const struct mp_camera_config *camera; + MPCameraMode mode; - int image_width; - int image_height; + int image_width; + int image_height; - bool gain_is_manual; - int gain; - int gain_max; + bool gain_is_manual; + int gain; + int gain_max; - bool exposure_is_manual; - int exposure; + bool exposure_is_manual; + int exposure; - bool has_auto_focus_continuous; - bool has_auto_focus_start; + bool has_auto_focus_continuous; + bool has_auto_focus_start; }; void mp_main_update_state(const struct mp_main_state *state); diff --git a/src/matrix.c b/src/matrix.c index 7de9cb3..869aecd 100644 --- a/src/matrix.c +++ b/src/matrix.c @@ -3,24 +3,24 @@ void print_matrix(float m[9]) { - printf(" [%.2f %.2f %.2f] \n", m[0], m[1], m[2]); - printf(" [%.2f %.2f %.2f] \n", m[3], m[4], m[5]); - printf(" [%.2f %.2f %.2f] \n\n", m[6], m[7], m[8]); + printf(" [%.2f %.2f %.2f] \n", m[0], m[1], m[2]); + printf(" [%.2f %.2f %.2f] \n", m[3], m[4], m[5]); + printf(" [%.2f %.2f %.2f] \n\n", m[6], m[7], m[8]); } void multiply_matrices(float a[9], float b[9], float out[9]) { - // zero out target matrix - for (int i = 0; i < 9; i++) { - out[i] = 0; - } + // zero out target matrix + for (int i = 0; i < 9; i++) { + out[i] = 0; + } - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - for (int k = 0; k < 3; k++) { - out[i * 3 + j] += a[i * 3 + k] * b[k * 3 + j]; - } - } - } + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + for (int k = 0; k < 3; k++) { + out[i * 3 + j] += a[i * 3 + k] * b[k * 3 + j]; + } + } + } } diff --git a/src/pipeline.c b/src/pipeline.c index f8ef81b..11ed1e4 100644 --- a/src/pipeline.c +++ b/src/pipeline.c @@ -1,135 +1,144 @@ #include "pipeline.h" -#include -#include #include +#include +#include struct _MPPipeline { - GMainContext *main_context; - GMainLoop *main_loop; - pthread_t thread; + GMainContext *main_context; + GMainLoop *main_loop; + pthread_t thread; }; static void * thread_main_loop(void *arg) { - MPPipeline *pipeline = arg; + MPPipeline *pipeline = arg; - g_main_loop_run(pipeline->main_loop); - return NULL; + g_main_loop_run(pipeline->main_loop); + return NULL; } MPPipeline * mp_pipeline_new() { - MPPipeline *pipeline = malloc(sizeof(MPPipeline)); - pipeline->main_context = g_main_context_new(); - pipeline->main_loop = g_main_loop_new(pipeline->main_context, false); - int res = - pthread_create(&pipeline->thread, NULL, thread_main_loop, pipeline); - assert(res == 0); + MPPipeline *pipeline = malloc(sizeof(MPPipeline)); + pipeline->main_context = g_main_context_new(); + pipeline->main_loop = g_main_loop_new(pipeline->main_context, false); + int res = + pthread_create(&pipeline->thread, NULL, thread_main_loop, pipeline); + assert(res == 0); - return pipeline; + return pipeline; } struct invoke_args { - MPPipeline *pipeline; - MPPipelineCallback callback; + MPPipeline *pipeline; + MPPipelineCallback callback; }; static bool invoke_impl(struct invoke_args *args) { - args->callback(args->pipeline, args + 1); - return false; + args->callback(args->pipeline, args + 1); + return false; } void -mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, - const void *data, size_t size) +mp_pipeline_invoke(MPPipeline *pipeline, + MPPipelineCallback callback, + const void *data, + size_t size) { - if (pthread_self() != pipeline->thread) { - struct invoke_args *args = malloc(sizeof(struct invoke_args) + size); - args->pipeline = pipeline; - args->callback = callback; + if (pthread_self() != pipeline->thread) { + struct invoke_args *args = malloc(sizeof(struct invoke_args) + size); + args->pipeline = pipeline; + args->callback = callback; - if (size > 0) { - memcpy(args + 1, data, size); - } + if (size > 0) { + memcpy(args + 1, data, size); + } - g_main_context_invoke_full(pipeline->main_context, - G_PRIORITY_DEFAULT, - (GSourceFunc)invoke_impl, args, free); - } else { - callback(pipeline, data); - } + g_main_context_invoke_full(pipeline->main_context, + G_PRIORITY_DEFAULT, + (GSourceFunc)invoke_impl, + args, + free); + } else { + callback(pipeline, data); + } } static bool unlock_mutex(GMutex *mutex) { - g_mutex_unlock(mutex); - return false; + g_mutex_unlock(mutex); + return false; } void mp_pipeline_sync(MPPipeline *pipeline) { - GMutex mutex; - g_mutex_init(&mutex); - g_mutex_lock(&mutex); + GMutex mutex; + g_mutex_init(&mutex); + g_mutex_lock(&mutex); - g_main_context_invoke_full(pipeline->main_context, G_PRIORITY_LOW, - (GSourceFunc)unlock_mutex, &mutex, NULL); - g_mutex_lock(&mutex); - g_mutex_unlock(&mutex); + g_main_context_invoke_full(pipeline->main_context, + G_PRIORITY_LOW, + (GSourceFunc)unlock_mutex, + &mutex, + NULL); + g_mutex_lock(&mutex); + g_mutex_unlock(&mutex); - g_mutex_clear(&mutex); + g_mutex_clear(&mutex); } void mp_pipeline_free(MPPipeline *pipeline) { - g_main_loop_quit(pipeline->main_loop); + g_main_loop_quit(pipeline->main_loop); - // Force the main thread loop to wake up, otherwise we might not exit - g_main_context_wakeup(pipeline->main_context); + // Force the main thread loop to wake up, otherwise we might not exit + g_main_context_wakeup(pipeline->main_context); - void *r; - pthread_join(pipeline->thread, &r); - free(pipeline); + void *r; + pthread_join(pipeline->thread, &r); + free(pipeline); } struct capture_source_args { - MPCamera *camera; - void (*callback)(MPBuffer, void *); - void *user_data; + MPCamera *camera; + void (*callback)(MPBuffer, void *); + void *user_data; }; static bool on_capture(int fd, GIOCondition condition, struct capture_source_args *args) { - MPBuffer buffer; - if (mp_camera_capture_buffer(args->camera, &buffer)) { - args->callback(buffer, args->user_data); - } - return true; + MPBuffer buffer; + if (mp_camera_capture_buffer(args->camera, &buffer)) { + args->callback(buffer, args->user_data); + } + return true; } // Not thread safe GSource * -mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, - void (*callback)(MPBuffer, void *), void *user_data) +mp_pipeline_add_capture_source(MPPipeline *pipeline, + MPCamera *camera, + void (*callback)(MPBuffer, void *), + void *user_data) { - int video_fd = mp_camera_get_video_fd(camera); - GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN); + int video_fd = mp_camera_get_video_fd(camera); + GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN); - struct capture_source_args *args = - malloc(sizeof(struct capture_source_args)); - args->camera = camera; - args->callback = callback; - args->user_data = user_data; - g_source_set_callback(video_source, (GSourceFunc)on_capture, args, free); - g_source_attach(video_source, pipeline->main_context); - return video_source; + struct capture_source_args *args = + malloc(sizeof(struct capture_source_args)); + args->camera = camera; + args->callback = callback; + args->user_data = user_data; + g_source_set_callback(video_source, (GSourceFunc)on_capture, args, free); + g_source_attach(video_source, pipeline->main_context); + return video_source; } diff --git a/src/pipeline.h b/src/pipeline.h index 67eaeff..7a3c27a 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -9,12 +9,15 @@ typedef struct _MPPipeline MPPipeline; typedef void (*MPPipelineCallback)(MPPipeline *, const void *); MPPipeline *mp_pipeline_new(); -void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, - const void *data, size_t size); +void mp_pipeline_invoke(MPPipeline *pipeline, + MPPipelineCallback callback, + const void *data, + size_t size); // Wait until all pending tasks have completed void mp_pipeline_sync(MPPipeline *pipeline); void mp_pipeline_free(MPPipeline *pipeline); -GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, - void (*callback)(MPBuffer, void *), - void *user_data); +GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, + MPCamera *camera, + void (*callback)(MPBuffer, void *), + void *user_data); diff --git a/src/process_pipeline.c b/src/process_pipeline.c index 768696c..95a031c 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -1,15 +1,15 @@ #include "process_pipeline.h" -#include "pipeline.h" -#include "zbar_pipeline.h" -#include "io_pipeline.h" -#include "main.h" #include "config.h" #include "gles2_debayer.h" -#include +#include "io_pipeline.h" +#include "main.h" +#include "pipeline.h" +#include "zbar_pipeline.h" #include -#include #include +#include +#include #include "gl_util.h" #include @@ -17,7 +17,7 @@ #define TIFFTAG_FORWARDMATRIX1 50964 static const float colormatrix_srgb[] = { 3.2409, -1.5373, -0.4986, -0.9692, 1.8759, - 0.0415, 0.0556, -0.2039, 1.0569 }; + 0.0415, 0.0556, -0.2039, 1.0569 }; static MPPipeline *pipeline; @@ -58,113 +58,120 @@ static char capture_fname[255]; static void register_custom_tiff_tags(TIFF *tif) { - static const TIFFFieldInfo custom_fields[] = { - { TIFFTAG_FORWARDMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1, - "ForwardMatrix1" }, - }; + static const TIFFFieldInfo custom_fields[] = { + { TIFFTAG_FORWARDMATRIX1, + -1, + -1, + TIFF_SRATIONAL, + FIELD_CUSTOM, + 1, + 1, + "ForwardMatrix1" }, + }; - // Add missing dng fields - TIFFMergeFieldInfo(tif, custom_fields, - sizeof(custom_fields) / sizeof(custom_fields[0])); + // Add missing dng fields + TIFFMergeFieldInfo(tif, + custom_fields, + sizeof(custom_fields) / sizeof(custom_fields[0])); } static bool find_processor(char *script) { - char filename[] = "postprocess.sh"; + char filename[] = "postprocess.sh"; - // Check postprocess.sh in the current working directory - sprintf(script, "./data/%s", filename); - if (access(script, F_OK) != -1) { - sprintf(script, "./data/%s", filename); - printf("Found postprocessor script at %s\n", script); - return true; - } + // Check postprocess.sh in the current working directory + sprintf(script, "./data/%s", filename); + if (access(script, F_OK) != -1) { + sprintf(script, "./data/%s", filename); + printf("Found postprocessor script at %s\n", script); + return true; + } - // Check for a script in XDG_CONFIG_HOME - sprintf(script, "%s/megapixels/%s", g_get_user_config_dir(), filename); - if (access(script, F_OK) != -1) { - printf("Found postprocessor script at %s\n", script); - return true; - } + // Check for a script in XDG_CONFIG_HOME + sprintf(script, "%s/megapixels/%s", g_get_user_config_dir(), filename); + if (access(script, F_OK) != -1) { + printf("Found postprocessor script at %s\n", script); + return true; + } - // Check user overridden /etc/megapixels/postprocessor.sh - sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename); - if (access(script, F_OK) != -1) { - printf("Found postprocessor script at %s\n", script); - return true; - } + // Check user overridden /etc/megapixels/postprocessor.sh + sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename); + if (access(script, F_OK) != -1) { + printf("Found postprocessor script at %s\n", script); + return true; + } - // Check packaged /usr/share/megapixels/postprocessor.sh - sprintf(script, "%s/megapixels/%s", DATADIR, filename); - if (access(script, F_OK) != -1) { - printf("Found postprocessor script at %s\n", script); - return true; - } + // Check packaged /usr/share/megapixels/postprocessor.sh + sprintf(script, "%s/megapixels/%s", DATADIR, filename); + if (access(script, F_OK) != -1) { + printf("Found postprocessor script at %s\n", script); + return true; + } - return false; + return false; } static void setup(MPPipeline *pipeline, const void *data) { - TIFFSetTagExtender(register_custom_tiff_tags); + TIFFSetTagExtender(register_custom_tiff_tags); - if (!find_processor(processing_script)) { - g_printerr("Could not find any post-process script\n"); - exit(1); - } + if (!find_processor(processing_script)) { + g_printerr("Could not find any post-process script\n"); + exit(1); + } } void mp_process_pipeline_start() { - pipeline = mp_pipeline_new(); + pipeline = mp_pipeline_new(); - mp_pipeline_invoke(pipeline, setup, NULL, 0); + mp_pipeline_invoke(pipeline, setup, NULL, 0); - mp_zbar_pipeline_start(); + mp_zbar_pipeline_start(); } void mp_process_pipeline_stop() { - mp_pipeline_free(pipeline); + mp_pipeline_free(pipeline); - mp_zbar_pipeline_stop(); + mp_zbar_pipeline_stop(); } void mp_process_pipeline_sync() { - mp_pipeline_sync(pipeline); + mp_pipeline_sync(pipeline); } #define NUM_BUFFERS 4 struct _MPProcessPipelineBuffer { - GLuint texture_id; + GLuint texture_id; - _Atomic(int) refcount; + _Atomic(int) refcount; }; static MPProcessPipelineBuffer output_buffers[NUM_BUFFERS]; void mp_process_pipeline_buffer_ref(MPProcessPipelineBuffer *buf) { - ++buf->refcount; + ++buf->refcount; } void mp_process_pipeline_buffer_unref(MPProcessPipelineBuffer *buf) { - --buf->refcount; + --buf->refcount; } uint32_t mp_process_pipeline_buffer_get_texture_id(MPProcessPipelineBuffer *buf) { - return buf->texture_id; + return buf->texture_id; } static GLES2Debayer *gles2_debayer = NULL; @@ -181,584 +188,637 @@ extern RENDERDOC_API_1_1_2 *rdoc_api; static void init_gl(MPPipeline *pipeline, GdkSurface **surface) { - GError *error = NULL; - context = gdk_surface_create_gl_context(*surface, &error); - if (context == NULL) { - printf("Failed to initialize OpenGL context: %s\n", error->message); - g_clear_error(&error); - return; - } + GError *error = NULL; + context = gdk_surface_create_gl_context(*surface, &error); + if (context == NULL) { + printf("Failed to initialize OpenGL context: %s\n", error->message); + g_clear_error(&error); + return; + } - gdk_gl_context_set_use_es(context, true); - gdk_gl_context_set_required_version(context, 2, 0); - gdk_gl_context_set_forward_compatible(context, false); + gdk_gl_context_set_use_es(context, true); + gdk_gl_context_set_required_version(context, 2, 0); + gdk_gl_context_set_forward_compatible(context, false); #ifdef DEBUG - gdk_gl_context_set_debug_enabled(context, true); + gdk_gl_context_set_debug_enabled(context, true); #else - gdk_gl_context_set_debug_enabled(context, false); + gdk_gl_context_set_debug_enabled(context, false); #endif - gdk_gl_context_realize(context, &error); - if (error != NULL) { - printf("Failed to create OpenGL context: %s\n", error->message); - g_clear_object(&context); - g_clear_error(&error); - return; - } + gdk_gl_context_realize(context, &error); + if (error != NULL) { + printf("Failed to create OpenGL context: %s\n", error->message); + g_clear_object(&context); + g_clear_error(&error); + return; + } - gdk_gl_context_make_current(context); - check_gl(); + gdk_gl_context_make_current(context); + check_gl(); - // Make a VAO for OpenGL - if (!gdk_gl_context_get_use_es(context)) { - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - check_gl(); - } + // Make a VAO for OpenGL + if (!gdk_gl_context_get_use_es(context)) { + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + check_gl(); + } - gles2_debayer = gles2_debayer_new(MP_PIXEL_FMT_BGGR8); - check_gl(); + gles2_debayer = gles2_debayer_new(MP_PIXEL_FMT_BGGR8); + check_gl(); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - check_gl(); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + check_gl(); - gles2_debayer_use(gles2_debayer); + gles2_debayer_use(gles2_debayer); - for (size_t i = 0; i < NUM_BUFFERS; ++i) { - glGenTextures(1, &output_buffers[i].texture_id); - glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } + for (size_t i = 0; i < NUM_BUFFERS; ++i) { + glGenTextures(1, &output_buffers[i].texture_id); + glBindTexture(GL_TEXTURE_2D, output_buffers[i].texture_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); - gboolean is_es = gdk_gl_context_get_use_es(context); - int major, minor; - gdk_gl_context_get_version(context, &major, &minor); + gboolean is_es = gdk_gl_context_get_use_es(context); + int 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 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 * process_image_for_preview(const uint8_t *image) { #ifdef PROFILE_DEBAYER - clock_t t1 = clock(); + clock_t t1 = clock(); #endif - // Pick an available buffer - MPProcessPipelineBuffer *output_buffer = NULL; - for (size_t i = 0; i < NUM_BUFFERS; ++i) { - if (output_buffers[i].refcount == 0) { - output_buffer = &output_buffers[i]; - } - } + // Pick an available buffer + MPProcessPipelineBuffer *output_buffer = NULL; + for (size_t i = 0; i < NUM_BUFFERS; ++i) { + if (output_buffers[i].refcount == 0) { + output_buffer = &output_buffers[i]; + } + } - if (output_buffer == NULL) { - return NULL; - } - assert(output_buffer != NULL); + if (output_buffer == NULL) { + return NULL; + } + assert(output_buffer != NULL); #ifdef RENDERDOC - if (rdoc_api) { - rdoc_api->StartFrameCapture(NULL, NULL); - } + if (rdoc_api) { + rdoc_api->StartFrameCapture(NULL, NULL); + } #endif - // Copy image to a GL texture. TODO: This can be avoided - GLuint input_texture; - glGenTextures(1, &input_texture); - glBindTexture(GL_TEXTURE_2D, input_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, mode.width, mode.height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, image); - check_gl(); + // Copy image to a GL texture. TODO: This can be avoided + GLuint input_texture; + glGenTextures(1, &input_texture); + glBindTexture(GL_TEXTURE_2D, input_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_LUMINANCE, + mode.width, + mode.height, + 0, + GL_LUMINANCE, + GL_UNSIGNED_BYTE, + image); + check_gl(); - gles2_debayer_process(gles2_debayer, output_buffer->texture_id, - input_texture); - check_gl(); + gles2_debayer_process( + gles2_debayer, output_buffer->texture_id, input_texture); + check_gl(); - glFinish(); + glFinish(); - glDeleteTextures(1, &input_texture); + glDeleteTextures(1, &input_texture); #ifdef PROFILE_DEBAYER - clock_t t2 = clock(); - printf("process_image_for_preview %fms\n", - (float)(t2 - t1) / CLOCKS_PER_SEC * 1000); + clock_t t2 = clock(); + printf("process_image_for_preview %fms\n", + (float)(t2 - t1) / CLOCKS_PER_SEC * 1000); #endif #ifdef RENDERDOC - if (rdoc_api) { - rdoc_api->EndFrameCapture(NULL, NULL); - } + if (rdoc_api) { + rdoc_api->EndFrameCapture(NULL, NULL); + } #endif - mp_process_pipeline_buffer_ref(output_buffer); - mp_main_set_preview(output_buffer); + mp_process_pipeline_buffer_ref(output_buffer); + mp_main_set_preview(output_buffer); - // Create a thumbnail from the preview for the last capture - GdkTexture *thumb = NULL; - if (captures_remaining == 1) { - printf("Making thumbnail\n"); + // Create a thumbnail from the preview for the last capture + GdkTexture *thumb = NULL; + if (captures_remaining == 1) { + 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); - check_gl(); + glReadPixels(0, + 0, + output_buffer_width, + output_buffer_height, + GL_RGBA, + GL_UNSIGNED_BYTE, + data); + check_gl(); - // Flip vertically - for (size_t y = 0; y < output_buffer_height / 2; ++y) { - for (size_t x = 0; x < output_buffer_width; ++x) { - uint32_t tmp = data[(output_buffer_height - y - 1) * - 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; - } - } + // Flip vertically + for (size_t y = 0; y < output_buffer_height / 2; ++y) { + for (size_t x = 0; x < output_buffer_width; ++x) { + uint32_t tmp = data[(output_buffer_height - y - 1) * + 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; + } + } - thumb = gdk_memory_texture_new( - output_buffer_width, output_buffer_height, - GDK_MEMORY_R8G8B8A8, g_bytes_new_take(data, size), - output_buffer_width * sizeof(uint32_t)); - } + thumb = gdk_memory_texture_new(output_buffer_width, + output_buffer_height, + GDK_MEMORY_R8G8B8A8, + g_bytes_new_take(data, size), + output_buffer_width * + sizeof(uint32_t)); + } - return thumb; + return thumb; } static void process_image_for_capture(const uint8_t *image, int count) { - time_t rawtime; - time(&rawtime); - struct tm tim = *(localtime(&rawtime)); + time_t rawtime; + time(&rawtime); + struct tm tim = *(localtime(&rawtime)); - char datetime[20] = { 0 }; - strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim); + char datetime[20] = { 0 }; + strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim); - char fname[255]; - sprintf(fname, "%s/%d.dng", burst_dir, count); + char fname[255]; + sprintf(fname, "%s/%d.dng", burst_dir, count); - TIFF *tif = TIFFOpen(fname, "w"); - if (!tif) { - printf("Could not open tiff\n"); - } + TIFF *tif = TIFFOpen(fname, "w"); + if (!tif) { + printf("Could not open tiff\n"); + } - // Define TIFF thumbnail - TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1); - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width >> 4); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height >> 4); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); - TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); - TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make()); - TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model()); - uint16_t orientation; - if (camera_rotation == 0) { - orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : - ORIENTATION_TOPLEFT; - } else if (camera_rotation == 90) { - orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : - ORIENTATION_LEFTBOT; - } else if (camera_rotation == 180) { - orientation = camera->mirrored ? ORIENTATION_BOTLEFT : - ORIENTATION_BOTRIGHT; - } else { - orientation = camera->mirrored ? ORIENTATION_LEFTTOP : - ORIENTATION_RIGHTTOP; - } - TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation); - TIFFSetField(tif, TIFFTAG_DATETIME, datetime); - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); - TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(tif, TIFFTAG_SOFTWARE, "Megapixels"); - long sub_offset = 0; - TIFFSetField(tif, TIFFTAG_SUBIFD, 1, &sub_offset); - TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0"); - TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0"); - char uniquecameramodel[255]; - sprintf(uniquecameramodel, "%s %s", mp_get_device_make(), - mp_get_device_model()); - TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, uniquecameramodel); - if (camera->colormatrix[0]) { - TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, camera->colormatrix); - } else { - TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, colormatrix_srgb); - } - if (camera->forwardmatrix[0]) { - TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9, camera->forwardmatrix); - } - static const float neutral[] = { 1.0, 1.0, 1.0 }; - TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); - TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21); - // Write black thumbnail, only windows uses this - { - unsigned char *buf = - (unsigned char *)calloc(1, (mode.width >> 4) * 3); - for (int row = 0; row < (mode.height >> 4); row++) { - TIFFWriteScanline(tif, buf, row, 0); - } - free(buf); - } - TIFFWriteDirectory(tif); + // Define TIFF thumbnail + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width >> 4); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height >> 4); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(tif, TIFFTAG_MAKE, mp_get_device_make()); + TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model()); + uint16_t orientation; + if (camera_rotation == 0) { + orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : + ORIENTATION_TOPLEFT; + } else if (camera_rotation == 90) { + orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : + ORIENTATION_LEFTBOT; + } else if (camera_rotation == 180) { + orientation = camera->mirrored ? ORIENTATION_BOTLEFT : + ORIENTATION_BOTRIGHT; + } else { + orientation = camera->mirrored ? ORIENTATION_LEFTTOP : + ORIENTATION_RIGHTTOP; + } + TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation); + TIFFSetField(tif, TIFFTAG_DATETIME, datetime); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_SOFTWARE, "Megapixels"); + long sub_offset = 0; + TIFFSetField(tif, TIFFTAG_SUBIFD, 1, &sub_offset); + TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0"); + TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0"); + char uniquecameramodel[255]; + sprintf(uniquecameramodel, + "%s %s", + mp_get_device_make(), + mp_get_device_model()); + TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, uniquecameramodel); + if (camera->colormatrix[0]) { + TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, camera->colormatrix); + } else { + TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, colormatrix_srgb); + } + if (camera->forwardmatrix[0]) { + TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9, camera->forwardmatrix); + } + static const float neutral[] = { 1.0, 1.0, 1.0 }; + TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); + TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21); + // Write black thumbnail, only windows uses this + { + unsigned char *buf = + (unsigned char *)calloc(1, (mode.width >> 4) * 3); + for (int row = 0; row < (mode.height >> 4); row++) { + TIFFWriteScanline(tif, buf, row, 0); + } + free(buf); + } + TIFFWriteDirectory(tif); - // Define main photo - TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, - mp_pixel_format_bits_per_pixel(mode.pixel_format)); - TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); - TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - static const short cfapatterndim[] = { 2, 2 }; - TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfapatterndim); + // Define main photo + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, mode.width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, mode.height); + TIFFSetField(tif, + TIFFTAG_BITSPERSAMPLE, + mp_pixel_format_bits_per_pixel(mode.pixel_format)); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + static const short cfapatterndim[] = { 2, 2 }; + TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfapatterndim); #if (TIFFLIB_VERSION < 20201219) && !LIBTIFF_CFA_PATTERN - TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR + TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR #else - TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, "\002\001\001\000"); // BGGR + TIFFSetField(tif, TIFFTAG_CFAPATTERN, 4, "\002\001\001\000"); // BGGR #endif - printf("TIFF version %d\n", TIFFLIB_VERSION); - int whitelevel = camera->whitelevel; - if (!whitelevel) { - whitelevel = - (1 << mp_pixel_format_pixel_depth(mode.pixel_format)) - 1; - } - TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel); - if (camera->blacklevel) { - const float blacklevel = camera->blacklevel; - TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &blacklevel); - } - TIFFCheckpointDirectory(tif); - printf("Writing frame to %s\n", fname); + printf("TIFF version %d\n", TIFFLIB_VERSION); + int whitelevel = camera->whitelevel; + if (!whitelevel) { + whitelevel = + (1 << mp_pixel_format_pixel_depth(mode.pixel_format)) - 1; + } + TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &whitelevel); + if (camera->blacklevel) { + const float blacklevel = camera->blacklevel; + TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &blacklevel); + } + TIFFCheckpointDirectory(tif); + printf("Writing frame to %s\n", fname); - 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); - } - TIFFWriteDirectory(tif); + 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); + } + TIFFWriteDirectory(tif); - // Add an EXIF block to the tiff - TIFFCreateEXIFDirectory(tif); - // 1 = manual, 2 = full auto, 3 = aperture priority, 4 = shutter priority - if (!exposure_is_manual) { - TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 2); - } else { - TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1); - } + // Add an EXIF block to the tiff + TIFFCreateEXIFDirectory(tif); + // 1 = manual, 2 = full auto, 3 = aperture priority, 4 = shutter priority + if (!exposure_is_manual) { + TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 2); + } else { + TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1); + } - TIFFSetField(tif, EXIFTAG_EXPOSURETIME, - (mode.frame_interval.numerator / - (float)mode.frame_interval.denominator) / - ((float)mode.height / (float)exposure)); - if (camera->iso_min && camera->iso_max) { - uint16_t isospeed = remap(gain - 1, 0, gain_max, camera->iso_min, - camera->iso_max); - TIFFSetField(tif, EXIFTAG_ISOSPEEDRATINGS, 1, &isospeed); - } - TIFFSetField(tif, EXIFTAG_FLASH, 0); + TIFFSetField(tif, + EXIFTAG_EXPOSURETIME, + (mode.frame_interval.numerator / + (float)mode.frame_interval.denominator) / + ((float)mode.height / (float)exposure)); + if (camera->iso_min && camera->iso_max) { + uint16_t isospeed = remap( + gain - 1, 0, gain_max, camera->iso_min, camera->iso_max); + TIFFSetField(tif, EXIFTAG_ISOSPEEDRATINGS, 1, &isospeed); + } + TIFFSetField(tif, EXIFTAG_FLASH, 0); - TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime); - TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime); - if (camera->fnumber) { - TIFFSetField(tif, EXIFTAG_FNUMBER, camera->fnumber); - } - if (camera->focallength) { - TIFFSetField(tif, EXIFTAG_FOCALLENGTH, camera->focallength); - } - if (camera->focallength && camera->cropfactor) { - TIFFSetField(tif, EXIFTAG_FOCALLENGTHIN35MMFILM, - (short)(camera->focallength * camera->cropfactor)); - } - uint64_t exif_offset = 0; - TIFFWriteCustomDirectory(tif, &exif_offset); - TIFFFreeDirectory(tif); + TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime); + TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime); + if (camera->fnumber) { + TIFFSetField(tif, EXIFTAG_FNUMBER, camera->fnumber); + } + if (camera->focallength) { + TIFFSetField(tif, EXIFTAG_FOCALLENGTH, camera->focallength); + } + if (camera->focallength && camera->cropfactor) { + TIFFSetField(tif, + EXIFTAG_FOCALLENGTHIN35MMFILM, + (short)(camera->focallength * camera->cropfactor)); + } + uint64_t exif_offset = 0; + TIFFWriteCustomDirectory(tif, &exif_offset); + TIFFFreeDirectory(tif); - // Update exif pointer - TIFFSetDirectory(tif, 0); - TIFFSetField(tif, TIFFTAG_EXIFIFD, exif_offset); - TIFFRewriteDirectory(tif); + // Update exif pointer + TIFFSetDirectory(tif, 0); + TIFFSetField(tif, TIFFTAG_EXIFIFD, exif_offset); + TIFFRewriteDirectory(tif); - TIFFClose(tif); + TIFFClose(tif); } static void post_process_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb) { - char *stdout; - g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL); + char *stdout; + g_subprocess_communicate_utf8_finish(proc, res, &stdout, NULL, NULL); - // The last line contains the file name - int end = strlen(stdout); - // Skip the newline at the end - stdout[--end] = '\0'; + // The last line contains the file name + int end = strlen(stdout); + // Skip the newline at the end + stdout[--end] = '\0'; - char *path = path = stdout + end - 1; - do { - if (*path == '\n') { - path++; - break; - } - --path; - } while (path > stdout); + char *path = path = stdout + end - 1; + do { + if (*path == '\n') { + path++; + break; + } + --path; + } while (path > stdout); - mp_main_capture_completed(thumb, path); + mp_main_capture_completed(thumb, path); } static void process_capture_burst(GdkTexture *thumb) { - time_t rawtime; - time(&rawtime); - struct tm tim = *(localtime(&rawtime)); + time_t rawtime; + time(&rawtime); + struct tm tim = *(localtime(&rawtime)); - char timestamp[30]; - strftime(timestamp, 30, "%Y%m%d%H%M%S", &tim); + char timestamp[30]; + strftime(timestamp, 30, "%Y%m%d%H%M%S", &tim); - if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) { - sprintf(capture_fname, "%s/IMG%s", - g_get_user_special_dir(G_USER_DIRECTORY_PICTURES), - timestamp); - } else if (getenv("XDG_PICTURES_DIR") != NULL) { - sprintf(capture_fname, "%s/IMG%s", getenv("XDG_PICTURES_DIR"), - timestamp); - } else { - sprintf(capture_fname, "%s/Pictures/IMG%s", getenv("HOME"), - timestamp); - } + if (g_get_user_special_dir(G_USER_DIRECTORY_PICTURES) != NULL) { + sprintf(capture_fname, + "%s/IMG%s", + g_get_user_special_dir(G_USER_DIRECTORY_PICTURES), + timestamp); + } else if (getenv("XDG_PICTURES_DIR") != NULL) { + sprintf(capture_fname, + "%s/IMG%s", + getenv("XDG_PICTURES_DIR"), + timestamp); + } else { + sprintf(capture_fname, + "%s/Pictures/IMG%s", + getenv("HOME"), + timestamp); + } - char save_dng_s[2] = "0"; - if (save_dng) { - save_dng_s[0] = '1'; - } + char save_dng_s[2] = "0"; + if (save_dng) { + save_dng_s[0] = '1'; + } - // 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); - GError *error = NULL; - GSubprocess *proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, - processing_script, burst_dir, - capture_fname, save_dng_s, NULL); + // 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); + GError *error = NULL; + GSubprocess *proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, + &error, + processing_script, + burst_dir, + capture_fname, + save_dng_s, + NULL); - if (!proc) { - g_printerr("Failed to spawn postprocess process: %s\n", - error->message); - return; - } + if (!proc) { + g_printerr("Failed to spawn postprocess process: %s\n", + error->message); + return; + } - g_subprocess_communicate_utf8_async( - proc, NULL, NULL, (GAsyncReadyCallback)post_process_finished, thumb); + g_subprocess_communicate_utf8_async( + proc, NULL, NULL, (GAsyncReadyCallback)post_process_finished, thumb); } static void process_image(MPPipeline *pipeline, const MPBuffer *buffer) { #ifdef PROFILE_PROCESS - clock_t t1 = clock(); + clock_t t1 = clock(); #endif - size_t size = mp_pixel_format_width_to_bytes(mode.pixel_format, mode.width) * - mode.height; - uint8_t *image = malloc(size); - memcpy(image, buffer->data, size); - mp_io_pipeline_release_buffer(buffer->index); + size_t size = mp_pixel_format_width_to_bytes(mode.pixel_format, mode.width) * + mode.height; + uint8_t *image = malloc(size); + memcpy(image, buffer->data, size); + 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); - mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image)); + 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)); #ifdef PROFILE_PROCESS - clock_t t2 = clock(); + clock_t t2 = clock(); #endif - GdkTexture *thumb = process_image_for_preview(image); + GdkTexture *thumb = process_image_for_preview(image); - if (captures_remaining > 0) { - int count = burst_length - captures_remaining; - --captures_remaining; + if (captures_remaining > 0) { + int count = burst_length - captures_remaining; + --captures_remaining; - process_image_for_capture(image, count); + process_image_for_capture(image, count); - if (captures_remaining == 0) { - assert(thumb); - process_capture_burst(thumb); - } else { - assert(!thumb); - } - } else { - assert(!thumb); - } + if (captures_remaining == 0) { + assert(thumb); + process_capture_burst(thumb); + } else { + assert(!thumb); + } + } else { + assert(!thumb); + } - mp_zbar_image_unref(zbar_image); + mp_zbar_image_unref(zbar_image); - ++frames_processed; - if (captures_remaining == 0) { - is_capturing = false; - } + ++frames_processed; + if (captures_remaining == 0) { + is_capturing = false; + } #ifdef PROFILE_PROCESS - clock_t t3 = clock(); - printf("process_image %fms, step 1:%fms, step 2:%fms\n", - (float)(t3 - t1) / CLOCKS_PER_SEC * 1000, - (float)(t2 - t1) / CLOCKS_PER_SEC * 1000, - (float)(t3 - t2) / CLOCKS_PER_SEC * 1000); + clock_t t3 = clock(); + printf("process_image %fms, step 1:%fms, step 2:%fms\n", + (float)(t3 - t1) / CLOCKS_PER_SEC * 1000, + (float)(t2 - t1) / CLOCKS_PER_SEC * 1000, + (float)(t3 - t2) / CLOCKS_PER_SEC * 1000); #endif } void mp_process_pipeline_process_image(MPBuffer buffer) { - // If we haven't processed the previous frame yet, drop this one - if (frames_received != frames_processed && !is_capturing) { - mp_io_pipeline_release_buffer(buffer.index); - return; - } + // If we haven't processed the previous frame yet, drop this one + if (frames_received != frames_processed && !is_capturing) { + mp_io_pipeline_release_buffer(buffer.index); + return; + } - ++frames_received; + ++frames_received; - mp_pipeline_invoke(pipeline, (MPPipelineCallback)process_image, &buffer, - sizeof(MPBuffer)); + mp_pipeline_invoke(pipeline, + (MPPipelineCallback)process_image, + &buffer, + sizeof(MPBuffer)); } static void capture() { - char template[] = "/tmp/megapixels.XXXXXX"; - char *tempdir; - tempdir = mkdtemp(template); + char template[] = "/tmp/megapixels.XXXXXX"; + char *tempdir; + tempdir = mkdtemp(template); - if (tempdir == NULL) { - g_printerr("Could not make capture directory %s\n", template); - exit(EXIT_FAILURE); - } + if (tempdir == NULL) { + g_printerr("Could not make capture directory %s\n", template); + exit(EXIT_FAILURE); + } - strcpy(burst_dir, tempdir); + strcpy(burst_dir, tempdir); - captures_remaining = burst_length; + captures_remaining = burst_length; } void mp_process_pipeline_capture() { - is_capturing = true; + is_capturing = true; - mp_pipeline_invoke(pipeline, capture, NULL, 0); + mp_pipeline_invoke(pipeline, capture, NULL, 0); } static void on_output_changed() { - output_buffer_width = mode.width / 2; - output_buffer_height = mode.height / 2; + output_buffer_width = mode.width / 2; + output_buffer_height = mode.height / 2; - if (camera->rotate != 0 || camera->rotate != 180) { - int tmp = output_buffer_width; - output_buffer_width = output_buffer_height; - output_buffer_height = tmp; - } + if (camera->rotate != 0 || camera->rotate != 180) { + int tmp = output_buffer_width; + output_buffer_width = output_buffer_height; + output_buffer_height = tmp; + } - for (size_t i = 0; i < NUM_BUFFERS; ++i) { - 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); - } + for (size_t i = 0; i < NUM_BUFFERS; ++i) { + 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); + } - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); - gles2_debayer_configure( - gles2_debayer, output_buffer_width, output_buffer_height, mode.width, - mode.height, camera->rotate, camera->mirrored, - camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, - camera->blacklevel); + gles2_debayer_configure( + gles2_debayer, + output_buffer_width, + output_buffer_height, + mode.width, + mode.height, + camera->rotate, + camera->mirrored, + camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, + camera->blacklevel); } static int mod(int a, int b) { - int r = a % b; - return r < 0 ? r + b : r; + int r = a % b; + return r < 0 ? r + b : r; } static void update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state) { - const bool output_changed = - !mp_camera_mode_is_equivalent(&mode, &state->mode) || - preview_width != state->preview_width || - preview_height != state->preview_height || - device_rotation != state->device_rotation; + const bool output_changed = + !mp_camera_mode_is_equivalent(&mode, &state->mode) || + preview_width != state->preview_width || + preview_height != state->preview_height || + device_rotation != state->device_rotation; - camera = state->camera; - mode = state->mode; + camera = state->camera; + mode = state->mode; - preview_width = state->preview_width; - preview_height = state->preview_height; + preview_width = state->preview_width; + preview_height = state->preview_height; - device_rotation = state->device_rotation; + device_rotation = state->device_rotation; - burst_length = state->burst_length; - save_dng = state->save_dng; + burst_length = state->burst_length; + save_dng = state->save_dng; - // gain_is_manual = state->gain_is_manual; - gain = state->gain; - gain_max = state->gain_max; + // gain_is_manual = state->gain_is_manual; + gain = state->gain; + gain_max = state->gain_max; - exposure_is_manual = state->exposure_is_manual; - exposure = state->exposure; + exposure_is_manual = state->exposure_is_manual; + exposure = state->exposure; - if (output_changed) { - camera_rotation = mod(camera->rotate - device_rotation, 360); + if (output_changed) { + camera_rotation = mod(camera->rotate - device_rotation, 360); - on_output_changed(); - } + on_output_changed(); + } - struct mp_main_state main_state = { - .camera = camera, - .mode = mode, - .image_width = output_buffer_width, - .image_height = output_buffer_height, - .gain_is_manual = state->gain_is_manual, - .gain = gain, - .gain_max = gain_max, - .exposure_is_manual = exposure_is_manual, - .exposure = exposure, - .has_auto_focus_continuous = state->has_auto_focus_continuous, - .has_auto_focus_start = state->has_auto_focus_start, - }; - mp_main_update_state(&main_state); + struct mp_main_state main_state = { + .camera = camera, + .mode = mode, + .image_width = output_buffer_width, + .image_height = output_buffer_height, + .gain_is_manual = state->gain_is_manual, + .gain = gain, + .gain_max = gain_max, + .exposure_is_manual = exposure_is_manual, + .exposure = exposure, + .has_auto_focus_continuous = state->has_auto_focus_continuous, + .has_auto_focus_start = state->has_auto_focus_start, + }; + mp_main_update_state(&main_state); } void mp_process_pipeline_update_state(const struct mp_process_pipeline_state *new_state) { - mp_pipeline_invoke(pipeline, (MPPipelineCallback)update_state, new_state, - sizeof(struct mp_process_pipeline_state)); + mp_pipeline_invoke(pipeline, + (MPPipelineCallback)update_state, + new_state, + sizeof(struct mp_process_pipeline_state)); } // GTK4 seems to require this diff --git a/src/process_pipeline.h b/src/process_pipeline.h index 6902409..55caad5 100644 --- a/src/process_pipeline.h +++ b/src/process_pipeline.h @@ -5,27 +5,27 @@ typedef struct _GdkSurface GdkSurface; struct mp_process_pipeline_state { - const struct mp_camera_config *camera; - MPCameraMode mode; + const struct mp_camera_config *camera; + MPCameraMode mode; - int burst_length; + int burst_length; - int preview_width; - int preview_height; + int preview_width; + int preview_height; - int device_rotation; + int device_rotation; - bool gain_is_manual; - int gain; - int gain_max; + bool gain_is_manual; + int gain; + int gain_max; - bool exposure_is_manual; - int exposure; + bool exposure_is_manual; + int exposure; - bool has_auto_focus_continuous; - bool has_auto_focus_start; + bool has_auto_focus_continuous; + bool has_auto_focus_start; - bool save_dng; + bool save_dng; }; void mp_process_pipeline_start(); diff --git a/src/zbar_pipeline.c b/src/zbar_pipeline.c index 566170c..25d6a44 100644 --- a/src/zbar_pipeline.c +++ b/src/zbar_pipeline.c @@ -1,20 +1,20 @@ #include "zbar_pipeline.h" -#include "pipeline.h" -#include "main.h" #include "io_pipeline.h" -#include +#include "main.h" +#include "pipeline.h" #include +#include struct _MPZBarImage { - uint8_t *data; - MPPixelFormat pixel_format; - int width; - int height; - int rotation; - bool mirrored; + uint8_t *data; + MPPixelFormat pixel_format; + int width; + int height; + int rotation; + bool mirrored; - _Atomic int ref_count; + _Atomic int ref_count; }; static MPPipeline *pipeline; @@ -27,237 +27,251 @@ static zbar_image_scanner_t *scanner; static void setup(MPPipeline *pipeline, const void *data) { - scanner = zbar_image_scanner_create(); - zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1); + scanner = zbar_image_scanner_create(); + zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1); } void mp_zbar_pipeline_start() { - pipeline = mp_pipeline_new(); + pipeline = mp_pipeline_new(); - mp_pipeline_invoke(pipeline, setup, NULL, 0); + mp_pipeline_invoke(pipeline, setup, NULL, 0); } void mp_zbar_pipeline_stop() { - mp_pipeline_free(pipeline); + mp_pipeline_free(pipeline); } static bool is_3d_code(zbar_symbol_type_t type) { - switch (type) { - case ZBAR_EAN2: - case ZBAR_EAN5: - case ZBAR_EAN8: - case ZBAR_UPCE: - case ZBAR_ISBN10: - case ZBAR_UPCA: - case ZBAR_EAN13: - case ZBAR_ISBN13: - case ZBAR_I25: - case ZBAR_DATABAR: - case ZBAR_DATABAR_EXP: - case ZBAR_CODABAR: - case ZBAR_CODE39: - case ZBAR_CODE93: - case ZBAR_CODE128: - return false; - case ZBAR_COMPOSITE: - case ZBAR_PDF417: - case ZBAR_QRCODE: - case ZBAR_SQCODE: - return true; - default: - return false; - } + switch (type) { + case ZBAR_EAN2: + case ZBAR_EAN5: + case ZBAR_EAN8: + case ZBAR_UPCE: + case ZBAR_ISBN10: + case ZBAR_UPCA: + case ZBAR_EAN13: + case ZBAR_ISBN13: + case ZBAR_I25: + case ZBAR_DATABAR: + case ZBAR_DATABAR_EXP: + case ZBAR_CODABAR: + case ZBAR_CODE39: + case ZBAR_CODE93: + case ZBAR_CODE128: + return false; + case ZBAR_COMPOSITE: + case ZBAR_PDF417: + case ZBAR_QRCODE: + case ZBAR_SQCODE: + return true; + default: + return false; + } } static inline void map_coords(int *x, int *y, int width, int height, int rotation, bool mirrored) { - int x_r, y_r; - if (rotation == 0) { - x_r = *x; - y_r = *y; - } else if (rotation == 90) { - x_r = *y; - y_r = height - *x - 1; - } else if (rotation == 270) { - x_r = width - *y - 1; - y_r = *x; - } else { - x_r = width - *x - 1; - y_r = height - *y - 1; - } + int x_r, y_r; + if (rotation == 0) { + x_r = *x; + y_r = *y; + } else if (rotation == 90) { + x_r = *y; + y_r = height - *x - 1; + } else if (rotation == 270) { + x_r = width - *y - 1; + y_r = *x; + } else { + x_r = width - *x - 1; + y_r = height - *y - 1; + } - if (mirrored) { - x_r = width - x_r - 1; - } + if (mirrored) { + x_r = width - x_r - 1; + } - *x = x_r; - *y = y_r; + *x = x_r; + *y = y_r; } 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) { - int tmp = width; - width = height; - height = tmp; - } + if (image->rotation == 90 || image->rotation == 270) { + int tmp = width; + width = height; + height = tmp; + } - MPZBarCode code; + MPZBarCode code; - unsigned loc_size = zbar_symbol_get_loc_size(symbol); - assert(loc_size > 0); + unsigned loc_size = zbar_symbol_get_loc_size(symbol); + assert(loc_size > 0); - zbar_symbol_type_t type = zbar_symbol_get_type(symbol); + zbar_symbol_type_t type = zbar_symbol_get_type(symbol); - if (is_3d_code(type) && loc_size == 4) { - for (unsigned i = 0; i < loc_size; ++i) { - code.bounds_x[i] = zbar_symbol_get_loc_x(symbol, i); - code.bounds_y[i] = zbar_symbol_get_loc_y(symbol, i); - } - } else { - int min_x = zbar_symbol_get_loc_x(symbol, 0); - int min_y = zbar_symbol_get_loc_y(symbol, 0); - int max_x = min_x, max_y = min_y; - for (unsigned i = 1; i < loc_size; ++i) { - int x = zbar_symbol_get_loc_x(symbol, i); - int y = zbar_symbol_get_loc_y(symbol, i); - min_x = MIN(min_x, x); - min_y = MIN(min_y, y); - max_x = MAX(max_x, x); - max_y = MAX(max_y, y); - } + if (is_3d_code(type) && loc_size == 4) { + for (unsigned i = 0; i < loc_size; ++i) { + code.bounds_x[i] = zbar_symbol_get_loc_x(symbol, i); + code.bounds_y[i] = zbar_symbol_get_loc_y(symbol, i); + } + } else { + int min_x = zbar_symbol_get_loc_x(symbol, 0); + int min_y = zbar_symbol_get_loc_y(symbol, 0); + int max_x = min_x, max_y = min_y; + for (unsigned i = 1; i < loc_size; ++i) { + int x = zbar_symbol_get_loc_x(symbol, i); + int y = zbar_symbol_get_loc_y(symbol, i); + min_x = MIN(min_x, x); + min_y = MIN(min_y, y); + max_x = MAX(max_x, x); + max_y = MAX(max_y, y); + } - code.bounds_x[0] = min_x; - code.bounds_y[0] = min_y; - code.bounds_x[1] = max_x; - code.bounds_y[1] = min_y; - code.bounds_x[2] = max_x; - code.bounds_y[2] = max_y; - code.bounds_x[3] = min_x; - code.bounds_y[3] = max_y; - } + code.bounds_x[0] = min_x; + code.bounds_y[0] = min_y; + code.bounds_x[1] = max_x; + code.bounds_y[1] = min_y; + code.bounds_x[2] = max_x; + code.bounds_y[2] = max_y; + code.bounds_x[3] = min_x; + code.bounds_y[3] = max_y; + } - for (uint8_t i = 0; i < 4; ++i) { - map_coords(&code.bounds_x[i], &code.bounds_y[i], width, height, - image->rotation, image->mirrored); - } + for (uint8_t i = 0; i < 4; ++i) { + map_coords(&code.bounds_x[i], + &code.bounds_y[i], + width, + height, + image->rotation, + image->mirrored); + } - const char *data = zbar_symbol_get_data(symbol); - unsigned int data_size = zbar_symbol_get_data_length(symbol); - code.type = zbar_get_symbol_name(type); - code.data = strndup(data, data_size + 1); - code.data[data_size] = 0; + const char *data = zbar_symbol_get_data(symbol); + unsigned int data_size = zbar_symbol_get_data_length(symbol); + code.type = zbar_get_symbol_name(type); + code.data = strndup(data, data_size + 1); + code.data[data_size] = 0; - return code; + return code; } static void process_image(MPPipeline *pipeline, MPZBarImage **_image) { - MPZBarImage *image = *_image; + MPZBarImage *image = *_image; - assert(image->pixel_format == MP_PIXEL_FMT_BGGR8 || - image->pixel_format == MP_PIXEL_FMT_GBRG8 || - image->pixel_format == MP_PIXEL_FMT_GRBG8 || - image->pixel_format == MP_PIXEL_FMT_RGGB8); + assert(image->pixel_format == MP_PIXEL_FMT_BGGR8 || + image->pixel_format == MP_PIXEL_FMT_GBRG8 || + image->pixel_format == MP_PIXEL_FMT_GRBG8 || + image->pixel_format == MP_PIXEL_FMT_RGGB8); - // Create a grayscale image for scanning from the current preview. - // Rotate/mirror correctly. - int width = image->width / 2; - int height = image->height / 2; + // Create a grayscale image for scanning from the current preview. + // Rotate/mirror correctly. + int width = image->width / 2; + int height = image->height / 2; - uint8_t *data = malloc(width * height * sizeof(uint8_t)); - size_t i = 0; - for (int y = 0; y < image->height; y += 2) { - for (int x = 0; x < image->width; x += 2) { - data[i++] = image->data[x + image->width * y]; - } - } + uint8_t *data = malloc(width * height * sizeof(uint8_t)); + size_t i = 0; + for (int y = 0; y < image->height; y += 2) { + for (int x = 0; x < image->width; x += 2) { + data[i++] = image->data[x + image->width * y]; + } + } - // Create image for zbar - zbar_image_t *zbar_image = zbar_image_create(); - zbar_image_set_format(zbar_image, zbar_fourcc('Y', '8', '0', '0')); - zbar_image_set_size(zbar_image, width, height); - zbar_image_set_data(zbar_image, data, width * height * sizeof(uint8_t), - zbar_image_free_data); + // Create image for zbar + zbar_image_t *zbar_image = zbar_image_create(); + zbar_image_set_format(zbar_image, zbar_fourcc('Y', '8', '0', '0')); + zbar_image_set_size(zbar_image, width, height); + zbar_image_set_data(zbar_image, + data, + width * height * sizeof(uint8_t), + zbar_image_free_data); - int res = zbar_scan_image(scanner, zbar_image); - assert(res >= 0); + int res = zbar_scan_image(scanner, zbar_image); + assert(res >= 0); - if (res > 0) { - MPZBarScanResult *result = malloc(sizeof(MPZBarScanResult)); - result->size = res; + if (res > 0) { + MPZBarScanResult *result = malloc(sizeof(MPZBarScanResult)); + result->size = res; - const zbar_symbol_t *symbol = zbar_image_first_symbol(zbar_image); - for (int i = 0; i < MIN(res, 8); ++i) { - assert(symbol != NULL); - result->codes[i] = - process_symbol(image, width, height, symbol); - symbol = zbar_symbol_next(symbol); - } + const zbar_symbol_t *symbol = zbar_image_first_symbol(zbar_image); + for (int i = 0; i < MIN(res, 8); ++i) { + assert(symbol != NULL); + result->codes[i] = + process_symbol(image, width, height, symbol); + symbol = zbar_symbol_next(symbol); + } - mp_main_set_zbar_result(result); - } else { - mp_main_set_zbar_result(NULL); - } + mp_main_set_zbar_result(result); + } else { + mp_main_set_zbar_result(NULL); + } - zbar_image_destroy(zbar_image); - mp_zbar_image_unref(image); + zbar_image_destroy(zbar_image); + mp_zbar_image_unref(image); - ++frames_processed; + ++frames_processed; } void mp_zbar_pipeline_process_image(MPZBarImage *image) { - // If we haven't processed the previous frame yet, drop this one - if (frames_received != frames_processed) { - mp_zbar_image_unref(image); - return; - } + // If we haven't processed the previous frame yet, drop this one + if (frames_received != frames_processed) { + mp_zbar_image_unref(image); + return; + } - ++frames_received; + ++frames_received; - mp_pipeline_invoke(pipeline, (MPPipelineCallback)process_image, &image, - sizeof(MPZBarImage *)); + mp_pipeline_invoke(pipeline, + (MPPipelineCallback)process_image, + &image, + sizeof(MPZBarImage *)); } MPZBarImage * -mp_zbar_image_new(uint8_t *data, MPPixelFormat pixel_format, int width, int height, - int rotation, bool mirrored) +mp_zbar_image_new(uint8_t *data, + MPPixelFormat pixel_format, + int width, + int height, + int rotation, + bool mirrored) { - MPZBarImage *image = malloc(sizeof(MPZBarImage)); - image->data = data; - image->pixel_format = pixel_format; - image->width = width; - image->height = height; - image->rotation = rotation; - image->mirrored = mirrored; - image->ref_count = 1; - return image; + MPZBarImage *image = malloc(sizeof(MPZBarImage)); + image->data = data; + image->pixel_format = pixel_format; + image->width = width; + image->height = height; + image->rotation = rotation; + image->mirrored = mirrored; + image->ref_count = 1; + return image; } MPZBarImage * mp_zbar_image_ref(MPZBarImage *image) { - ++image->ref_count; - return image; + ++image->ref_count; + return image; } void mp_zbar_image_unref(MPZBarImage *image) { - if (--image->ref_count == 0) { - free(image->data); - free(image); - } + if (--image->ref_count == 0) { + free(image->data); + free(image); + } } diff --git a/src/zbar_pipeline.h b/src/zbar_pipeline.h index a54be6a..cab39a0 100644 --- a/src/zbar_pipeline.h +++ b/src/zbar_pipeline.h @@ -5,15 +5,15 @@ typedef struct _MPZBarImage MPZBarImage; typedef struct { - int bounds_x[4]; - int bounds_y[4]; - char *data; - const char *type; + int bounds_x[4]; + int bounds_y[4]; + char *data; + const char *type; } MPZBarCode; typedef struct { - MPZBarCode codes[8]; - uint8_t size; + MPZBarCode codes[8]; + uint8_t size; } MPZBarScanResult; void mp_zbar_pipeline_start(); @@ -21,7 +21,11 @@ void mp_zbar_pipeline_stop(); void mp_zbar_pipeline_process_image(MPZBarImage *image); -MPZBarImage *mp_zbar_image_new(uint8_t *data, MPPixelFormat pixel_format, int width, - int height, int rotation, bool mirrored); +MPZBarImage *mp_zbar_image_new(uint8_t *data, + MPPixelFormat pixel_format, + int width, + int height, + int rotation, + bool mirrored); MPZBarImage *mp_zbar_image_ref(MPZBarImage *image); void mp_zbar_image_unref(MPZBarImage *image); diff --git a/tools/camera_test.c b/tools/camera_test.c index fbaf52a..cf07791 100644 --- a/tools/camera_test.c +++ b/tools/camera_test.c @@ -9,203 +9,208 @@ double get_time() { - struct timeval t; - struct timezone tzp; - gettimeofday(&t, &tzp); - return t.tv_sec + t.tv_usec * 1e-6; + struct timeval t; + struct timezone tzp; + gettimeofday(&t, &tzp); + return t.tv_sec + t.tv_usec * 1e-6; } int main(int argc, char *argv[]) { - if (argc != 2 && argc != 3) { - printf("Usage: %s []\n", - argv[0]); - return 1; - } + if (argc != 2 && argc != 3) { + printf("Usage: %s []\n", + argv[0]); + return 1; + } - char *video_name = argv[1]; - char *subdev_name = NULL; - if (argc == 3) { - subdev_name = argv[2]; - } + char *video_name = argv[1]; + char *subdev_name = NULL; + if (argc == 3) { + subdev_name = argv[2]; + } - double find_start = get_time(); + double find_start = get_time(); - // First find the device - MPDevice *device = mp_device_find(video_name); - if (!device) { - printf("Device not found\n"); - return 1; - } + // First find the device + MPDevice *device = mp_device_find(video_name); + if (!device) { + printf("Device not found\n"); + return 1; + } - double find_end = get_time(); + double find_end = get_time(); - printf("Finding the device took %fms\n", (find_end - find_start) * 1000); + printf("Finding the device took %fms\n", (find_end - find_start) * 1000); - int video_fd; - uint32_t video_entity_id; - { - const struct media_v2_entity *entity = - mp_device_find_entity(device, video_name); - if (!entity) { - printf("Unable to find video device interface\n"); - return 1; - } + int video_fd; + uint32_t video_entity_id; + { + const struct media_v2_entity *entity = + mp_device_find_entity(device, video_name); + if (!entity) { + printf("Unable to find video device interface\n"); + return 1; + } - video_entity_id = entity->id; + video_entity_id = entity->id; - const struct media_v2_interface *iface = - mp_device_find_entity_interface(device, video_entity_id); + const struct media_v2_interface *iface = + mp_device_find_entity_interface(device, video_entity_id); - char buf[256]; - if (!mp_find_device_path(iface->devnode, buf, 256)) { - printf("Unable to find video device path\n"); - return 1; - } + char buf[256]; + if (!mp_find_device_path(iface->devnode, buf, 256)) { + printf("Unable to find video device path\n"); + return 1; + } - video_fd = open(buf, O_RDWR); - if (video_fd == -1) { - printf("Unable to open video device\n"); - return 1; - } - } + video_fd = open(buf, O_RDWR); + if (video_fd == -1) { + printf("Unable to open video device\n"); + return 1; + } + } - int subdev_fd = -1; - if (subdev_name) { - const struct media_v2_entity *entity = - mp_device_find_entity(device, subdev_name); - if (!entity) { - printf("Unable to find sub-device\n"); - return 1; - } + int subdev_fd = -1; + if (subdev_name) { + const struct media_v2_entity *entity = + mp_device_find_entity(device, subdev_name); + if (!entity) { + printf("Unable to find sub-device\n"); + return 1; + } - const struct media_v2_pad *source_pad = - mp_device_get_pad_from_entity(device, entity->id); - const struct media_v2_pad *sink_pad = - mp_device_get_pad_from_entity(device, video_entity_id); + const struct media_v2_pad *source_pad = + mp_device_get_pad_from_entity(device, entity->id); + const struct media_v2_pad *sink_pad = + mp_device_get_pad_from_entity(device, video_entity_id); - // Disable other links - const struct media_v2_entity *entities = - mp_device_get_entities(device); - for (int i = 0; i < mp_device_get_num_entities(device); ++i) { - if (entities[i].id != video_entity_id && - entities[i].id != entity->id) { - const struct media_v2_pad *pad = - mp_device_get_pad_from_entity( - device, entities[i].id); - mp_device_setup_link(device, pad->id, sink_pad->id, - false); - } - } + // Disable other links + const struct media_v2_entity *entities = + mp_device_get_entities(device); + for (int i = 0; i < mp_device_get_num_entities(device); ++i) { + if (entities[i].id != video_entity_id && + entities[i].id != entity->id) { + const struct media_v2_pad *pad = + mp_device_get_pad_from_entity( + device, entities[i].id); + mp_device_setup_link( + device, pad->id, sink_pad->id, false); + } + } - // Then enable ours - mp_device_setup_link(device, source_pad->id, sink_pad->id, true); + // Then enable ours + mp_device_setup_link(device, source_pad->id, sink_pad->id, true); - const struct media_v2_interface *iface = - mp_device_find_entity_interface(device, entity->id); + const struct media_v2_interface *iface = + mp_device_find_entity_interface(device, entity->id); - char buf[256]; - if (!mp_find_device_path(iface->devnode, buf, 256)) { - printf("Unable to find sub-device path\n"); - return 1; - } + char buf[256]; + if (!mp_find_device_path(iface->devnode, buf, 256)) { + printf("Unable to find sub-device path\n"); + return 1; + } - subdev_fd = open(buf, O_RDWR); - if (subdev_fd == -1) { - printf("Unable to open sub-device\n"); - return 1; - } - } + subdev_fd = open(buf, O_RDWR); + if (subdev_fd == -1) { + printf("Unable to open sub-device\n"); + return 1; + } + } - double open_end = get_time(); + double open_end = get_time(); - printf("Opening the device took %fms\n", (open_end - find_end) * 1000); + printf("Opening the device took %fms\n", (open_end - find_end) * 1000); - MPCamera *camera = mp_camera_new(video_fd, subdev_fd); + MPCamera *camera = mp_camera_new(video_fd, subdev_fd); - MPControlList *controls = mp_camera_list_controls(camera); + MPControlList *controls = mp_camera_list_controls(camera); - double control_list_end = get_time(); + double control_list_end = get_time(); - printf("Available controls: (took %fms)\n", - (control_list_end - open_end) * 1000); - for (MPControlList *list = controls; list; - list = mp_control_list_next(list)) { - MPControl *c = mp_control_list_get(list); + printf("Available controls: (took %fms)\n", + (control_list_end - open_end) * 1000); + for (MPControlList *list = controls; list; + list = mp_control_list_next(list)) { + MPControl *c = mp_control_list_get(list); - printf(" %32s id:%s type:%s default:%d\n", c->name, - mp_control_id_to_str(c->id), mp_control_type_to_str(c->type), - c->default_value); - } + printf(" %32s id:%s type:%s default:%d\n", + c->name, + mp_control_id_to_str(c->id), + mp_control_type_to_str(c->type), + c->default_value); + } - double mode_list_begin = get_time(); + double mode_list_begin = get_time(); - MPCameraModeList *modes = mp_camera_list_available_modes(camera); + MPCameraModeList *modes = mp_camera_list_available_modes(camera); - double mode_list_end = get_time(); + double mode_list_end = get_time(); - printf("Available modes: (took %fms)\n", - (mode_list_end - mode_list_begin) * 1000); - for (MPCameraModeList *list = modes; list; - list = mp_camera_mode_list_next(list)) { - MPCameraMode *m = mp_camera_mode_list_get(list); - printf(" %dx%d interval:%d/%d fmt:%s\n", m->width, m->height, - m->frame_interval.numerator, m->frame_interval.denominator, - mp_pixel_format_to_str(m->pixel_format)); + printf("Available modes: (took %fms)\n", + (mode_list_end - mode_list_begin) * 1000); + for (MPCameraModeList *list = modes; list; + list = mp_camera_mode_list_next(list)) { + MPCameraMode *m = mp_camera_mode_list_get(list); + printf(" %dx%d interval:%d/%d fmt:%s\n", + m->width, + m->height, + m->frame_interval.numerator, + m->frame_interval.denominator, + mp_pixel_format_to_str(m->pixel_format)); - // Skip really slow framerates - if (m->frame_interval.denominator < 15) { - printf(" Skipping…\n"); - continue; - } + // Skip really slow framerates + if (m->frame_interval.denominator < 15) { + printf(" Skipping…\n"); + continue; + } - double start_capture = get_time(); + double start_capture = get_time(); - mp_camera_set_mode(camera, m); - mp_camera_start_capture(camera); + mp_camera_set_mode(camera, m); + mp_camera_start_capture(camera); - double last = get_time(); - printf(" Testing 10 captures, starting took %fms\n", - (last - start_capture) * 1000); + double last = get_time(); + printf(" Testing 10 captures, starting took %fms\n", + (last - start_capture) * 1000); - for (int i = 0; i < 10; ++i) { - MPBuffer buffer; - if (!mp_camera_capture_buffer(camera, &buffer)) { - printf(" Failed to capture buffer\n"); - } + for (int i = 0; i < 10; ++i) { + MPBuffer buffer; + if (!mp_camera_capture_buffer(camera, &buffer)) { + printf(" Failed to capture buffer\n"); + } - size_t num_bytes = mp_pixel_format_width_to_bytes( - m->pixel_format, m->width) * - m->height; - uint8_t *data = malloc(num_bytes); - memcpy(data, buffer.data, num_bytes); + size_t num_bytes = mp_pixel_format_width_to_bytes( + m->pixel_format, m->width) * + m->height; + uint8_t *data = malloc(num_bytes); + memcpy(data, buffer.data, num_bytes); - printf(" first byte: %d.", data[0]); + printf(" first byte: %d.", data[0]); - free(data); + free(data); - mp_camera_release_buffer(camera, buffer.index); + mp_camera_release_buffer(camera, buffer.index); - double now = get_time(); - printf(" capture took %fms\n", (now - last) * 1000); - last = now; - } + double now = get_time(); + printf(" capture took %fms\n", (now - last) * 1000); + last = now; + } - mp_camera_stop_capture(camera); - } + mp_camera_stop_capture(camera); + } - double cleanup_start = get_time(); + double cleanup_start = get_time(); - mp_camera_free(camera); + mp_camera_free(camera); - close(video_fd); - if (subdev_fd != -1) - close(subdev_fd); + close(video_fd); + if (subdev_fd != -1) + close(subdev_fd); - mp_device_close(device); + mp_device_close(device); - double cleanup_end = get_time(); + double cleanup_end = get_time(); - printf("Cleanup took %fms\n", (cleanup_end - cleanup_start) * 1000); + printf("Cleanup took %fms\n", (cleanup_end - cleanup_start) * 1000); } diff --git a/tools/list_devices.c b/tools/list_devices.c index 291f982..e748a00 100644 --- a/tools/list_devices.c +++ b/tools/list_devices.c @@ -5,56 +5,65 @@ int main(int argc, char *argv[]) { - MPDeviceList *list = mp_device_list_new(); + MPDeviceList *list = mp_device_list_new(); - while (list) { - MPDevice *device = mp_device_list_get(list); + while (list) { + MPDevice *device = mp_device_list_get(list); - const struct media_device_info *info = mp_device_get_info(device); - printf("%s (%s) %s\n", info->model, info->driver, info->serial); - printf(" Bus Info: %s\n", info->bus_info); - printf(" Media Version: %d\n", info->media_version); - printf(" HW Revision: %d\n", info->hw_revision); - printf(" Driver Version: %d\n", info->driver_version); + const struct media_device_info *info = mp_device_get_info(device); + printf("%s (%s) %s\n", info->model, info->driver, info->serial); + printf(" Bus Info: %s\n", info->bus_info); + printf(" Media Version: %d\n", info->media_version); + printf(" HW Revision: %d\n", info->hw_revision); + printf(" Driver Version: %d\n", info->driver_version); - const struct media_v2_entity *entities = - mp_device_get_entities(device); - size_t num = mp_device_get_num_entities(device); - printf(" Entities (%ld):\n", num); - for (int i = 0; i < num; ++i) { - printf(" %d %s (%d)\n", entities[i].id, entities[i].name, - entities[i].function); - } + const struct media_v2_entity *entities = + mp_device_get_entities(device); + size_t num = mp_device_get_num_entities(device); + printf(" Entities (%ld):\n", num); + for (int i = 0; i < num; ++i) { + printf(" %d %s (%d)\n", + entities[i].id, + entities[i].name, + entities[i].function); + } - const struct media_v2_interface *interfaces = - mp_device_get_interfaces(device); - num = mp_device_get_num_interfaces(device); - printf(" Interfaces (%ld):\n", num); - for (int i = 0; i < num; ++i) { - printf(" %d (%d - %d) devnode %d:%d\n", interfaces[i].id, - interfaces[i].intf_type, interfaces[i].flags, - interfaces[i].devnode.major, - interfaces[i].devnode.minor); - } + const struct media_v2_interface *interfaces = + mp_device_get_interfaces(device); + num = mp_device_get_num_interfaces(device); + printf(" Interfaces (%ld):\n", num); + for (int i = 0; i < num; ++i) { + printf(" %d (%d - %d) devnode %d:%d\n", + interfaces[i].id, + interfaces[i].intf_type, + interfaces[i].flags, + interfaces[i].devnode.major, + interfaces[i].devnode.minor); + } - const struct media_v2_pad *pads = mp_device_get_pads(device); - num = mp_device_get_num_pads(device); - printf(" Pads (%ld):\n", num); - for (int i = 0; i < num; ++i) { - printf(" %d for device:%d (%d)\n", pads[i].id, - pads[i].entity_id, pads[i].flags); - } + const struct media_v2_pad *pads = mp_device_get_pads(device); + num = mp_device_get_num_pads(device); + printf(" Pads (%ld):\n", num); + for (int i = 0; i < num; ++i) { + printf(" %d for device:%d (%d)\n", + pads[i].id, + pads[i].entity_id, + pads[i].flags); + } - const struct media_v2_link *links = mp_device_get_links(device); - num = mp_device_get_num_links(device); - printf(" Links (%ld):\n", num); - for (int i = 0; i < num; ++i) { - printf(" %d from:%d to:%d (%d)\n", links[i].id, - links[i].source_id, links[i].sink_id, links[i].flags); - } + const struct media_v2_link *links = mp_device_get_links(device); + num = mp_device_get_num_links(device); + printf(" Links (%ld):\n", num); + for (int i = 0; i < num; ++i) { + printf(" %d from:%d to:%d (%d)\n", + links[i].id, + links[i].source_id, + links[i].sink_id, + links[i].flags); + } - list = mp_device_list_next(list); - } + list = mp_device_list_next(list); + } - mp_device_list_free(list); + mp_device_list_free(list); }