From 72105c949177ea143621e483c43011184938dd93 Mon Sep 17 00:00:00 2001 From: Martijn Braam Date: Sun, 6 Dec 2020 15:44:31 +0100 Subject: [PATCH] Code style --- .clang-format | 548 ++++++++++++++ camera.c | 1782 +++++++++++++++++++++++--------------------- camera.h | 70 +- camera_config.c | 432 +++++------ camera_config.h | 50 +- device.c | 586 ++++++++------- device.h | 39 +- ini.c | 221 +++--- ini.h | 14 +- io_pipeline.c | 665 +++++++++-------- io_pipeline.h | 16 +- main.c | 224 +++--- main.h | 21 +- matrix.c | 13 +- pipeline.c | 134 ++-- pipeline.h | 7 +- process_pipeline.c | 558 +++++++------- process_pipeline.h | 24 +- quickpreview.c | 288 +++---- quickpreview.h | 33 +- 20 files changed, 3200 insertions(+), 2525 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ccb07fa --- /dev/null +++ b/.clang-format @@ -0,0 +1,548 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 4. +# +# For more information, see: +# +# Documentation/process/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +#AlignEscapedNewlines: Left # Unknown to clang-format-4.0 +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: All +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + #AfterExternBlock: false # Unknown to clang-format-5.0 + 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 +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0 +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0 +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 85 +CommentPragmas: '^ IWYU pragma:' +#CompactNamespaces: false # Unknown to clang-format-4.0 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +#FixNamespaceComments: false # Unknown to clang-format-4.0 + +# Taken from: +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \ +# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# | sort | uniq +ForEachMacros: + - 'apei_estatus_for_each_section' + - 'ata_for_each_dev' + - 'ata_for_each_link' + - '__ata_qc_for_each' + - 'ata_qc_for_each' + - 'ata_qc_for_each_raw' + - 'ata_qc_for_each_with_internal' + - 'ax25_for_each' + - 'ax25_uid_for_each' + - '__bio_for_each_bvec' + - 'bio_for_each_bvec' + - 'bio_for_each_bvec_all' + - 'bio_for_each_integrity_vec' + - '__bio_for_each_segment' + - 'bio_for_each_segment' + - 'bio_for_each_segment_all' + - 'bio_list_for_each' + - 'bip_for_each_vec' + - 'bitmap_for_each_clear_region' + - 'bitmap_for_each_set_region' + - 'blkg_for_each_descendant_post' + - 'blkg_for_each_descendant_pre' + - 'blk_queue_for_each_rl' + - 'bond_for_each_slave' + - 'bond_for_each_slave_rcu' + - 'bpf_for_each_spilled_reg' + - 'btree_for_each_safe128' + - 'btree_for_each_safe32' + - 'btree_for_each_safe64' + - 'btree_for_each_safel' + - 'card_for_each_dev' + - 'cgroup_taskset_for_each' + - 'cgroup_taskset_for_each_leader' + - 'cpufreq_for_each_entry' + - 'cpufreq_for_each_entry_idx' + - 'cpufreq_for_each_valid_entry' + - 'cpufreq_for_each_valid_entry_idx' + - 'css_for_each_child' + - 'css_for_each_descendant_post' + - 'css_for_each_descendant_pre' + - 'device_for_each_child_node' + - 'dma_fence_chain_for_each' + - 'do_for_each_ftrace_op' + - 'drm_atomic_crtc_for_each_plane' + - 'drm_atomic_crtc_state_for_each_plane' + - 'drm_atomic_crtc_state_for_each_plane_state' + - 'drm_atomic_for_each_plane_damage' + - 'drm_client_for_each_connector_iter' + - 'drm_client_for_each_modeset' + - 'drm_connector_for_each_possible_encoder' + - 'drm_for_each_bridge_in_chain' + - 'drm_for_each_connector_iter' + - 'drm_for_each_crtc' + - 'drm_for_each_encoder' + - 'drm_for_each_encoder_mask' + - 'drm_for_each_fb' + - 'drm_for_each_legacy_plane' + - 'drm_for_each_plane' + - 'drm_for_each_plane_mask' + - 'drm_for_each_privobj' + - 'drm_mm_for_each_hole' + - 'drm_mm_for_each_node' + - 'drm_mm_for_each_node_in_range' + - 'drm_mm_for_each_node_safe' + - 'flow_action_for_each' + - 'for_each_active_dev_scope' + - 'for_each_active_drhd_unit' + - 'for_each_active_iommu' + - 'for_each_aggr_pgid' + - 'for_each_available_child_of_node' + - 'for_each_bio' + - 'for_each_board_func_rsrc' + - 'for_each_bvec' + - 'for_each_card_auxs' + - 'for_each_card_auxs_safe' + - 'for_each_card_components' + - 'for_each_card_dapms' + - 'for_each_card_pre_auxs' + - 'for_each_card_prelinks' + - 'for_each_card_rtds' + - 'for_each_card_rtds_safe' + - 'for_each_card_widgets' + - 'for_each_card_widgets_safe' + - 'for_each_cgroup_storage_type' + - 'for_each_child_of_node' + - 'for_each_clear_bit' + - 'for_each_clear_bit_from' + - 'for_each_cmsghdr' + - 'for_each_compatible_node' + - 'for_each_component_dais' + - 'for_each_component_dais_safe' + - 'for_each_comp_order' + - 'for_each_console' + - 'for_each_cpu' + - 'for_each_cpu_and' + - 'for_each_cpu_not' + - 'for_each_cpu_wrap' + - 'for_each_dapm_widgets' + - 'for_each_dev_addr' + - 'for_each_dev_scope' + - 'for_each_displayid_db' + - 'for_each_dma_cap_mask' + - 'for_each_dpcm_be' + - 'for_each_dpcm_be_rollback' + - 'for_each_dpcm_be_safe' + - 'for_each_dpcm_fe' + - 'for_each_drhd_unit' + - 'for_each_dss_dev' + - 'for_each_efi_memory_desc' + - 'for_each_efi_memory_desc_in_map' + - 'for_each_element' + - 'for_each_element_extid' + - 'for_each_element_id' + - 'for_each_endpoint_of_node' + - 'for_each_evictable_lru' + - 'for_each_fib6_node_rt_rcu' + - 'for_each_fib6_walker_rt' + - 'for_each_free_mem_pfn_range_in_zone' + - 'for_each_free_mem_pfn_range_in_zone_from' + - 'for_each_free_mem_range' + - 'for_each_free_mem_range_reverse' + - 'for_each_func_rsrc' + - 'for_each_hstate' + - 'for_each_if' + - 'for_each_iommu' + - 'for_each_ip_tunnel_rcu' + - 'for_each_irq_nr' + - 'for_each_link_codecs' + - 'for_each_link_cpus' + - 'for_each_link_platforms' + - 'for_each_lru' + - 'for_each_matching_node' + - 'for_each_matching_node_and_match' + - 'for_each_member' + - 'for_each_mem_region' + - 'for_each_memblock_type' + - 'for_each_memcg_cache_index' + - 'for_each_mem_pfn_range' + - '__for_each_mem_range' + - 'for_each_mem_range' + - '__for_each_mem_range_rev' + - 'for_each_mem_range_rev' + - 'for_each_migratetype_order' + - 'for_each_msi_entry' + - 'for_each_msi_entry_safe' + - 'for_each_net' + - 'for_each_net_continue_reverse' + - 'for_each_netdev' + - 'for_each_netdev_continue' + - 'for_each_netdev_continue_rcu' + - 'for_each_netdev_continue_reverse' + - 'for_each_netdev_feature' + - 'for_each_netdev_in_bond_rcu' + - 'for_each_netdev_rcu' + - 'for_each_netdev_reverse' + - 'for_each_netdev_safe' + - 'for_each_net_rcu' + - 'for_each_new_connector_in_state' + - 'for_each_new_crtc_in_state' + - 'for_each_new_mst_mgr_in_state' + - 'for_each_new_plane_in_state' + - 'for_each_new_private_obj_in_state' + - 'for_each_node' + - 'for_each_node_by_name' + - 'for_each_node_by_type' + - 'for_each_node_mask' + - 'for_each_node_state' + - 'for_each_node_with_cpus' + - 'for_each_node_with_property' + - 'for_each_nonreserved_multicast_dest_pgid' + - 'for_each_of_allnodes' + - 'for_each_of_allnodes_from' + - 'for_each_of_cpu_node' + - 'for_each_of_pci_range' + - 'for_each_old_connector_in_state' + - 'for_each_old_crtc_in_state' + - 'for_each_old_mst_mgr_in_state' + - 'for_each_oldnew_connector_in_state' + - 'for_each_oldnew_crtc_in_state' + - 'for_each_oldnew_mst_mgr_in_state' + - 'for_each_oldnew_plane_in_state' + - 'for_each_oldnew_plane_in_state_reverse' + - 'for_each_oldnew_private_obj_in_state' + - 'for_each_old_plane_in_state' + - 'for_each_old_private_obj_in_state' + - 'for_each_online_cpu' + - 'for_each_online_node' + - 'for_each_online_pgdat' + - 'for_each_pci_bridge' + - 'for_each_pci_dev' + - 'for_each_pci_msi_entry' + - 'for_each_pcm_streams' + - 'for_each_physmem_range' + - 'for_each_populated_zone' + - 'for_each_possible_cpu' + - 'for_each_present_cpu' + - 'for_each_prime_number' + - 'for_each_prime_number_from' + - 'for_each_process' + - 'for_each_process_thread' + - 'for_each_property_of_node' + - 'for_each_registered_fb' + - 'for_each_requested_gpio' + - 'for_each_requested_gpio_in_range' + - 'for_each_reserved_mem_range' + - 'for_each_reserved_mem_region' + - 'for_each_rtd_codec_dais' + - 'for_each_rtd_codec_dais_rollback' + - 'for_each_rtd_components' + - 'for_each_rtd_cpu_dais' + - 'for_each_rtd_cpu_dais_rollback' + - 'for_each_rtd_dais' + - 'for_each_set_bit' + - 'for_each_set_bit_from' + - 'for_each_set_clump8' + - 'for_each_sg' + - 'for_each_sg_dma_page' + - 'for_each_sg_page' + - 'for_each_sgtable_dma_page' + - 'for_each_sgtable_dma_sg' + - 'for_each_sgtable_page' + - 'for_each_sgtable_sg' + - 'for_each_sibling_event' + - 'for_each_subelement' + - 'for_each_subelement_extid' + - 'for_each_subelement_id' + - '__for_each_thread' + - 'for_each_thread' + - 'for_each_unicast_dest_pgid' + - 'for_each_wakeup_source' + - 'for_each_zone' + - 'for_each_zone_zonelist' + - 'for_each_zone_zonelist_nodemask' + - 'fwnode_for_each_available_child_node' + - 'fwnode_for_each_child_node' + - 'fwnode_graph_for_each_endpoint' + - 'gadget_for_each_ep' + - 'genradix_for_each' + - 'genradix_for_each_from' + - 'hash_for_each' + - 'hash_for_each_possible' + - 'hash_for_each_possible_rcu' + - 'hash_for_each_possible_rcu_notrace' + - 'hash_for_each_possible_safe' + - 'hash_for_each_rcu' + - 'hash_for_each_safe' + - 'hctx_for_each_ctx' + - 'hlist_bl_for_each_entry' + - 'hlist_bl_for_each_entry_rcu' + - 'hlist_bl_for_each_entry_safe' + - 'hlist_for_each' + - 'hlist_for_each_entry' + - 'hlist_for_each_entry_continue' + - 'hlist_for_each_entry_continue_rcu' + - 'hlist_for_each_entry_continue_rcu_bh' + - 'hlist_for_each_entry_from' + - 'hlist_for_each_entry_from_rcu' + - 'hlist_for_each_entry_rcu' + - 'hlist_for_each_entry_rcu_bh' + - 'hlist_for_each_entry_rcu_notrace' + - 'hlist_for_each_entry_safe' + - '__hlist_for_each_rcu' + - 'hlist_for_each_safe' + - 'hlist_nulls_for_each_entry' + - 'hlist_nulls_for_each_entry_from' + - 'hlist_nulls_for_each_entry_rcu' + - 'hlist_nulls_for_each_entry_safe' + - 'i3c_bus_for_each_i2cdev' + - 'i3c_bus_for_each_i3cdev' + - 'ide_host_for_each_port' + - 'ide_port_for_each_dev' + - 'ide_port_for_each_present_dev' + - 'idr_for_each_entry' + - 'idr_for_each_entry_continue' + - 'idr_for_each_entry_continue_ul' + - 'idr_for_each_entry_ul' + - 'in_dev_for_each_ifa_rcu' + - 'in_dev_for_each_ifa_rtnl' + - 'inet_bind_bucket_for_each' + - 'inet_lhash2_for_each_icsk_rcu' + - 'key_for_each' + - 'key_for_each_safe' + - 'klp_for_each_func' + - 'klp_for_each_func_safe' + - 'klp_for_each_func_static' + - 'klp_for_each_object' + - 'klp_for_each_object_safe' + - 'klp_for_each_object_static' + - 'kunit_suite_for_each_test_case' + - 'kvm_for_each_memslot' + - 'kvm_for_each_vcpu' + - 'list_for_each' + - 'list_for_each_codec' + - 'list_for_each_codec_safe' + - 'list_for_each_continue' + - 'list_for_each_entry' + - 'list_for_each_entry_continue' + - 'list_for_each_entry_continue_rcu' + - 'list_for_each_entry_continue_reverse' + - 'list_for_each_entry_from' + - 'list_for_each_entry_from_rcu' + - 'list_for_each_entry_from_reverse' + - 'list_for_each_entry_lockless' + - 'list_for_each_entry_rcu' + - 'list_for_each_entry_reverse' + - 'list_for_each_entry_safe' + - 'list_for_each_entry_safe_continue' + - 'list_for_each_entry_safe_from' + - 'list_for_each_entry_safe_reverse' + - 'list_for_each_prev' + - 'list_for_each_prev_safe' + - 'list_for_each_safe' + - 'llist_for_each' + - 'llist_for_each_entry' + - 'llist_for_each_entry_safe' + - 'llist_for_each_safe' + - 'mci_for_each_dimm' + - 'media_device_for_each_entity' + - 'media_device_for_each_intf' + - 'media_device_for_each_link' + - 'media_device_for_each_pad' + - 'nanddev_io_for_each_page' + - 'netdev_for_each_lower_dev' + - 'netdev_for_each_lower_private' + - 'netdev_for_each_lower_private_rcu' + - 'netdev_for_each_mc_addr' + - 'netdev_for_each_uc_addr' + - 'netdev_for_each_upper_dev_rcu' + - 'netdev_hw_addr_list_for_each' + - 'nft_rule_for_each_expr' + - 'nla_for_each_attr' + - 'nla_for_each_nested' + - 'nlmsg_for_each_attr' + - 'nlmsg_for_each_msg' + - 'nr_neigh_for_each' + - 'nr_neigh_for_each_safe' + - 'nr_node_for_each' + - 'nr_node_for_each_safe' + - 'of_for_each_phandle' + - 'of_property_for_each_string' + - 'of_property_for_each_u32' + - 'pci_bus_for_each_resource' + - 'pcm_for_each_format' + - 'ping_portaddr_for_each_entry' + - 'plist_for_each' + - 'plist_for_each_continue' + - 'plist_for_each_entry' + - 'plist_for_each_entry_continue' + - 'plist_for_each_entry_safe' + - 'plist_for_each_safe' + - 'pnp_for_each_card' + - 'pnp_for_each_dev' + - 'protocol_for_each_card' + - 'protocol_for_each_dev' + - 'queue_for_each_hw_ctx' + - 'radix_tree_for_each_slot' + - 'radix_tree_for_each_tagged' + - 'rbtree_postorder_for_each_entry_safe' + - 'rdma_for_each_block' + - 'rdma_for_each_port' + - 'rdma_umem_for_each_dma_block' + - 'resource_list_for_each_entry' + - 'resource_list_for_each_entry_safe' + - 'rhl_for_each_entry_rcu' + - 'rhl_for_each_rcu' + - 'rht_for_each' + - 'rht_for_each_entry' + - 'rht_for_each_entry_from' + - 'rht_for_each_entry_rcu' + - 'rht_for_each_entry_rcu_from' + - 'rht_for_each_entry_safe' + - 'rht_for_each_from' + - 'rht_for_each_rcu' + - 'rht_for_each_rcu_from' + - '__rq_for_each_bio' + - 'rq_for_each_bvec' + - 'rq_for_each_segment' + - 'scsi_for_each_prot_sg' + - 'scsi_for_each_sg' + - 'sctp_for_each_hentry' + - 'sctp_skb_for_each' + - 'shdma_for_each_chan' + - '__shost_for_each_device' + - 'shost_for_each_device' + - 'sk_for_each' + - 'sk_for_each_bound' + - 'sk_for_each_entry_offset_rcu' + - 'sk_for_each_from' + - 'sk_for_each_rcu' + - 'sk_for_each_safe' + - 'sk_nulls_for_each' + - 'sk_nulls_for_each_from' + - 'sk_nulls_for_each_rcu' + - 'snd_array_for_each' + - 'snd_pcm_group_for_each_entry' + - 'snd_soc_dapm_widget_for_each_path' + - 'snd_soc_dapm_widget_for_each_path_safe' + - 'snd_soc_dapm_widget_for_each_sink_path' + - 'snd_soc_dapm_widget_for_each_source_path' + - 'tb_property_for_each' + - 'tcf_exts_for_each_action' + - 'udp_portaddr_for_each_entry' + - 'udp_portaddr_for_each_entry_rcu' + - 'usb_hub_for_each_child' + - 'v4l2_device_for_each_subdev' + - 'v4l2_m2m_for_each_dst_buf' + - 'v4l2_m2m_for_each_dst_buf_safe' + - 'v4l2_m2m_for_each_src_buf' + - 'v4l2_m2m_for_each_src_buf_safe' + - 'virtio_device_for_each_vq' + - 'while_for_each_ftrace_op' + - 'xa_for_each' + - 'xa_for_each_marked' + - 'xa_for_each_range' + - 'xa_for_each_start' + - 'xas_for_each' + - 'xas_for_each_conflict' + - 'xas_for_each_marked' + - 'xbc_array_for_each_value' + - 'xbc_for_each_key_value' + - 'xbc_node_for_each_array_value' + - 'xbc_node_for_each_child' + - 'xbc_node_for_each_key_value' + - 'zorro_for_each_dev' + +#IncludeBlocks: Preserve # Unknown to clang-format-5.0 +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +#IndentPPDirectives: None # Unknown to clang-format-5.0 +IndentWidth: 8 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0 +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 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +#SortUsingDeclarations: false # Unknown to clang-format-4.0 +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0 +#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0 +SpaceBeforeParens: ControlStatements +#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0 +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Always +... diff --git a/camera.c b/camera.c index 0e4364a..6e80781 100644 --- a/camera.c +++ b/camera.c @@ -10,1130 +10,1194 @@ #define MAX_VIDEO_BUFFERS 20 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) +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) +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) +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) +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) +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) +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) +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_width_to_bytes(MPPixelFormat pixel_format, uint32_t width) +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) +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) +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) +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) +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) +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; + uint32_t length; + uint8_t *data; }; 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; - bool use_mplane; + bool use_mplane; }; -MPCamera *mp_camera_new(int video_fd, int subdev_fd) +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; - 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; + return camera; } -void mp_camera_free(MPCamera *camera) +void +mp_camera_free(MPCamera *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); } -bool mp_camera_is_subdev(MPCamera *camera) +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) +int +mp_camera_get_video_fd(MPCamera *camera) { - return camera->video_fd; + return camera->video_fd; } -int mp_camera_get_subdev_fd(MPCamera *camera) +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) +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) +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) +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) +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) +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; + } - ++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"); + } + } - // 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) +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"); + } + } - 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) +bool +mp_camera_is_capturing(MPCamera *camera) { - return camera->num_buffers > 0; + return camera->num_buffers > 0; } -bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), void *user_data) +bool +mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), + void *user_data) { - 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"); - 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"); + 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); - MPImage image = { - .pixel_format = pixel_format, - .width = width, - .height = height, - .data = camera->buffers[buf.index].data, - }; + MPImage image = { + .pixel_format = pixel_format, + .width = width, + .height = height, + .data = camera->buffers[buf.index].data, + }; - callback(image, user_data); + callback(image, user_data); - // The callback may have stopped the capture, only queue the buffer if we're - // still capturing. - if (mp_camera_is_capturing(camera)) { - if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { - errno_printerr("VIDIOC_QBUF"); - return false; - } - } + // The callback may have stopped the capture, only queue the buffer if we're + // still capturing. + if (mp_camera_is_capturing(camera)) { + if (xioctl(camera->video_fd, VIDIOC_QBUF, &buf) == -1) { + errno_printerr("VIDIOC_QBUF"); + return false; + } + } - return true; + 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) +static bool +all_modes(MPCamera *camera, MPCameraMode *mode) { - return true; + return true; } -static bool available_modes(MPCamera *camera, MPCameraMode *mode) +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) +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) +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) +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) +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) +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) +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) +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) +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 * +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) +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) +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) +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) +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) +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; } -bool mp_camera_control_try_int32(MPCamera *camera, uint32_t id, int32_t *v) +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) +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 +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) +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) +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) +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; } diff --git a/camera.h b/camera.h index 80af844..3004e8e 100644 --- a/camera.h +++ b/camera.h @@ -5,19 +5,19 @@ #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); @@ -31,23 +31,24 @@ uint32_t mp_pixel_format_to_v4l_bus_code(MPPixelFormat pixel_format); uint32_t mp_pixel_format_bits_per_pixel(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 mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, + 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 pixel_format; - uint32_t width; - uint32_t height; - uint8_t *data; + uint32_t pixel_format; + uint32_t width; + uint32_t height; + uint8_t *data; } MPImage; typedef struct _MPCamera MPCamera; @@ -66,7 +67,8 @@ bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode); bool mp_camera_start_capture(MPCamera *camera); bool mp_camera_stop_capture(MPCamera *camera); bool mp_camera_is_capturing(MPCamera *camera); -bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), void *user_data); +bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *), + void *user_data); typedef struct _MPCameraModeList MPCameraModeList; @@ -77,21 +79,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/camera_config.c b/camera_config.c index 36eff8d..1e52d62 100644 --- a/camera_config.c +++ b/camera_config.c @@ -20,263 +20,269 @@ static char *exif_model; static bool find_config(char *conffile) { - char buf[512]; - char *xdg_config_home; - wordexp_t exp_result; - FILE *fp; + char buf[512]; + char *xdg_config_home; + wordexp_t exp_result; + FILE *fp; - // Resolve XDG stuff - if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) { - xdg_config_home = "~/.config"; - } - wordexp(xdg_config_home, &exp_result, 0); - xdg_config_home = strdup(exp_result.we_wordv[0]); - wordfree(&exp_result); + // Resolve XDG stuff + if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) { + xdg_config_home = "~/.config"; + } + wordexp(xdg_config_home, &exp_result, 0); + xdg_config_home = strdup(exp_result.we_wordv[0]); + wordfree(&exp_result); - 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", xdg_config_home, 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", xdg_config_home, + 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) + 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 { - g_printerr("Unknown key '%s' in [%s]\n", name, section); - exit(1); - } - } - return 1; + 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 { + g_printerr("Unknown key '%s' in [%s]\n", name, section); + exit(1); + } + } + return 1; } void -calculate_matrices() { +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); + 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; - } - - 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(); - - return true; -} - -const char * mp_get_device_make() +bool +mp_load_config() { - return exif_make; + 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; + } + + calculate_matrices(); + + return true; } -const char * mp_get_device_model() +const char * +mp_get_device_make() { - return exif_model; + return exif_make; } -const struct mp_camera_config * mp_get_camera_config(size_t index) +const char * +mp_get_device_model() { - if (index >= num_cameras) - return NULL; - - return &cameras[index]; + return exif_model; +} + +const struct mp_camera_config * +mp_get_camera_config(size_t index) +{ + if (index >= num_cameras) + return NULL; + + return &cameras[index]; } diff --git a/camera_config.h b/camera_config.h index 10817ae..f506af8 100644 --- a/camera_config.h +++ b/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; }; bool mp_load_config(); const char *mp_get_device_make(); const char *mp_get_device_model(); -const struct mp_camera_config * mp_get_camera_config(size_t index); +const struct mp_camera_config *mp_get_camera_config(size_t index); diff --git a/device.c b/device.c index a20434e..e8e6153 100644 --- a/device.c +++ b/device.c @@ -8,416 +8,456 @@ #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) { - 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) +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) +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) +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) +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) +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) +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) +bool +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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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) +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_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) +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) +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) +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) +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) +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) +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 * +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) +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 * +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 * +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) +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) +MPDeviceList * +mp_device_list_next(const MPDeviceList *device_list) { - return device_list->next; + return device_list->next; } diff --git a/device.h b/device.h index be7e1ba..c47a40d 100644 --- a/device.h +++ b/device.h @@ -5,7 +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; @@ -14,26 +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 struct media_v2_entity *mp_device_find_entity_type(const MPDevice *device, const uint32_t type); -const struct media_v2_entity *mp_device_get_entity(const MPDevice *device, uint32_t id); +const struct media_v2_entity *mp_device_find_entity(const MPDevice *device, + const char *driver_name); +const struct media_v2_entity *mp_device_find_entity_type(const MPDevice *device, + const uint32_t type); +const struct media_v2_entity *mp_device_get_entity(const MPDevice *device, + 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); +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); 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); +const struct media_v2_pad *mp_device_get_pad_from_entity(const MPDevice *device, + 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); -const struct media_v2_link *mp_device_find_link_from(const MPDevice *device, uint32_t source); -const struct media_v2_link *mp_device_find_link_to(const MPDevice *device, 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_find_entity_link(const MPDevice *device, + uint32_t entity_id); +const struct media_v2_link *mp_device_find_link_from(const MPDevice *device, + uint32_t source); +const struct media_v2_link *mp_device_find_link_to(const MPDevice *device, + 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); const struct media_v2_link *mp_device_get_links(const MPDevice *device); size_t mp_device_get_num_links(const MPDevice *device); @@ -43,7 +55,8 @@ typedef struct _MPDeviceList MPDeviceList; 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); +MPDevice *mp_device_list_find_remove(MPDeviceList **device_list, + const char *driver_name); MPDevice *mp_device_list_remove(MPDeviceList **device_list); MPDevice *mp_device_list_get(const MPDeviceList *device_list); diff --git a/ini.c b/ini.c index 6bc1eae..201145c 100644 --- a/ini.c +++ b/ini.c @@ -25,171 +25,174 @@ https://github.com/benhoyt/inih #define MAX_NAME 50 /* Strip whitespace chars off end of given string, in place. Return s. */ -static char* rstrip(char* s) +static char * +rstrip(char *s) { - char* p = s + strlen(s); - while (p > s && isspace((unsigned char)(*--p))) - *p = '\0'; - return s; + char *p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; } /* Return pointer to first non-whitespace char in given string. */ -static char* lskip(const char* s) +static char * +lskip(const char *s) { - while (*s && isspace((unsigned char)(*s))) - s++; - return (char*)s; + while (*s && isspace((unsigned char)(*s))) + s++; + return (char *)s; } /* Return pointer to first char (of chars) or inline comment in given string, or pointer to null at end of string if neither found. Inline comment must be prefixed by a whitespace character to register as a comment. */ -static char* find_chars_or_comment(const char* s, const char* chars) +static char * +find_chars_or_comment(const char *s, const char *chars) { #if INI_ALLOW_INLINE_COMMENTS - int was_space = 0; - while (*s && (!chars || !strchr(chars, *s)) && - !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { - was_space = isspace((unsigned char)(*s)); - s++; - } + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } #else - while (*s && (!chars || !strchr(chars, *s))) { - s++; - } + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } #endif - return (char*)s; + return (char *)s; } /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -static char* strncpy0(char* dest, const char* src, size_t size) +static char * +strncpy0(char *dest, const char *src, size_t size) { - strncpy(dest, src, size-1); - dest[size - 1] = '\0'; - return dest; + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; } /* See documentation in header file. */ -int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, - void* user) +int +ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, void *user) { - /* Uses a fair bit of stack (use heap instead if you need to) */ + /* Uses a fair bit of stack (use heap instead if you need to) */ #if INI_USE_STACK - char line[INI_MAX_LINE]; + char line[INI_MAX_LINE]; #else - char* line; + char *line; #endif - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; - char* start; - char* end; - char* name; - char* value; - int lineno = 0; - int error = 0; + char *start; + char *end; + char *name; + char *value; + int lineno = 0; + int error = 0; #if !INI_USE_STACK - line = (char*)malloc(INI_MAX_LINE); - if (!line) { - return -2; - } + line = (char *)malloc(INI_MAX_LINE); + if (!line) { + return -2; + } #endif - /* Scan through stream line by line */ - while (reader(line, INI_MAX_LINE, stream) != NULL) { - lineno++; + /* Scan through stream line by line */ + while (reader(line, INI_MAX_LINE, stream) != NULL) { + lineno++; - start = line; + start = line; #if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) { - start += 3; - } + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } #endif - start = lskip(rstrip(start)); + start = lskip(rstrip(start)); - if (*start == ';' || *start == '#') { - /* Per Python configparser, allow both ; and # comments at the + if (*start == ';' || *start == '#') { + /* Per Python configparser, allow both ; and # comments at the start of a line */ - } + } #if INI_ALLOW_MULTILINE - else if (*prev_name && *start && start > line) { - /* Non-blank line with leading whitespace, treat as continuation + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation of previous name's value (as per Python configparser). */ - if (!handler(user, section, prev_name, start) && !error) - error = lineno; - } + if (!handler(user, section, prev_name, start) && !error) + error = lineno; + } #endif - else if (*start == '[') { - /* A "[section]" line */ - end = find_chars_or_comment(start + 1, "]"); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; - } - else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } - else if (*start) { - /* Not a comment, must be a name[=:]value pair */ - end = find_chars_or_comment(start, "=:"); - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = lskip(end + 1); + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = lskip(end + 1); #if INI_ALLOW_INLINE_COMMENTS - end = find_chars_or_comment(value, NULL); - if (*end) - *end = '\0'; + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; #endif - rstrip(value); + rstrip(value); - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!handler(user, section, name, value) && !error) - error = lineno; + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!handler(user, section, name, value) && !error) + error = lineno; memset(value, 0, strlen(value)); - } - else if (!error) { - /* No '=' or ':' found on name[=:]value line */ - error = lineno; - } - } + } else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } #if INI_STOP_ON_FIRST_ERROR - if (error) - break; + if (error) + break; #endif - } + } #if !INI_USE_STACK - free(line); + free(line); #endif - return error; + return error; } /* See documentation in header file. */ -int ini_parse_file(FILE* file, ini_handler handler, void* user) +int +ini_parse_file(FILE *file, ini_handler handler, void *user) { - return ini_parse_stream((ini_reader)fgets, file, handler, user); + return ini_parse_stream((ini_reader)fgets, file, handler, user); } /* See documentation in header file. */ -int ini_parse(const char* filename, ini_handler handler, void* user) +int +ini_parse(const char *filename, ini_handler handler, void *user) { - FILE* file; - int error; + FILE *file; + int error; - file = fopen(filename, "r"); - if (!file) - return -1; - error = ini_parse_file(file, handler, user); - fclose(file); - return error; + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; } diff --git a/ini.h b/ini.h index 2804255..aa03e69 100644 --- a/ini.h +++ b/ini.h @@ -18,11 +18,11 @@ extern "C" { #include /* Typedef for prototype of handler function. */ -typedef int (*ini_handler)(void* user, const char* section, - const char* name, const char* value); +typedef int (*ini_handler)(void *user, const char *section, const char *name, + const char *value); /* Typedef for prototype of fgets-style reader function. */ -typedef char* (*ini_reader)(char* str, int num, void* stream); +typedef char *(*ini_reader)(char *str, int num, void *stream); /* Parse given INI-style file. May have [section]s, name=value pairs (whitespace stripped), and comments starting with ';' (semicolon). Section @@ -37,16 +37,16 @@ typedef char* (*ini_reader)(char* str, int num, void* stream); stop on first error), -1 on file open error, or -2 on memory allocation error (only when INI_USE_STACK is zero). */ -int ini_parse(const char* filename, ini_handler handler, void* user); +int ini_parse(const char *filename, ini_handler handler, void *user); /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't close the file when it's finished -- the caller must do that. */ -int ini_parse_file(FILE* file, ini_handler handler, void* user); +int ini_parse_file(FILE *file, ini_handler handler, void *user); /* Same as ini_parse(), but takes an ini_reader function pointer instead of filename. Used for implementing custom or string-based I/O. */ -int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, - void* user); +int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, + void *user); /* Nonzero to allow multi-line value parsing, in the style of Python's configparser. If allowed, ini_parse() will call the handler with the same diff --git a/io_pipeline.c b/io_pipeline.c index fee30cc..e7b2ca9 100644 --- a/io_pipeline.c +++ b/io_pipeline.c @@ -13,51 +13,49 @@ #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; - 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]; @@ -78,11 +76,11 @@ static int preview_width; static int preview_height; 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 = {}; @@ -93,413 +91,450 @@ static bool want_focus = false; static MPPipeline *pipeline; static GSource *capture_source; -static void setup_camera(MPDeviceList **device_list, const struct mp_camera_config *config) +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\n", dev_name); - exit(EXIT_FAILURE); - } + info->video_fd = open(dev_name, O_RDWR); + if (info->video_fd == -1) { + g_printerr("Could not open %s\n", dev_name); + 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\n", info->dev_fname); - exit(EXIT_FAILURE); - } + info->fd = open(info->dev_fname, O_RDWR); + if (info->fd == -1) { + g_printerr("Could not open %s\n", info->dev_fname); + 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); - // 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(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(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; + } + } } -static void setup(MPPipeline *pipeline, const void *data) +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); } -void mp_io_pipeline_start() +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() +void +mp_io_pipeline_stop() { - if (capture_source) { - g_source_destroy(capture_source); - } + if (capture_source) { + g_source_destroy(capture_source); + } - 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, - .preview_width = preview_width, - .preview_height = preview_height, - .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, + .preview_width = preview_width, + .preview_height = preview_height, + .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() +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_camera_stop_capture(info->camera); + // Change camera mode for capturing + 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); - update_process_pipeline(); + update_process_pipeline(); - mp_process_pipeline_capture(); + mp_process_pipeline_capture(); } -void mp_io_pipeline_capture() +void +mp_io_pipeline_capture() { - mp_pipeline_invoke(pipeline, capture, NULL, 0); + mp_pipeline_invoke(pipeline, capture, NULL, 0); } 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) { - if (info->has_auto_focus_continuous) { - mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, 1); - } else if (info->has_auto_focus_start) { - mp_camera_control_set_bool(info->camera, V4L2_CID_AUTO_FOCUS_START, 1); - } + if (want_focus) { + if (info->has_auto_focus_continuous) { + mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, + 1); + } else if (info->has_auto_focus_start) { + mp_camera_control_set_bool(info->camera, + V4L2_CID_AUTO_FOCUS_START, 1); + } - want_focus = false; - } + want_focus = false; + } - if (current_controls.gain_is_manual != desired_controls.gain_is_manual) { - mp_camera_control_set_bool(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(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(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(info->camera, info->gain_ctrl, + desired_controls.gain); + } - if (current_controls.exposure_is_manual != desired_controls.exposure_is_manual) { - mp_camera_control_set_int32( - 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(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(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(info->camera, V4L2_CID_EXPOSURE, + desired_controls.exposure); + } - current_controls = desired_controls; + current_controls = desired_controls; } static void on_frame(MPImage image, 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 50x50 area - size_t test_size = MIN(50, image.width) * MIN(50, image.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 50x50 area + size_t test_size = + MIN(50, image.width) * MIN(50, image.height); - bool image_is_blank = true; - for (size_t i = 0; i < test_size; ++i) { - if (image.data[i] != 0) { - image_is_blank = false; - } - } + bool image_is_blank = true; + for (size_t i = 0; i < test_size; ++i) { + if (image.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; + } - // Copy from the camera buffer - size_t size = mp_pixel_format_width_to_bytes(image.pixel_format, image.width) * image.height; - uint8_t *buffer = malloc(size); - memcpy(buffer, image.data, size); + // Copy from the camera buffer + size_t size = + mp_pixel_format_width_to_bytes(image.pixel_format, image.width) * + image.height; + uint8_t *buffer = malloc(size); + memcpy(buffer, image.data, size); - image.data = buffer; + image.data = buffer; - // Send the image off for processing - mp_process_pipeline_process_image(image); + // Send the image off for processing + mp_process_pipeline_process_image(image); - 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(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(info->camera, + V4L2_CID_EXPOSURE_AUTO, + V4L2_EXPOSURE_AUTO); + } - if (!current_controls.gain_is_manual) { - mp_camera_control_set_bool(info->camera, V4L2_CID_AUTOGAIN, true); - } + if (!current_controls.gain_is_manual) { + mp_camera_control_set_bool(info->camera, + V4L2_CID_AUTOGAIN, true); + } - // Go back to preview mode - mp_camera_stop_capture(info->camera); + // Go back to preview mode + 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); - 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_camera_stop_capture(info->camera); - mp_device_setup_link( - dev_info->device, - info->pad_id, - dev_info->interface_pad_id, - false); - } + 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_int32(info->camera, V4L2_CID_EXPOSURE_AUTO) == V4L2_EXPOSURE_MANUAL; - current_controls.gain = mp_camera_control_get_int32(info->camera, info->gain_ctrl); + current_controls.gain_is_manual = + mp_camera_control_get_int32( + info->camera, V4L2_CID_EXPOSURE_AUTO) == + V4L2_EXPOSURE_MANUAL; + current_controls.gain = mp_camera_control_get_int32( + info->camera, info->gain_ctrl); - current_controls.exposure_is_manual = mp_camera_control_get_bool(info->camera, V4L2_CID_AUTOGAIN) == 0; - current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); - } - } + current_controls.exposure_is_manual = + mp_camera_control_get_bool(info->camera, + V4L2_CID_AUTOGAIN) == 0; + 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; + has_changed = has_changed || burst_length != state->burst_length || + preview_width != state->preview_width || + preview_height != state->preview_height; - burst_length = state->burst_length; - preview_width = state->preview_width; - preview_height = state->preview_height; + burst_length = state->burst_length; + preview_width = state->preview_width; + preview_height = state->preview_height; - 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; - } + has_changed = + has_changed || memcmp(&previous_desired, &desired_controls, + sizeof(struct control_state)) != 0; + } - 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) +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/io_pipeline.h b/io_pipeline.h index 9962174..10a6298 100644 --- a/io_pipeline.h +++ b/io_pipeline.h @@ -3,18 +3,18 @@ #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; - bool gain_is_manual; - int gain; + bool gain_is_manual; + int gain; - bool exposure_is_manual; - int exposure; + bool exposure_is_manual; + int exposure; }; void mp_io_pipeline_start(); diff --git a/main.c b/main.c index 8dfe283..4e8ff00 100644 --- a/main.c +++ b/main.c @@ -21,10 +21,7 @@ #include "quickpreview.h" #include "io_pipeline.h" -enum user_control { - USER_CONTROL_ISO, - USER_CONTROL_SHUTTER -}; +enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER }; static bool camera_is_initialized = false; static const struct mp_camera_config *camera = NULL; @@ -121,17 +118,14 @@ update_state(const struct mp_main_state *state) return false; } -void mp_main_update_state(const struct mp_main_state *state) +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; - 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 @@ -145,19 +139,16 @@ set_preview(cairo_surface_t *image) return false; } -void mp_main_set_preview(cairo_surface_t *image) +void +mp_main_set_preview(cairo_surface_t *image) { - g_main_context_invoke_full( - g_main_context_default(), - G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)set_preview, - image, - NULL); + g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)set_preview, image, NULL); } static void -draw_surface_scaled_centered( - cairo_t *cr, uint32_t dst_width, uint32_t dst_height, cairo_surface_t *surface) +draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height, + cairo_surface_t *surface) { cairo_save(cr); @@ -165,7 +156,7 @@ draw_surface_scaled_centered( int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); - double scale = MIN(dst_width / (double) width, dst_height / (double) height); + double scale = MIN(dst_width / (double)width, dst_height / (double)height); cairo_scale(cr, scale, scale); cairo_translate(cr, -width / 2, -height / 2); @@ -181,10 +172,8 @@ capture_completed(const char *fname) strncpy(last_path, fname, 260); // Create a thumbnail from the current surface - cairo_surface_t *thumb = cairo_image_surface_create( - CAIRO_FORMAT_ARGB32, - 24, - 24); + cairo_surface_t *thumb = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 24, 24); cairo_t *cr = cairo_create(thumb); draw_surface_scaled_centered(cr, 24, 24, surface); @@ -196,16 +185,13 @@ capture_completed(const char *fname) return false; } -void mp_main_capture_completed(const char *fname) +void +mp_main_capture_completed(const char *fname) { gchar *name = g_strdup(fname); - g_main_context_invoke_full( - g_main_context_default(), - G_PRIORITY_DEFAULT_IDLE, - (GSourceFunc)capture_completed, - name, - g_free); + g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE, + (GSourceFunc)capture_completed, name, g_free); } static void @@ -217,14 +203,16 @@ draw_controls() char shutterangle[6]; if (exposure_is_manual) { - temp = (int)((float)exposure / (float)camera->capture_mode.height * 360); + temp = (int)((float)exposure / (float)camera->capture_mode.height * + 360); sprintf(shutterangle, "%d\u00b0", temp); } else { sprintf(shutterangle, "auto"); } if (gain_is_manual) { - temp = remap(gain - 1, 0, gain_max, camera->iso_min, camera->iso_max); + temp = remap(gain - 1, 0, gain_max, camera->iso_min, + camera->iso_max); sprintf(iso, "%d", temp); } else { sprintf(iso, "auto"); @@ -237,16 +225,18 @@ draw_controls() if (gtk_widget_get_window(preview) == NULL) { return; } - status_surface = gdk_window_create_similar_surface(gtk_widget_get_window(preview), - CAIRO_CONTENT_COLOR_ALPHA, - preview_width, 32); + status_surface = + gdk_window_create_similar_surface(gtk_widget_get_window(preview), + CAIRO_CONTENT_COLOR_ALPHA, + preview_width, 32); cr = cairo_create(status_surface); cairo_set_source_rgba(cr, 0, 0, 0, 0.0); cairo_paint(cr); // Draw the outlines for the headings - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cr, 9); cairo_set_source_rgba(cr, 0, 0, 0, 1); @@ -266,7 +256,8 @@ draw_controls() cairo_show_text(cr, "Shutter"); // Draw the outlines for the values - cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_select_font_face(cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 11); cairo_set_source_rgba(cr, 0, 0, 0, 1); @@ -286,7 +277,7 @@ draw_controls() cairo_show_text(cr, shutterangle); cairo_destroy(cr); - + gtk_widget_queue_draw_area(preview, 0, 0, preview_width, 32); } @@ -302,7 +293,8 @@ preview_draw(GtkWidget *widget, cairo_t *cr, gpointer data) // Draw camera preview if (surface) { - draw_surface_scaled_centered(cr, preview_width, preview_height, surface); + draw_surface_scaled_centered(cr, preview_width, preview_height, + surface); } // Draw control overlay @@ -311,15 +303,14 @@ preview_draw(GtkWidget *widget, cairo_t *cr, gpointer data) return FALSE; } - static gboolean preview_configure(GtkWidget *widget, GdkEventConfigure *event) { int new_preview_width = gtk_widget_get_allocated_width(widget); int new_preview_height = gtk_widget_get_allocated_height(widget); - if (preview_width != new_preview_width || preview_height != new_preview_height) - { + if (preview_width != new_preview_width || + preview_height != new_preview_height) { preview_width = new_preview_width; preview_height = new_preview_height; update_io_pipeline(); @@ -336,11 +327,11 @@ on_open_last_clicked(GtkWidget *widget, gpointer user_data) char uri[275]; GError *error = NULL; - if(strlen(last_path) == 0) { + if (strlen(last_path) == 0) { return; } sprintf(uri, "file://%s.tiff", last_path); - if(!g_app_info_launch_default_for_uri(uri, NULL, &error)){ + if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) { g_printerr("Could not launch image viewer: %s\n", error->message); } } @@ -351,7 +342,7 @@ on_open_directory_clicked(GtkWidget *widget, gpointer user_data) char uri[270]; GError *error = NULL; sprintf(uri, "file://%s/Pictures", getenv("HOME")); - if(!g_app_info_launch_default_for_uri(uri, NULL, &error)){ + if (!g_app_info_launch_default_for_uri(uri, NULL, &error)) { g_printerr("Could not launch image viewer: %s\n", error->message); } } @@ -377,11 +368,12 @@ on_preview_tap(GtkWidget *widget, GdkEventButton *event, gpointer user_data) gtk_widget_show(control_box); } - if (event->x < 60 ) { + if (event->x < 60) { // ISO current_control = USER_CONTROL_ISO; gtk_label_set_text(GTK_LABEL(control_name), "ISO"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), !gain_is_manual); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), + !gain_is_manual); gtk_adjustment_set_lower(control_slider, 0.0); gtk_adjustment_set_upper(control_slider, (float)gain_max); gtk_adjustment_set_value(control_slider, (double)gain); @@ -390,7 +382,8 @@ on_preview_tap(GtkWidget *widget, GdkEventButton *event, gpointer user_data) // Shutter angle current_control = USER_CONTROL_SHUTTER; gtk_label_set_text(GTK_LABEL(control_name), "Shutter"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), !exposure_is_manual); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(control_auto), + !exposure_is_manual); gtk_adjustment_set_lower(control_slider, 1.0); gtk_adjustment_set_upper(control_slider, 360.0); gtk_adjustment_set_value(control_slider, (double)exposure); @@ -415,7 +408,8 @@ void on_camera_switch_clicked(GtkWidget *widget, gpointer user_data) { size_t next_index = camera->index + 1; - const struct mp_camera_config *next_camera = mp_get_camera_config(next_index); + const struct mp_camera_config *next_camera = + mp_get_camera_config(next_index); if (!next_camera) { next_index = 0; @@ -445,18 +439,18 @@ on_control_auto_toggled(GtkToggleButton *widget, gpointer user_data) bool has_changed; switch (current_control) { - case USER_CONTROL_ISO: - if (gain_is_manual != is_manual) { - gain_is_manual = is_manual; - has_changed = true; - } - break; - case USER_CONTROL_SHUTTER: - if (exposure_is_manual != is_manual) { - exposure_is_manual = is_manual; - has_changed = true; - } - break; + case USER_CONTROL_ISO: + if (gain_is_manual != is_manual) { + gain_is_manual = is_manual; + has_changed = true; + } + break; + case USER_CONTROL_SHUTTER: + if (exposure_is_manual != is_manual) { + exposure_is_manual = is_manual; + has_changed = true; + } + break; } if (has_changed) { @@ -472,22 +466,22 @@ on_control_slider_changed(GtkAdjustment *widget, gpointer user_data) bool has_changed = false; switch (current_control) { - case USER_CONTROL_ISO: - if (value != gain) { - gain = (int)value; - has_changed = true; - } - break; - case USER_CONTROL_SHUTTER: - { - // So far all sensors use exposure time in number of sensor rows - int new_exposure = (int)(value / 360.0 * camera->capture_mode.height); - if (new_exposure != exposure) { - exposure = new_exposure; - has_changed = true; - } - break; + case USER_CONTROL_ISO: + if (value != gain) { + gain = (int)value; + has_changed = true; } + break; + case USER_CONTROL_SHUTTER: { + // So far all sensors use exposure time in number of sensor rows + int new_exposure = + (int)(value / 360.0 * camera->capture_mode.height); + if (new_exposure != exposure) { + exposure = new_exposure; + has_changed = true; + } + break; + } } if (has_changed) { @@ -504,19 +498,26 @@ main(int argc, char *argv[]) setenv("LC_NUMERIC", "C", 1); - gtk_init(&argc, &argv); - g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", TRUE, NULL); - GtkBuilder *builder = gtk_builder_new_from_resource("/org/postmarketos/Megapixels/camera.glade"); + g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", + TRUE, NULL); + GtkBuilder *builder = gtk_builder_new_from_resource( + "/org/postmarketos/Megapixels/camera.glade"); GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); GtkWidget *shutter = GTK_WIDGET(gtk_builder_get_object(builder, "shutter")); - GtkWidget *switch_btn = GTK_WIDGET(gtk_builder_get_object(builder, "switch_camera")); - GtkWidget *settings_btn = GTK_WIDGET(gtk_builder_get_object(builder, "settings")); - GtkWidget *settings_back = GTK_WIDGET(gtk_builder_get_object(builder, "settings_back")); - GtkWidget *error_close = GTK_WIDGET(gtk_builder_get_object(builder, "error_close")); - GtkWidget *open_last = GTK_WIDGET(gtk_builder_get_object(builder, "open_last")); - GtkWidget *open_directory = GTK_WIDGET(gtk_builder_get_object(builder, "open_directory")); + GtkWidget *switch_btn = + GTK_WIDGET(gtk_builder_get_object(builder, "switch_camera")); + GtkWidget *settings_btn = + GTK_WIDGET(gtk_builder_get_object(builder, "settings")); + GtkWidget *settings_back = + GTK_WIDGET(gtk_builder_get_object(builder, "settings_back")); + GtkWidget *error_close = + GTK_WIDGET(gtk_builder_get_object(builder, "error_close")); + GtkWidget *open_last = + GTK_WIDGET(gtk_builder_get_object(builder, "open_last")); + GtkWidget *open_directory = + GTK_WIDGET(gtk_builder_get_object(builder, "open_directory")); preview = GTK_WIDGET(gtk_builder_get_object(builder, "preview")); error_box = GTK_WIDGET(gtk_builder_get_object(builder, "error_box")); error_message = GTK_WIDGET(gtk_builder_get_object(builder, "error_message")); @@ -524,38 +525,49 @@ main(int argc, char *argv[]) thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last")); control_box = GTK_WIDGET(gtk_builder_get_object(builder, "control_box")); control_name = GTK_WIDGET(gtk_builder_get_object(builder, "control_name")); - control_slider = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "control_adj")); + control_slider = + GTK_ADJUSTMENT(gtk_builder_get_object(builder, "control_adj")); control_auto = GTK_WIDGET(gtk_builder_get_object(builder, "control_auto")); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), NULL); - g_signal_connect(error_close, "clicked", G_CALLBACK(on_error_close_clicked), NULL); - g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked), NULL); - g_signal_connect(settings_btn, "clicked", G_CALLBACK(on_settings_btn_clicked), NULL); - g_signal_connect(settings_back, "clicked", G_CALLBACK(on_back_clicked), NULL); - g_signal_connect(open_last, "clicked", G_CALLBACK(on_open_last_clicked), NULL); - g_signal_connect(open_directory, "clicked", G_CALLBACK(on_open_directory_clicked), NULL); + g_signal_connect(error_close, "clicked", G_CALLBACK(on_error_close_clicked), + NULL); + g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked), + NULL); + g_signal_connect(settings_btn, "clicked", + G_CALLBACK(on_settings_btn_clicked), NULL); + g_signal_connect(settings_back, "clicked", G_CALLBACK(on_back_clicked), + NULL); + g_signal_connect(open_last, "clicked", G_CALLBACK(on_open_last_clicked), + NULL); + g_signal_connect(open_directory, "clicked", + G_CALLBACK(on_open_directory_clicked), NULL); g_signal_connect(preview, "draw", G_CALLBACK(preview_draw), NULL); - g_signal_connect(preview, "configure-event", G_CALLBACK(preview_configure), NULL); + g_signal_connect(preview, "configure-event", G_CALLBACK(preview_configure), + NULL); gtk_widget_set_events(preview, gtk_widget_get_events(preview) | - GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap), NULL); - g_signal_connect(control_auto, "toggled", G_CALLBACK(on_control_auto_toggled), NULL); - g_signal_connect(control_slider, "value-changed", G_CALLBACK(on_control_slider_changed), NULL); + GDK_BUTTON_PRESS_MASK | + GDK_POINTER_MOTION_MASK); + g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap), + NULL); + g_signal_connect(control_auto, "toggled", + G_CALLBACK(on_control_auto_toggled), NULL); + g_signal_connect(control_slider, "value-changed", + G_CALLBACK(on_control_slider_changed), NULL); GtkCssProvider *provider = gtk_css_provider_new(); if (access("camera.css", F_OK) != -1) { gtk_css_provider_load_from_path(provider, "camera.css", NULL); } else { - gtk_css_provider_load_from_resource(provider, "/org/postmarketos/Megapixels/camera.css"); + gtk_css_provider_load_from_resource( + provider, "/org/postmarketos/Megapixels/camera.css"); } GtkStyleContext *context = gtk_widget_get_style_context(error_box); - gtk_style_context_add_provider(context, - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); + gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); context = gtk_widget_get_style_context(control_box); - gtk_style_context_add_provider(context, - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); + gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); mp_io_pipeline_start(); diff --git a/main.h b/main.h index c99bb07..2fd65a0 100644 --- a/main.h +++ b/main.h @@ -4,18 +4,18 @@ #include "gtk/gtk.h" struct mp_main_state { - const struct mp_camera_config *camera; - MPCameraMode mode; + const struct mp_camera_config *camera; + MPCameraMode mode; - 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); @@ -23,5 +23,4 @@ void mp_main_update_state(const struct mp_main_state *state); void mp_main_set_preview(cairo_surface_t *image); void mp_main_capture_completed(const char *fname); -int -remap(int value, int input_min, int input_max, int output_min, int output_max); +int remap(int value, int input_min, int input_max, int output_min, int output_max); diff --git a/matrix.c b/matrix.c index f2f0607..b828816 100644 --- a/matrix.c +++ b/matrix.c @@ -1,14 +1,15 @@ void -multiply_matrices(float a[9], float b[9], float out[9]) { +multiply_matrices(float a[9], float b[9], float out[9]) +{ // zero out target matrix - for(int i=0; i<9; i++) { + 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/pipeline.c b/pipeline.c index 42ac8f1..fcfa4c2 100644 --- a/pipeline.c +++ b/pipeline.c @@ -5,104 +5,106 @@ #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) +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 * +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) +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) +void +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); + } } -void mp_pipeline_free(MPPipeline *pipeline) +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)(MPImage, void *); - void *user_data; +struct capture_source_args { + MPCamera *camera; + void (*callback)(MPImage, void *); + void *user_data; }; -static bool on_capture(int fd, GIOCondition condition, struct capture_source_args *args) +static bool +on_capture(int fd, GIOCondition condition, struct capture_source_args *args) { - mp_camera_capture_image(args->camera, args->callback, args->user_data); - return true; + mp_camera_capture_image(args->camera, args->callback, args->user_data); + return true; } // Not thread safe -GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data) +GSource * +mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, + void (*callback)(MPImage, 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/pipeline.h b/pipeline.h index b40f572..6f71faa 100644 --- a/pipeline.h +++ b/pipeline.h @@ -9,7 +9,10 @@ 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); void mp_pipeline_free(MPPipeline *pipeline); -GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, void (*callback)(MPImage, void *), void *user_data); +GSource *mp_pipeline_add_capture_source(MPPipeline *pipeline, MPCamera *camera, + void (*callback)(MPImage, void *), + void *user_data); diff --git a/process_pipeline.c b/process_pipeline.c index 0bc8dca..33cb72b 100644 --- a/process_pipeline.c +++ b/process_pipeline.c @@ -12,11 +12,8 @@ #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 -}; +static const float colormatrix_srgb[] = { 3.2409, -1.5373, -0.4986, -0.9692, 1.8759, + 0.0415, 0.0556, -0.2039, 1.0569 }; static MPPipeline *pipeline; @@ -49,373 +46,378 @@ 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 *xdg_config_home; - char filename[] = "postprocess.sh"; - wordexp_t exp_result; + char *xdg_config_home; + char filename[] = "postprocess.sh"; + wordexp_t exp_result; - // Resolve XDG stuff - if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) { - xdg_config_home = "~/.config"; - } - wordexp(xdg_config_home, &exp_result, 0); - xdg_config_home = strdup(exp_result.we_wordv[0]); - wordfree(&exp_result); + // Resolve XDG stuff + if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL) { + xdg_config_home = "~/.config"; + } + wordexp(xdg_config_home, &exp_result, 0); + xdg_config_home = strdup(exp_result.we_wordv[0]); + wordfree(&exp_result); - // Check postprocess.h in the current working directory - sprintf(script, "%s", filename); - if(access(script, F_OK) != -1) { - sprintf(script, "./%s", filename); - printf("Found postprocessor script at %s\n", script); - return true; - } + // Check postprocess.h in the current working directory + sprintf(script, "%s", filename); + if (access(script, F_OK) != -1) { + sprintf(script, "./%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", xdg_config_home, 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", xdg_config_home, 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) +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() +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); } -void mp_process_pipeline_stop() +void +mp_process_pipeline_stop() { - mp_pipeline_free(pipeline); + mp_pipeline_free(pipeline); } static void process_image_for_preview(const MPImage *image) { - uint32_t surface_width, surface_height, skip; - quick_preview_size( - &surface_width, - &surface_height, - &skip, - preview_width, - preview_height, - image->width, - image->height, - image->pixel_format, - camera->rotate); + uint32_t surface_width, surface_height, skip; + quick_preview_size(&surface_width, &surface_height, &skip, preview_width, + preview_height, image->width, image->height, + image->pixel_format, camera->rotate); - cairo_surface_t *surface = cairo_image_surface_create( - CAIRO_FORMAT_RGB24, - surface_width, - surface_height); + cairo_surface_t *surface = cairo_image_surface_create( + CAIRO_FORMAT_RGB24, surface_width, surface_height); - uint8_t *pixels = cairo_image_surface_get_data(surface); + uint8_t *pixels = cairo_image_surface_get_data(surface); - quick_preview( - (uint32_t *)pixels, - surface_width, - surface_height, - image->data, - image->width, - image->height, - image->pixel_format, - camera->rotate, - camera->mirrored, - camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, - camera->blacklevel, - skip); + quick_preview((uint32_t *)pixels, surface_width, surface_height, image->data, + image->width, image->height, image->pixel_format, + camera->rotate, camera->mirrored, + camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, + camera->blacklevel, skip); - mp_main_set_preview(surface); + mp_main_set_preview(surface); } static void process_image_for_capture(const MPImage *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, image->width >> 4); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image->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->rotate == 0) { - orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : ORIENTATION_TOPLEFT; - } else if (camera->rotate == 90) { - orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : ORIENTATION_LEFTBOT; - } else if (camera->rotate == 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, (int)image->width >> 4); - for (int row = 0; row < image->height>>4; row++) { - TIFFWriteScanline(tif, buf, row, 0); - } - free(buf); - } - TIFFWriteDirectory(tif); + // Define TIFF thumbnail + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 1); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image->width >> 4); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image->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->rotate == 0) { + orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : + ORIENTATION_TOPLEFT; + } else if (camera->rotate == 90) { + orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : + ORIENTATION_LEFTBOT; + } else if (camera->rotate == 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, (int)image->width >> 4); + for (int row = 0; row < (image->height >> 4); row++) { + TIFFWriteScanline(tif, buf, row, 0); + } + free(buf); + } + TIFFWriteDirectory(tif); - // Define main photo - TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image->width); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image->height); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); - 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); - TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR - if(camera->whitelevel) { - TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &camera->whitelevel); - } - if(camera->blacklevel) { - TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &camera->blacklevel); - } - TIFFCheckpointDirectory(tif); - printf("Writing frame to %s\n", fname); + // Define main photo + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, image->width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, image->height); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + 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); + TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR + if (camera->whitelevel) { + TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &camera->whitelevel); + } + if (camera->blacklevel) { + TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &camera->blacklevel); + } + TIFFCheckpointDirectory(tif); + printf("Writing frame to %s\n", fname); - unsigned char *pLine = (unsigned char*)malloc(image->width); - for(int row = 0; row < image->height; row++){ - TIFFWriteScanline(tif, image->data + (row * image->width), row, 0); - } - free(pLine); - TIFFWriteDirectory(tif); + unsigned char *pLine = (unsigned char *)malloc(image->width); + for (int row = 0; row < image->height; row++) { + TIFFWriteScanline(tif, image->data + (row * image->width), row, 0); + } + free(pLine); + 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)image->height / (float)exposure)); - uint16_t isospeed[1]; - isospeed[0] = (uint16_t)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)image->height / (float)exposure)); + uint16_t isospeed[1]; + isospeed[0] = (uint16_t)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 process_capture_burst() { - 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); - sprintf(capture_fname, "%s/Pictures/IMG%s", getenv("HOME"), timestamp); + sprintf(capture_fname, "%s/Pictures/IMG%s", getenv("HOME"), timestamp); - // Start post-processing the captured burst - g_print("Post process %s to %s.ext\n", burst_dir, capture_fname); - char command[1024]; - sprintf(command, "%s %s %s &", processing_script, burst_dir, capture_fname); - system(command); + // Start post-processing the captured burst + g_print("Post process %s to %s.ext\n", burst_dir, capture_fname); + char command[1024]; + sprintf(command, "%s %s %s &", processing_script, burst_dir, capture_fname); + system(command); } static void process_image(MPPipeline *pipeline, const MPImage *image) { - assert(image->width == mode.width && image->height == mode.height); + assert(image->width == mode.width && image->height == mode.height); - process_image_for_preview(image); + 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) { - process_capture_burst(); + if (captures_remaining == 0) { + process_capture_burst(); - mp_main_capture_completed(capture_fname); - } - } + mp_main_capture_completed(capture_fname); + } + } - free(image->data); + free(image->data); - ++frames_processed; - if (captures_remaining == 0) { - is_capturing = false; - } + ++frames_processed; + if (captures_remaining == 0) { + is_capturing = false; + } } -void mp_process_pipeline_process_image(MPImage image) +void +mp_process_pipeline_process_image(MPImage image) { - // If we haven't processed the previous frame yet, drop this one - if (frames_received != frames_processed && !is_capturing) { - printf("Dropped frame at capture\n"); - return; - } + // If we haven't processed the previous frame yet, drop this one + if (frames_received != frames_processed && !is_capturing) { + printf("Dropped frame at capture\n"); + return; + } - ++frames_received; + ++frames_received; - mp_pipeline_invoke(pipeline, (MPPipelineCallback)process_image, &image, sizeof(MPImage)); + mp_pipeline_invoke(pipeline, (MPPipelineCallback)process_image, &image, + sizeof(MPImage)); } -static void capture() +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() +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 update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state) { - camera = state->camera; - mode = state->mode; + camera = state->camera; + mode = state->mode; - burst_length = state->burst_length; + burst_length = state->burst_length; - preview_width = state->preview_width; - preview_height = state->preview_height; + preview_width = state->preview_width; + preview_height = state->preview_height; - // 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; - struct mp_main_state main_state = { - .camera = camera, - .mode = mode, - .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, + .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) +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)); } diff --git a/process_pipeline.h b/process_pipeline.h index 8886f17..40cadd7 100644 --- a/process_pipeline.h +++ b/process_pipeline.h @@ -3,23 +3,23 @@ #include "camera_config.h" 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; - 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_process_pipeline_start(); diff --git a/quickpreview.c b/quickpreview.c index 7f56fee..156b9df 100644 --- a/quickpreview.c +++ b/quickpreview.c @@ -7,12 +7,14 @@ #include #include -static inline uint32_t pack_rgb(uint8_t r, uint8_t g, uint8_t b) +static inline uint32_t +pack_rgb(uint8_t r, uint8_t g, uint8_t b) { return (r << 16) | (g << 8) | b; } -static inline uint32_t convert_yuv_to_srgb(uint8_t y, uint8_t u, uint8_t v) +static inline uint32_t +convert_yuv_to_srgb(uint8_t y, uint8_t u, uint8_t v) { uint32_t r = 1.164f * y + 1.596f * (v - 128); uint32_t g = 1.164f * y - 0.813f * (v - 128) - 0.391f * (u - 128); @@ -20,15 +22,22 @@ static inline uint32_t convert_yuv_to_srgb(uint8_t y, uint8_t u, uint8_t v) return pack_rgb(r, g, b); } -static inline uint32_t apply_colormatrix(uint32_t color, const float *colormatrix) +static inline uint32_t +apply_colormatrix(uint32_t color, const float *colormatrix) { if (!colormatrix) { return color; } - uint32_t r = (color >> 16) * colormatrix[0] + ((color >> 8) & 0xFF) * colormatrix[1] + (color & 0xFF) * colormatrix[2]; - uint32_t g = (color >> 16) * colormatrix[3] + ((color >> 8) & 0xFF) * colormatrix[4] + (color & 0xFF) * colormatrix[5]; - uint32_t b = (color >> 16) * colormatrix[6] + ((color >> 8) & 0xFF) * colormatrix[7] + (color & 0xFF) * colormatrix[8]; + uint32_t r = (color >> 16) * colormatrix[0] + + ((color >> 8) & 0xFF) * colormatrix[1] + + (color & 0xFF) * colormatrix[2]; + uint32_t g = (color >> 16) * colormatrix[3] + + ((color >> 8) & 0xFF) * colormatrix[4] + + (color & 0xFF) * colormatrix[5]; + uint32_t b = (color >> 16) * colormatrix[6] + + ((color >> 8) & 0xFF) * colormatrix[7] + + (color & 0xFF) * colormatrix[8]; // Clip colors if (r > 0xFF) @@ -40,7 +49,9 @@ static inline uint32_t apply_colormatrix(uint32_t color, const float *colormatri return pack_rgb(r, g, b); } -static inline uint32_t coord_map(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int rotation, bool mirrored) +static inline uint32_t +coord_map(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int rotation, + bool mirrored) { uint32_t x_r, y_r; if (rotation == 0) { @@ -68,19 +79,13 @@ static inline uint32_t coord_map(uint32_t x, uint32_t y, uint32_t width, uint32_ return index; } -static void quick_preview_rggb8( - uint32_t *dst, - const uint32_t dst_width, - const uint32_t dst_height, - const uint8_t *src, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const uint32_t rotation, - const bool mirrored, - const float *colormatrix, - const uint8_t blacklevel, - const uint32_t skip) +static void +quick_preview_rggb8(uint32_t *dst, const uint32_t dst_width, + const uint32_t dst_height, const uint8_t *src, + const uint32_t src_width, const uint32_t src_height, + const MPPixelFormat format, const uint32_t rotation, + const bool mirrored, const float *colormatrix, + const uint8_t blacklevel, const uint32_t skip) { uint32_t src_y = 0, dst_y = 0; while (src_y < src_height) { @@ -94,25 +99,26 @@ static void quick_preview_rggb8( uint32_t color; switch (format) { - case MP_PIXEL_FMT_BGGR8: - color = pack_rgb(b2, b1, b0); - break; - case MP_PIXEL_FMT_GBRG8: - color = pack_rgb(b2, b0, b1); - break; - case MP_PIXEL_FMT_GRBG8: - color = pack_rgb(b1, b0, b2); - break; - case MP_PIXEL_FMT_RGGB8: - color = pack_rgb(b0, b1, b2); - break; - default: - assert(false); + case MP_PIXEL_FMT_BGGR8: + color = pack_rgb(b2, b1, b0); + break; + case MP_PIXEL_FMT_GBRG8: + color = pack_rgb(b2, b0, b1); + break; + case MP_PIXEL_FMT_GRBG8: + color = pack_rgb(b1, b0, b2); + break; + case MP_PIXEL_FMT_RGGB8: + color = pack_rgb(b0, b1, b2); + break; + default: + assert(false); } color = apply_colormatrix(color, colormatrix); - dst[coord_map(dst_x, dst_y, dst_width, dst_height, rotation, mirrored)] = color; + dst[coord_map(dst_x, dst_y, dst_width, dst_height, rotation, + mirrored)] = color; src_x += 2 + 2 * skip; ++dst_x; @@ -123,19 +129,13 @@ static void quick_preview_rggb8( } } -static void quick_preview_rggb10( - uint32_t *dst, - const uint32_t dst_width, - const uint32_t dst_height, - const uint8_t *src, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const uint32_t rotation, - const bool mirrored, - const float *colormatrix, - const uint8_t blacklevel, - const uint32_t skip) +static void +quick_preview_rggb10(uint32_t *dst, const uint32_t dst_width, + const uint32_t dst_height, const uint8_t *src, + const uint32_t src_width, const uint32_t src_height, + const MPPixelFormat format, const uint32_t rotation, + const bool mirrored, const float *colormatrix, + const uint8_t blacklevel, const uint32_t skip) { assert(src_width % 2 == 0); @@ -153,25 +153,26 @@ static void quick_preview_rggb10( uint32_t color; switch (format) { - case MP_PIXEL_FMT_BGGR10P: - color = pack_rgb(b2, b1, b0); - break; - case MP_PIXEL_FMT_GBRG10P: - color = pack_rgb(b2, b0, b1); - break; - case MP_PIXEL_FMT_GRBG10P: - color = pack_rgb(b1, b0, b2); - break; - case MP_PIXEL_FMT_RGGB10P: - color = pack_rgb(b0, b1, b2); - break; - default: - assert(false); + case MP_PIXEL_FMT_BGGR10P: + color = pack_rgb(b2, b1, b0); + break; + case MP_PIXEL_FMT_GBRG10P: + color = pack_rgb(b2, b0, b1); + break; + case MP_PIXEL_FMT_GRBG10P: + color = pack_rgb(b1, b0, b2); + break; + case MP_PIXEL_FMT_RGGB10P: + color = pack_rgb(b0, b1, b2); + break; + default: + assert(false); } color = apply_colormatrix(color, colormatrix); - dst[coord_map(dst_x, dst_y, dst_width, dst_height, rotation, mirrored)] = color; + dst[coord_map(dst_x, dst_y, dst_width, dst_height, rotation, + mirrored)] = color; uint32_t advance = 1 + skip; if (src_x % 5 == 0) { @@ -187,18 +188,12 @@ static void quick_preview_rggb10( } } -static void quick_preview_yuv( - uint32_t *dst, - const uint32_t dst_width, - const uint32_t dst_height, - const uint8_t *src, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const uint32_t rotation, - const bool mirrored, - const float *colormatrix, - const uint32_t skip) +static void +quick_preview_yuv(uint32_t *dst, const uint32_t dst_width, const uint32_t dst_height, + const uint8_t *src, const uint32_t src_width, + const uint32_t src_height, const MPPixelFormat format, + const uint32_t rotation, const bool mirrored, + const float *colormatrix, const uint32_t skip) { assert(src_width % 2 == 0); @@ -222,28 +217,31 @@ static void quick_preview_yuv( uint32_t color1, color2; switch (format) { - case MP_PIXEL_FMT_UYVY: - color1 = convert_yuv_to_srgb(b1, b0, b2); - color2 = convert_yuv_to_srgb(b3, b0, b2); - break; - case MP_PIXEL_FMT_YUYV: - color1 = convert_yuv_to_srgb(b0, b1, b3); - color2 = convert_yuv_to_srgb(b2, b1, b3); - break; - default: - assert(false); + case MP_PIXEL_FMT_UYVY: + color1 = convert_yuv_to_srgb(b1, b0, b2); + color2 = convert_yuv_to_srgb(b3, b0, b2); + break; + case MP_PIXEL_FMT_YUYV: + color1 = convert_yuv_to_srgb(b0, b1, b3); + color2 = convert_yuv_to_srgb(b2, b1, b3); + break; + default: + assert(false); } color1 = apply_colormatrix(color1, colormatrix); color2 = apply_colormatrix(color2, colormatrix); - uint32_t dst_i1 = coord_map(dst_x, dst_y, dst_width, dst_height, rotation, mirrored); + uint32_t dst_i1 = coord_map(dst_x, dst_y, dst_width, + dst_height, rotation, mirrored); dst[dst_i1] = color1; ++dst_x; // The last pixel needs to be skipped if we have an odd un-rotated width if (dst_x < unrot_dst_width) { - uint32_t dst_i2 = coord_map(dst_x, dst_y, dst_width, dst_height, rotation, mirrored); + uint32_t dst_i2 = + coord_map(dst_x, dst_y, dst_width, + dst_height, rotation, mirrored); dst[dst_i2] = color2; ++dst_x; } @@ -256,92 +254,52 @@ static void quick_preview_yuv( } } -void quick_preview( - uint32_t *dst, - const uint32_t dst_width, - const uint32_t dst_height, - const uint8_t *src, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const uint32_t rotation, - const bool mirrored, - const float *colormatrix, - const uint8_t blacklevel, - const uint32_t skip) +void +quick_preview(uint32_t *dst, const uint32_t dst_width, const uint32_t dst_height, + const uint8_t *src, const uint32_t src_width, + const uint32_t src_height, const MPPixelFormat format, + const uint32_t rotation, const bool mirrored, const float *colormatrix, + const uint8_t blacklevel, const uint32_t skip) { switch (format) { - case MP_PIXEL_FMT_BGGR8: - case MP_PIXEL_FMT_GBRG8: - case MP_PIXEL_FMT_GRBG8: - case MP_PIXEL_FMT_RGGB8: - quick_preview_rggb8( - dst, - dst_width, - dst_height, - src, - src_width, - src_height, - format, - rotation, - mirrored, - colormatrix, - blacklevel, - skip); - break; - case MP_PIXEL_FMT_BGGR10P: - case MP_PIXEL_FMT_GBRG10P: - case MP_PIXEL_FMT_GRBG10P: - case MP_PIXEL_FMT_RGGB10P: - quick_preview_rggb10( - dst, - dst_width, - dst_height, - src, - src_width, - src_height, - format, - rotation, - mirrored, - colormatrix, - blacklevel, - skip); - break; - case MP_PIXEL_FMT_UYVY: - case MP_PIXEL_FMT_YUYV: - quick_preview_yuv( - dst, - dst_width, - dst_height, - src, - src_width, - src_height, - format, - rotation, - mirrored, - colormatrix, - skip); - break; - default: - assert(false); + case MP_PIXEL_FMT_BGGR8: + case MP_PIXEL_FMT_GBRG8: + case MP_PIXEL_FMT_GRBG8: + case MP_PIXEL_FMT_RGGB8: + quick_preview_rggb8(dst, dst_width, dst_height, src, src_width, + src_height, format, rotation, mirrored, + colormatrix, blacklevel, skip); + break; + case MP_PIXEL_FMT_BGGR10P: + case MP_PIXEL_FMT_GBRG10P: + case MP_PIXEL_FMT_GRBG10P: + case MP_PIXEL_FMT_RGGB10P: + quick_preview_rggb10(dst, dst_width, dst_height, src, src_width, + src_height, format, rotation, mirrored, + colormatrix, blacklevel, skip); + break; + case MP_PIXEL_FMT_UYVY: + case MP_PIXEL_FMT_YUYV: + quick_preview_yuv(dst, dst_width, dst_height, src, src_width, + src_height, format, rotation, mirrored, + colormatrix, skip); + break; + default: + assert(false); } } -static uint32_t div_ceil(uint32_t x, uint32_t y) +static uint32_t +div_ceil(uint32_t x, uint32_t y) { - return x/y + !!(x % y); + return x / y + !!(x % y); } -void quick_preview_size( - uint32_t *dst_width, - uint32_t *dst_height, - uint32_t *skip, - const uint32_t preview_width, - const uint32_t preview_height, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const int rotation) +void +quick_preview_size(uint32_t *dst_width, uint32_t *dst_height, uint32_t *skip, + const uint32_t preview_width, const uint32_t preview_height, + const uint32_t src_width, const uint32_t src_height, + const MPPixelFormat format, const int rotation) { uint32_t colors_x = mp_pixel_format_width_to_colors(format, src_width); uint32_t colors_y = mp_pixel_format_height_to_colors(format, src_height); diff --git a/quickpreview.h b/quickpreview.h index bae38bc..1815215 100644 --- a/quickpreview.h +++ b/quickpreview.h @@ -1,27 +1,14 @@ #include "camera.h" #include -void quick_preview( - uint32_t *dst, - const uint32_t dst_width, - const uint32_t dst_height, - const uint8_t *src, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const uint32_t rotation, - const bool mirrored, - const float *colormatrix, - const uint8_t blacklevel, - const uint32_t skip); +void quick_preview(uint32_t *dst, const uint32_t dst_width, + const uint32_t dst_height, const uint8_t *src, + const uint32_t src_width, const uint32_t src_height, + const MPPixelFormat format, const uint32_t rotation, + const bool mirrored, const float *colormatrix, + const uint8_t blacklevel, const uint32_t skip); -void quick_preview_size( - uint32_t *dst_width, - uint32_t *dst_height, - uint32_t *skip, - const uint32_t preview_width, - const uint32_t preview_height, - const uint32_t src_width, - const uint32_t src_height, - const MPPixelFormat format, - const int rotation); +void quick_preview_size(uint32_t *dst_width, uint32_t *dst_height, uint32_t *skip, + const uint32_t preview_width, const uint32_t preview_height, + const uint32_t src_width, const uint32_t src_height, + const MPPixelFormat format, const int rotation);