Code style

This commit is contained in:
Martijn Braam 2020-12-06 15:44:31 +01:00
parent 101abe33cd
commit 72105c9491
20 changed files with 3200 additions and 2525 deletions

548
.clang-format Normal file
View File

@ -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
...

308
camera.c
View File

@ -10,26 +10,19 @@
#define MAX_VIDEO_BUFFERS 20 #define MAX_VIDEO_BUFFERS 20
static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = { static const char *pixel_format_names[MP_PIXEL_FMT_MAX] = {
"unsupported", "unsupported", "BGGR8", "GBRG8", "GRBG8", "RGGB8", "BGGR10P",
"BGGR8", "GBRG10P", "GRBG10P", "RGGB10P", "UYVY", "YUYV",
"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"); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, "INVALID");
return pixel_format_names[pixel_format]; 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) { for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
if (strcasecmp(pixel_format_names[i], name) == 0) { if (strcasecmp(pixel_format_names[i], name) == 0) {
@ -53,13 +46,15 @@ static const uint32_t pixel_format_v4l_pixel_formats[MP_PIXEL_FMT_MAX] = {
V4L2_PIX_FMT_YUYV, 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); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
return pixel_format_v4l_pixel_formats[pixel_format]; 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) { for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) { if (pixel_format_v4l_pixel_formats[i] == v4l_pixel_format) {
@ -83,13 +78,15 @@ static const uint32_t pixel_format_v4l_bus_codes[MP_PIXEL_FMT_MAX] = {
MEDIA_BUS_FMT_YUYV8_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); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
return pixel_format_v4l_bus_codes[pixel_format]; 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) { for (MPPixelFormat i = 0; i < MP_PIXEL_FMT_MAX; ++i) {
if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) { if (pixel_format_v4l_bus_codes[i] == v4l_bus_code) {
@ -99,28 +96,34 @@ MPPixelFormat mp_pixel_format_from_v4l_bus_code(uint32_t v4l_bus_code)
return MP_PIXEL_FMT_UNSUPPORTED; 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); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
switch (pixel_format) { switch (pixel_format) {
case MP_PIXEL_FMT_BGGR8: case MP_PIXEL_FMT_BGGR8:
case MP_PIXEL_FMT_GBRG8: case MP_PIXEL_FMT_GBRG8:
case MP_PIXEL_FMT_GRBG8: case MP_PIXEL_FMT_GRBG8:
case MP_PIXEL_FMT_RGGB8: return 8; case MP_PIXEL_FMT_RGGB8:
return 8;
case MP_PIXEL_FMT_BGGR10P: case MP_PIXEL_FMT_BGGR10P:
case MP_PIXEL_FMT_GBRG10P: case MP_PIXEL_FMT_GBRG10P:
case MP_PIXEL_FMT_GRBG10P: case MP_PIXEL_FMT_GRBG10P:
case MP_PIXEL_FMT_RGGB10P: return 10; case MP_PIXEL_FMT_RGGB10P:
return 10;
case MP_PIXEL_FMT_UYVY: case MP_PIXEL_FMT_UYVY:
case MP_PIXEL_FMT_YUYV: return 16; case MP_PIXEL_FMT_YUYV:
default: return 0; 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); 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 bits_per_width = width * (uint64_t)bits_per_pixel;
uint64_t remainder = bits_per_width % 8; uint64_t remainder = bits_per_width % 8;
if (remainder == 0) if (remainder == 0)
@ -129,25 +132,31 @@ uint32_t mp_pixel_format_width_to_bytes(MPPixelFormat pixel_format, uint32_t wid
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); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
switch (pixel_format) { switch (pixel_format) {
case MP_PIXEL_FMT_BGGR8: case MP_PIXEL_FMT_BGGR8:
case MP_PIXEL_FMT_GBRG8: case MP_PIXEL_FMT_GBRG8:
case MP_PIXEL_FMT_GRBG8: case MP_PIXEL_FMT_GRBG8:
case MP_PIXEL_FMT_RGGB8: return width / 2; case MP_PIXEL_FMT_RGGB8:
return width / 2;
case MP_PIXEL_FMT_BGGR10P: case MP_PIXEL_FMT_BGGR10P:
case MP_PIXEL_FMT_GBRG10P: case MP_PIXEL_FMT_GBRG10P:
case MP_PIXEL_FMT_GRBG10P: case MP_PIXEL_FMT_GRBG10P:
case MP_PIXEL_FMT_RGGB10P: return width / 2 * 5; case MP_PIXEL_FMT_RGGB10P:
return width / 2 * 5;
case MP_PIXEL_FMT_UYVY: case MP_PIXEL_FMT_UYVY:
case MP_PIXEL_FMT_YUYV: return width; case MP_PIXEL_FMT_YUYV:
default: return 0; 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); g_return_val_if_fail(pixel_format < MP_PIXEL_FMT_MAX, 0);
switch (pixel_format) { switch (pixel_format) {
@ -158,28 +167,33 @@ uint32_t mp_pixel_format_height_to_colors(MPPixelFormat pixel_format, uint32_t h
case MP_PIXEL_FMT_BGGR10P: case MP_PIXEL_FMT_BGGR10P:
case MP_PIXEL_FMT_GBRG10P: case MP_PIXEL_FMT_GBRG10P:
case MP_PIXEL_FMT_GRBG10P: case MP_PIXEL_FMT_GRBG10P:
case MP_PIXEL_FMT_RGGB10P: return height / 2; case MP_PIXEL_FMT_RGGB10P:
return height / 2;
case MP_PIXEL_FMT_UYVY: case MP_PIXEL_FMT_UYVY:
case MP_PIXEL_FMT_YUYV: return height; case MP_PIXEL_FMT_YUYV:
default: return 0; 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 return m1->pixel_format == m2->pixel_format &&
&& m1->frame_interval.numerator == m2->frame_interval.numerator m1->frame_interval.numerator == m2->frame_interval.numerator &&
&& m1->frame_interval.denominator == m2->frame_interval.denominator m1->frame_interval.denominator == m2->frame_interval.denominator &&
&& m1->width == m2->width m1->width == m2->width && m1->height == m2->height;
&& 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; int r;
do { do {
@ -206,7 +220,8 @@ struct _MPCamera {
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);
@ -236,7 +251,8 @@ MPCamera *mp_camera_new(int video_fd, int subdev_fd)
return camera; return camera;
} }
void mp_camera_free(MPCamera *camera) void
mp_camera_free(MPCamera *camera)
{ {
g_warn_if_fail(camera->num_buffers == 0); g_warn_if_fail(camera->num_buffers == 0);
if (camera->num_buffers != 0) { if (camera->num_buffers != 0) {
@ -246,22 +262,26 @@ void mp_camera_free(MPCamera *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); uint32_t pixfmt = mp_pixel_format_from_v4l_pixel_format(mode->pixel_format);
struct v4l2_format fmt = {}; struct v4l2_format fmt = {};
@ -298,7 +318,8 @@ static bool camera_mode_impl(MPCamera *camera, int request, MPCameraMode *mode)
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)) { if (!camera_mode_impl(camera, VIDIOC_TRY_FMT, mode)) {
errno_printerr("VIDIOC_S_FMT"); errno_printerr("VIDIOC_S_FMT");
@ -307,34 +328,38 @@ bool mp_camera_try_mode(MPCamera *camera, MPCameraMode *mode)
return true; 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 // Set the mode in the subdev the camera is one
if (mp_camera_is_subdev(camera)) if (mp_camera_is_subdev(camera)) {
{
struct v4l2_subdev_frame_interval interval = {}; struct v4l2_subdev_frame_interval interval = {};
interval.pad = 0; interval.pad = 0;
interval.interval = mode->frame_interval; interval.interval = mode->frame_interval;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) { if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL,
&interval) == -1) {
errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
return false; return false;
} }
bool did_set_frame_rate = bool did_set_frame_rate = interval.interval.numerator ==
interval.interval.numerator == mode->frame_interval.numerator mode->frame_interval.numerator &&
&& interval.interval.denominator == mode->frame_interval.denominator; interval.interval.denominator ==
mode->frame_interval.denominator;
struct v4l2_subdev_format fmt = {}; struct v4l2_subdev_format fmt = {};
fmt.pad = 0; fmt.pad = 0;
fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
fmt.format.width = mode->width; fmt.format.width = mode->width;
fmt.format.height = mode->height; fmt.format.height = mode->height;
fmt.format.code = mp_pixel_format_to_v4l_bus_code(mode->pixel_format); fmt.format.code =
mp_pixel_format_to_v4l_bus_code(mode->pixel_format);
fmt.format.field = V4L2_FIELD_ANY; fmt.format.field = V4L2_FIELD_ANY;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) { if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FMT, &fmt) == -1) {
errno_printerr("VIDIOC_SUBDEV_S_FMT"); errno_printerr("VIDIOC_SUBDEV_S_FMT");
@ -345,16 +370,17 @@ bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode)
// too high a frame-rate, but that means the frame-rate won't be set // 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 // 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. // succeed before. Ideally we'd be able to set both at once.
if (!did_set_frame_rate) if (!did_set_frame_rate) {
{
interval.interval = mode->frame_interval; interval.interval = mode->frame_interval;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &interval) == -1) { if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL,
&interval) == -1) {
errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL"); errno_printerr("VIDIOC_SUBDEV_S_FRAME_INTERVAL");
} }
} }
// Update the mode // Update the mode
mode->pixel_format = mp_pixel_format_from_v4l_bus_code(fmt.format.code); mode->pixel_format =
mp_pixel_format_from_v4l_bus_code(fmt.format.code);
mode->frame_interval = interval.interval; mode->frame_interval = interval.interval;
mode->width = fmt.format.width; mode->width = fmt.format.width;
mode->height = fmt.format.height; mode->height = fmt.format.height;
@ -374,7 +400,8 @@ bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *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->has_set_mode, false);
g_return_val_if_fail(camera->num_buffers == 0, false); g_return_val_if_fail(camera->num_buffers == 0, false);
@ -396,7 +423,8 @@ bool mp_camera_start_capture(MPCamera *camera)
} }
if (req.count < 2) { if (req.count < 2) {
g_printerr("Insufficient buffer memory. Only %d buffers available.\n", g_printerr(
"Insufficient buffer memory. Only %d buffers available.\n",
req.count); req.count);
goto error; goto error;
} }
@ -422,22 +450,14 @@ bool mp_camera_start_capture(MPCamera *camera)
if (camera->use_mplane) { if (camera->use_mplane) {
camera->buffers[i].length = planes[0].length; camera->buffers[i].length = planes[0].length;
camera->buffers[i].data = mmap( camera->buffers[i].data =
NULL, mmap(NULL, planes[0].length, PROT_READ, MAP_SHARED,
planes[0].length, camera->video_fd, planes[0].m.mem_offset);
PROT_READ,
MAP_SHARED,
camera->video_fd,
planes[0].m.mem_offset);
} else { } else {
camera->buffers[i].length = buf.length; camera->buffers[i].length = buf.length;
camera->buffers[i].data = mmap( camera->buffers[i].data =
NULL, mmap(NULL, buf.length, PROT_READ, MAP_SHARED,
buf.length, camera->video_fd, buf.m.offset);
PROT_READ,
MAP_SHARED,
camera->video_fd,
buf.m.offset);
} }
if (camera->buffers[i].data == MAP_FAILED) { if (camera->buffers[i].data == MAP_FAILED) {
@ -486,7 +506,8 @@ error:
// Unmap any mapped buffers // Unmap any mapped buffers
assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
for (uint32_t i = 0; i < camera->num_buffers; ++i) { for (uint32_t i = 0; i < camera->num_buffers; ++i) {
if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) { if (munmap(camera->buffers[i].data, camera->buffers[i].length) ==
-1) {
errno_printerr("munmap"); errno_printerr("munmap");
} }
} }
@ -506,7 +527,8 @@ error:
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);
@ -517,7 +539,8 @@ bool mp_camera_stop_capture(MPCamera *camera)
assert(camera->num_buffers <= MAX_VIDEO_BUFFERS); assert(camera->num_buffers <= MAX_VIDEO_BUFFERS);
for (int i = 0; i < camera->num_buffers; ++i) { for (int i = 0; i < camera->num_buffers; ++i) {
if (munmap(camera->buffers[i].data, camera->buffers[i].length) == -1) { if (munmap(camera->buffers[i].data, camera->buffers[i].length) ==
-1) {
errno_printerr("munmap"); errno_printerr("munmap");
} }
} }
@ -535,12 +558,15 @@ bool mp_camera_stop_capture(MPCamera *camera)
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 = {}; struct v4l2_buffer buf = {};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@ -576,7 +602,8 @@ bool mp_camera_capture_image(MPCamera *camera, void (*callback)(MPImage, void *)
bytesused = buf.bytesused; bytesused = buf.bytesused;
} }
assert(bytesused == mp_pixel_format_width_to_bytes(pixel_format, width) * height); assert(bytesused ==
mp_pixel_format_width_to_bytes(pixel_format, width) * height);
assert(bytesused == camera->buffers[buf.index].length); assert(bytesused == camera->buffers[buf.index].length);
MPImage image = { MPImage image = {
@ -615,7 +642,8 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
fmt.index = fmt_index; fmt.index = fmt_index;
fmt.pad = 0; fmt.pad = 0;
fmt.which = V4L2_SUBDEV_FORMAT_TRY; fmt.which = V4L2_SUBDEV_FORMAT_TRY;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) == -1) { if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &fmt) ==
-1) {
if (errno != EINVAL) { if (errno != EINVAL) {
errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE"); errno_printerr("VIDIOC_SUBDEV_ENUM_MBUS_CODE");
} }
@ -634,16 +662,18 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
frame.pad = 0; frame.pad = 0;
frame.code = fmt.code; frame.code = fmt.code;
frame.which = V4L2_SUBDEV_FORMAT_TRY; frame.which = V4L2_SUBDEV_FORMAT_TRY;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frame) == -1) { if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE,
&frame) == -1) {
if (errno != EINVAL) { if (errno != EINVAL) {
errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_SIZE"); errno_printerr(
"VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
} }
break; break;
} }
// TODO: Handle other types // TODO: Handle other types
if (frame.min_width != frame.max_width if (frame.min_width != frame.max_width ||
|| frame.min_height != frame.max_height) { frame.min_height != frame.max_height) {
break; break;
} }
@ -655,9 +685,12 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
interval.width = frame.max_width; interval.width = frame.max_width;
interval.height = frame.max_height; interval.height = frame.max_height;
interval.which = V4L2_SUBDEV_FORMAT_TRY; interval.which = V4L2_SUBDEV_FORMAT_TRY;
if (xioctl(camera->subdev_fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &interval) == -1) { if (xioctl(camera->subdev_fd,
VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL,
&interval) == -1) {
if (errno != EINVAL) { if (errno != EINVAL) {
errno_printerr("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL"); errno_printerr(
"VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
} }
break; break;
} }
@ -673,7 +706,8 @@ get_subdev_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
continue; continue;
} }
MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList)); MPCameraModeList *new_item =
malloc(sizeof(MPCameraModeList));
new_item->mode = mode; new_item->mode = mode;
new_item->next = item; new_item->next = item;
item = new_item; item = new_item;
@ -701,7 +735,8 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
} }
// Skip unsupported formats // Skip unsupported formats
uint32_t format = mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat); uint32_t format =
mp_pixel_format_from_v4l_pixel_format(fmt.pixelformat);
if (format == MP_PIXEL_FMT_UNSUPPORTED) { if (format == MP_PIXEL_FMT_UNSUPPORTED) {
continue; continue;
} }
@ -710,7 +745,8 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
struct v4l2_frmsizeenum frame = {}; struct v4l2_frmsizeenum frame = {};
frame.index = frame_index; frame.index = frame_index;
frame.pixel_format = fmt.pixelformat; frame.pixel_format = fmt.pixelformat;
if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMESIZES, &frame) == -1) { if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMESIZES,
&frame) == -1) {
if (errno != EINVAL) { if (errno != EINVAL) {
errno_printerr("VIDIOC_ENUM_FRAMESIZES"); errno_printerr("VIDIOC_ENUM_FRAMESIZES");
} }
@ -728,9 +764,12 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
interval.pixel_format = fmt.pixelformat; interval.pixel_format = fmt.pixelformat;
interval.width = frame.discrete.width; interval.width = frame.discrete.width;
interval.height = frame.discrete.height; interval.height = frame.discrete.height;
if (xioctl(camera->video_fd, VIDIOC_ENUM_FRAMEINTERVALS, &interval) == -1) { if (xioctl(camera->video_fd,
VIDIOC_ENUM_FRAMEINTERVALS,
&interval) == -1) {
if (errno != EINVAL) { if (errno != EINVAL) {
errno_printerr("VIDIOC_ENUM_FRAMESIZES"); errno_printerr(
"VIDIOC_ENUM_FRAMESIZES");
} }
break; break;
} }
@ -751,7 +790,8 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
continue; continue;
} }
MPCameraModeList *new_item = malloc(sizeof(MPCameraModeList)); MPCameraModeList *new_item =
malloc(sizeof(MPCameraModeList));
new_item->mode = mode; new_item->mode = mode;
new_item->next = item; new_item->next = item;
item = new_item; item = new_item;
@ -762,19 +802,22 @@ get_video_modes(MPCamera *camera, bool (*check)(MPCamera *, MPCameraMode *))
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; MPCameraMode attempt = *mode;
return mp_camera_try_mode(camera, &attempt) return mp_camera_try_mode(camera, &attempt) &&
&& mp_camera_mode_is_equivalent(mode, &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)) { if (mp_camera_is_subdev(camera)) {
return get_subdev_modes(camera, all_modes); return get_subdev_modes(camera, all_modes);
@ -783,7 +826,8 @@ MPCameraModeList *mp_camera_list_supported_modes(MPCamera *camera)
} }
} }
MPCameraModeList *mp_camera_list_available_modes(MPCamera *camera) MPCameraModeList *
mp_camera_list_available_modes(MPCamera *camera)
{ {
if (mp_camera_is_subdev(camera)) { if (mp_camera_is_subdev(camera)) {
return get_subdev_modes(camera, available_modes); return get_subdev_modes(camera, available_modes);
@ -792,19 +836,22 @@ MPCameraModeList *mp_camera_list_available_modes(MPCamera *camera)
} }
} }
MPCameraMode *mp_camera_mode_list_get(MPCameraModeList *list) MPCameraMode *
mp_camera_mode_list_get(MPCameraModeList *list)
{ {
g_return_val_if_fail(list, NULL); g_return_val_if_fail(list, NULL);
return &list->mode; 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); g_return_val_if_fail(list, NULL);
return list->next; return list->next;
} }
void mp_camera_mode_list_free(MPCameraModeList *list) void
mp_camera_mode_list_free(MPCameraModeList *list)
{ {
while (list) { while (list) {
MPCameraModeList *tmp = list; MPCameraModeList *tmp = list;
@ -923,7 +970,8 @@ struct int_str_pair control_id_names[] = {
{ V4L2_CID_FLASH_READY, "FLASH_READY" }, { 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);
@ -962,7 +1010,8 @@ struct int_str_pair control_type_names[] = {
// { V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS, "HEVC_SLICE_PARAMS" }, // { 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);
@ -980,7 +1029,8 @@ struct _MPControlList {
MPControlList *next; MPControlList *next;
}; };
static int control_fd(MPCamera *camera) static int
control_fd(MPCamera *camera)
{ {
if (camera->subdev_fd != -1) { if (camera->subdev_fd != -1) {
return camera->subdev_fd; return camera->subdev_fd;
@ -988,7 +1038,8 @@ static int control_fd(MPCamera *camera)
return camera->video_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;
@ -1018,7 +1069,8 @@ MPControlList *mp_camera_list_controls(MPCamera *camera)
}; };
strcpy(control.name, ctrl.name); strcpy(control.name, ctrl.name);
memcpy(control.dimensions, ctrl.dims, sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); memcpy(control.dimensions, ctrl.dims,
sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS);
MPControlList *new_item = malloc(sizeof(MPControlList)); MPControlList *new_item = malloc(sizeof(MPControlList));
new_item->control = control; new_item->control = control;
@ -1031,19 +1083,22 @@ MPControlList *mp_camera_list_controls(MPCamera *camera)
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); g_return_val_if_fail(list, NULL);
return &list->control; return &list->control;
} }
MPControlList *mp_control_list_next(MPControlList *list) MPControlList *
mp_control_list_next(MPControlList *list)
{ {
g_return_val_if_fail(list, NULL); g_return_val_if_fail(list, NULL);
return list->next; return list->next;
} }
void mp_control_list_free(MPControlList *list) void
mp_control_list_free(MPControlList *list)
{ {
while (list) { while (list) {
MPControlList *tmp = list; MPControlList *tmp = list;
@ -1052,7 +1107,8 @@ void mp_control_list_free(MPControlList *list)
} }
} }
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 = {}; struct v4l2_query_ext_ctrl ctrl = {};
ctrl.id = id; ctrl.id = id;
@ -1075,12 +1131,14 @@ bool mp_camera_query_control(MPCamera *camera, uint32_t id, MPControl *control)
control->element_size = ctrl.elem_size; control->element_size = ctrl.elem_size;
control->element_count = ctrl.elems; control->element_count = ctrl.elems;
control->dimensions_count = ctrl.nr_of_dims; control->dimensions_count = ctrl.nr_of_dims;
memcpy(control->dimensions, ctrl.dims, sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS); memcpy(control->dimensions, ctrl.dims,
sizeof(uint32_t) * V4L2_CTRL_MAX_DIMS);
} }
return true; 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 = {}; struct v4l2_ext_control ctrl = {};
ctrl.id = id; ctrl.id = id;
@ -1100,24 +1158,28 @@ static bool control_impl_int32(MPCamera *camera, uint32_t id, int request, int32
return true; 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; int32_t v = 0;
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v);
return 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; int32_t value = *v;
bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value); bool s = control_impl_int32(camera, id, VIDIOC_TRY_EXT_CTRLS, &value);
@ -1125,13 +1187,15 @@ bool mp_camera_control_try_boolean(MPCamera *camera, uint32_t id, bool *v)
return s; 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; int32_t value = v;
return control_impl_int32(camera, id, VIDIOC_S_EXT_CTRLS, &value); 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; int32_t v = false;
control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v); control_impl_int32(camera, id, VIDIOC_G_EXT_CTRLS, &v);

View File

@ -31,7 +31,8 @@ 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_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_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_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 { typedef struct {
MPPixelFormat pixel_format; MPPixelFormat pixel_format;
@ -66,7 +67,8 @@ bool mp_camera_set_mode(MPCamera *camera, MPCameraMode *mode);
bool mp_camera_start_capture(MPCamera *camera); bool mp_camera_start_capture(MPCamera *camera);
bool mp_camera_stop_capture(MPCamera *camera); bool mp_camera_stop_capture(MPCamera *camera);
bool mp_camera_is_capturing(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; typedef struct _MPCameraModeList MPCameraModeList;

View File

@ -42,27 +42,28 @@ find_config(char *conffile)
// Check config/%dt.ini in the current working directory // Check config/%dt.ini in the current working directory
sprintf(conffile, "config/%s.ini", buf); sprintf(conffile, "config/%s.ini", buf);
if(access(conffile, F_OK) != -1) { if (access(conffile, F_OK) != -1) {
printf("Found config file at %s\n", conffile); printf("Found config file at %s\n", conffile);
return true; return true;
} }
// Check for a config file in XDG_CONFIG_HOME // Check for a config file in XDG_CONFIG_HOME
sprintf(conffile, "%s/megapixels/config/%s.ini", xdg_config_home, buf); sprintf(conffile, "%s/megapixels/config/%s.ini", xdg_config_home,
if(access(conffile, F_OK) != -1) { buf);
if (access(conffile, F_OK) != -1) {
printf("Found config file at %s\n", conffile); printf("Found config file at %s\n", conffile);
return true; return true;
} }
// Check user overridden /etc/megapixels/config/$dt.ini // Check user overridden /etc/megapixels/config/$dt.ini
sprintf(conffile, "%s/megapixels/config/%s.ini", SYSCONFDIR, buf); sprintf(conffile, "%s/megapixels/config/%s.ini", SYSCONFDIR, buf);
if(access(conffile, F_OK) != -1) { if (access(conffile, F_OK) != -1) {
printf("Found config file at %s\n", conffile); printf("Found config file at %s\n", conffile);
return true; return true;
} }
// Check packaged /usr/share/megapixels/config/$dt.ini // Check packaged /usr/share/megapixels/config/$dt.ini
sprintf(conffile, "%s/megapixels/config/%s.ini", DATADIR, buf); sprintf(conffile, "%s/megapixels/config/%s.ini", DATADIR, buf);
if(access(conffile, F_OK) != -1) { if (access(conffile, F_OK) != -1) {
printf("Found config file at %s\n", conffile); printf("Found config file at %s\n", conffile);
return true; return true;
} }
@ -86,11 +87,12 @@ strtoint(const char *nptr, char **endptr, int base)
{ {
long x = strtol(nptr, endptr, base); long x = strtol(nptr, endptr, base);
assert(x <= INT_MAX); assert(x <= INT_MAX);
return (int) x; return (int)x;
} }
static bool 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); int prefix_length = strlen(prefix);
if (strncmp(prefix, name, prefix_length) != 0) if (strncmp(prefix, name, prefix_length) != 0)
@ -153,8 +155,10 @@ config_ini_handler(void *user, const char *section, const char *name,
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)) { if (config_handle_camera_mode("capture-", &cc->capture_mode, name,
} else if (config_handle_camera_mode("preview-", &cc->preview_mode, name, value)) { value)) {
} else if (config_handle_camera_mode("preview-", &cc->preview_mode,
name, value)) {
} else if (strcmp(name, "rotate") == 0) { } else if (strcmp(name, "rotate") == 0) {
cc->rotate = strtoint(value, NULL, 10); cc->rotate = strtoint(value, NULL, 10);
} else if (strcmp(name, "mirrored") == 0) { } else if (strcmp(name, "mirrored") == 0) {
@ -166,15 +170,18 @@ config_ini_handler(void *user, const char *section, const char *name,
} else if (strcmp(name, "media-links") == 0) { } else if (strcmp(name, "media-links") == 0) {
char **linkdefs = g_strsplit(value, ",", 0); char **linkdefs = g_strsplit(value, ",", 0);
for (int i = 0; i < MP_MAX_LINKS && linkdefs[i] != NULL; ++i) { for (int i = 0; i < MP_MAX_LINKS && linkdefs[i] != NULL;
++i) {
char **linkdef = g_strsplit(linkdefs[i], "->", 2); char **linkdef = g_strsplit(linkdefs[i], "->", 2);
char **porta = g_strsplit(linkdef[0], ":", 2); char **porta = g_strsplit(linkdef[0], ":", 2);
char **portb = g_strsplit(linkdef[1], ":", 2); char **portb = g_strsplit(linkdef[1], ":", 2);
strcpy(cc->media_links[i].source_name, porta[0]); strcpy(cc->media_links[i].source_name, porta[0]);
strcpy(cc->media_links[i].target_name, portb[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].source_port =
cc->media_links[i].target_port = strtoint(portb[1], NULL, 10); strtoint(porta[1], NULL, 10);
cc->media_links[i].target_port =
strtoint(portb[1], NULL, 10);
g_strfreev(portb); g_strfreev(portb);
g_strfreev(porta); g_strfreev(porta);
@ -184,28 +191,18 @@ config_ini_handler(void *user, const char *section, const char *name,
g_strfreev(linkdefs); g_strfreev(linkdefs);
} else if (strcmp(name, "colormatrix") == 0) { } else if (strcmp(name, "colormatrix") == 0) {
sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f", sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f",
cc->colormatrix+0, cc->colormatrix + 0, cc->colormatrix + 1,
cc->colormatrix+1, cc->colormatrix + 2, cc->colormatrix + 3,
cc->colormatrix+2, cc->colormatrix + 4, cc->colormatrix + 5,
cc->colormatrix+3, cc->colormatrix + 6, cc->colormatrix + 7,
cc->colormatrix+4, cc->colormatrix + 8);
cc->colormatrix+5,
cc->colormatrix+6,
cc->colormatrix+7,
cc->colormatrix+8
);
} else if (strcmp(name, "forwardmatrix") == 0) { } else if (strcmp(name, "forwardmatrix") == 0) {
sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f", sscanf(value, "%f,%f,%f,%f,%f,%f,%f,%f,%f",
cc->forwardmatrix+0, cc->forwardmatrix + 0, cc->forwardmatrix + 1,
cc->forwardmatrix+1, cc->forwardmatrix + 2, cc->forwardmatrix + 3,
cc->forwardmatrix+2, cc->forwardmatrix + 4, cc->forwardmatrix + 5,
cc->forwardmatrix+3, cc->forwardmatrix + 6, cc->forwardmatrix + 7,
cc->forwardmatrix+4, cc->forwardmatrix + 8);
cc->forwardmatrix+5,
cc->forwardmatrix+6,
cc->forwardmatrix+7,
cc->forwardmatrix+8
);
} else if (strcmp(name, "whitelevel") == 0) { } else if (strcmp(name, "whitelevel") == 0) {
cc->whitelevel = strtoint(value, NULL, 10); cc->whitelevel = strtoint(value, NULL, 10);
} else if (strcmp(name, "blacklevel") == 0) { } else if (strcmp(name, "blacklevel") == 0) {
@ -229,15 +226,21 @@ config_ini_handler(void *user, const char *section, const char *name,
} }
void void
calculate_matrices() { calculate_matrices()
{
for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) { for (size_t i = 0; i < MP_MAX_CAMERAS; ++i) {
if (cameras[i].colormatrix != NULL && cameras[i].forwardmatrix != NULL) { if (cameras[i].colormatrix != NULL &&
multiply_matrices(cameras[i].colormatrix, cameras[i].forwardmatrix, cameras[i].previewmatrix); cameras[i].forwardmatrix != NULL) {
multiply_matrices(cameras[i].colormatrix,
cameras[i].forwardmatrix,
cameras[i].previewmatrix);
} }
} }
} }
bool mp_load_config() { bool
mp_load_config()
{
char file[512]; char file[512];
if (!find_config(file)) { if (!find_config(file)) {
g_printerr("Could not find any config file\n"); g_printerr("Could not find any config file\n");
@ -263,17 +266,20 @@ bool mp_load_config() {
return true; return true;
} }
const char * mp_get_device_make() const char *
mp_get_device_make()
{ {
return exif_make; return exif_make;
} }
const char * mp_get_device_model() const char *
mp_get_device_model()
{ {
return exif_model; return exif_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)
{ {
if (index >= num_cameras) if (index >= num_cameras)
return NULL; return NULL;

View File

@ -47,4 +47,4 @@ bool mp_load_config();
const char *mp_get_device_make(); const char *mp_get_device_make();
const char *mp_get_device_model(); 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);

130
device.c
View File

@ -8,10 +8,12 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
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]; char uevent_path[256];
snprintf(uevent_path, 256, "/sys/dev/char/%d:%d/uevent", devnode.major, devnode.minor); snprintf(uevent_path, 256, "/sys/dev/char/%d:%d/uevent", devnode.major,
devnode.minor);
FILE *f = fopen(uevent_path, "r"); FILE *f = fopen(uevent_path, "r");
if (!f) { if (!f) {
@ -51,12 +53,14 @@ struct _MPDevice {
size_t num_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; int r;
do { do {
@ -65,19 +69,20 @@ static int xioctl(int fd, int request, void *arg)
return r; 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); int fd = open(path, O_RDWR);
if (fd == -1) { if (fd == -1) {
@ -88,12 +93,13 @@ MPDevice *mp_device_open(const char *path)
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 // Get the topology of the media device
struct media_v2_topology topology = {}; struct media_v2_topology topology = {};
if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1 if (xioctl(fd, MEDIA_IOC_G_TOPOLOGY, &topology) == -1 ||
|| topology.num_entities == 0) { topology.num_entities == 0) {
close(fd); close(fd);
return NULL; return NULL;
} }
@ -101,9 +107,11 @@ MPDevice *mp_device_new(int fd)
// Create the device // Create the device
MPDevice *device = calloc(1, sizeof(MPDevice)); MPDevice *device = calloc(1, sizeof(MPDevice));
device->fd = fd; device->fd = fd;
device->entities = calloc(topology.num_entities, sizeof(struct media_v2_entity)); device->entities =
calloc(topology.num_entities, sizeof(struct media_v2_entity));
device->num_entities = topology.num_entities; device->num_entities = topology.num_entities;
device->interfaces = calloc(topology.num_interfaces, sizeof(struct media_v2_interface)); device->interfaces =
calloc(topology.num_interfaces, sizeof(struct media_v2_interface));
device->num_interfaces = topology.num_interfaces; device->num_interfaces = topology.num_interfaces;
device->pads = calloc(topology.num_pads, sizeof(struct media_v2_pad)); device->pads = calloc(topology.num_pads, sizeof(struct media_v2_pad));
device->num_pads = topology.num_pads; device->num_pads = topology.num_pads;
@ -131,7 +139,8 @@ MPDevice *mp_device_new(int fd)
return device; return device;
} }
void mp_device_close(MPDevice *device) void
mp_device_close(MPDevice *device)
{ {
close(device->fd); close(device->fd);
free(device->entities); free(device->entities);
@ -141,9 +150,12 @@ void mp_device_close(MPDevice *device)
free(device); 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); const struct media_v2_pad *source_pad =
mp_device_get_pad(device, source_pad_id);
g_return_val_if_fail(source_pad, false); g_return_val_if_fail(source_pad, false);
const struct media_v2_pad *sink_pad = mp_device_get_pad(device, sink_pad_id); const struct media_v2_pad *sink_pad = mp_device_get_pad(device, sink_pad_id);
@ -163,7 +175,8 @@ bool mp_device_setup_link(MPDevice *device, uint32_t source_pad_id, uint32_t sin
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);
@ -176,7 +189,8 @@ const struct media_v2_entity *mp_device_find_entity(const MPDevice *device, cons
return NULL; 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 // Find the entity from the entity type
for (uint32_t i = 0; i < device->num_entities; ++i) { for (uint32_t i = 0; i < device->num_entities; ++i) {
@ -187,12 +201,14 @@ const struct media_v2_entity *mp_device_find_entity_type(const MPDevice *device,
return NULL; 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) { for (int i = 0; i < device->num_entities; ++i) {
if (device->entities[i].id == id) { if (device->entities[i].id == id) {
@ -202,17 +218,20 @@ const struct media_v2_entity *mp_device_get_entity(const MPDevice *device, uint3
return NULL; 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 // Find the interface through the link
const struct media_v2_link *link = mp_device_find_link_to(device, entity_id); const struct media_v2_link *link = mp_device_find_link_to(device, entity_id);
@ -222,7 +241,8 @@ const struct media_v2_interface *mp_device_find_entity_interface(const MPDevice
return mp_device_get_interface(device, link->source_id); 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) { for (int i = 0; i < device->num_interfaces; ++i) {
if (device->interfaces[i].id == id) { if (device->interfaces[i].id == id) {
@ -232,17 +252,20 @@ const struct media_v2_interface *mp_device_get_interface(const MPDevice *device,
return NULL; 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) { for (int i = 0; i < device->num_pads; ++i) {
if (device->pads[i].entity_id == entity_id) { if (device->pads[i].entity_id == entity_id) {
@ -252,7 +275,8 @@ const struct media_v2_pad *mp_device_get_pad_from_entity(const MPDevice *device,
return NULL; 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) { for (int i = 0; i < device->num_pads; ++i) {
if (device->pads[i].id == id) { if (device->pads[i].id == id) {
@ -262,19 +286,23 @@ const struct media_v2_pad *mp_device_get_pad(const MPDevice *device, uint32_t id
return NULL; 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_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); const struct media_v2_link *link = mp_device_find_link_to(device, pad->id);
if (link) { if (link) {
return link; return link;
@ -282,7 +310,8 @@ const struct media_v2_link *mp_device_find_entity_link(const MPDevice *device, u
return mp_device_find_link_from(device, pad->id); 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) { for (int i = 0; i < device->num_links; ++i) {
if (device->links[i].source_id == source) { if (device->links[i].source_id == source) {
@ -292,7 +321,8 @@ const struct media_v2_link *mp_device_find_link_from(const MPDevice *device, uin
return NULL; 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) { for (int i = 0; i < device->num_links; ++i) {
if (device->links[i].sink_id == sink) { if (device->links[i].sink_id == sink) {
@ -302,18 +332,20 @@ const struct media_v2_link *mp_device_find_link_to(const MPDevice *device, uint3
return NULL; 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) { for (int i = 0; i < device->num_links; ++i) {
if (device->links[i].source_id == source if (device->links[i].source_id == source &&
&& device->links[i].sink_id == sink) { device->links[i].sink_id == sink) {
return &device->links[i]; return &device->links[i];
} }
} }
return NULL; 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) { for (int i = 0; i < device->num_links; ++i) {
if (device->links[i].id == id) { if (device->links[i].id == id) {
@ -323,12 +355,14 @@ const struct media_v2_link *mp_device_get_link(const MPDevice *device, uint32_t
return NULL; 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;
} }
@ -338,7 +372,8 @@ struct _MPDeviceList {
MPDeviceList *next; MPDeviceList *next;
}; };
MPDeviceList *mp_device_list_new() MPDeviceList *
mp_device_list_new()
{ {
MPDeviceList *current = NULL; MPDeviceList *current = NULL;
@ -365,7 +400,8 @@ MPDeviceList *mp_device_list_new()
return current; return current;
} }
void mp_device_list_free(MPDeviceList *device_list) void
mp_device_list_free(MPDeviceList *device_list)
{ {
while (device_list) { while (device_list) {
MPDeviceList *tmp = device_list; MPDeviceList *tmp = device_list;
@ -376,7 +412,8 @@ void mp_device_list_free(MPDeviceList *device_list)
} }
} }
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; MPDevice *found_device = NULL;
int length = strlen(driver_name); int length = strlen(driver_name);
@ -396,7 +433,8 @@ MPDevice *mp_device_list_find_remove(MPDeviceList **list, const char *driver_nam
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;
@ -412,12 +450,14 @@ MPDevice *mp_device_list_remove(MPDeviceList **device_list)
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;
} }

View File

@ -5,7 +5,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
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; typedef struct _MPDevice MPDevice;
@ -14,26 +15,37 @@ MPDevice *mp_device_open(const char *path);
MPDevice *mp_device_new(int fd); MPDevice *mp_device_new(int fd);
void mp_device_close(MPDevice *device); 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_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(const MPDevice *device,
const struct media_v2_entity *mp_device_find_entity_type(const MPDevice *device, const uint32_t type); const char *driver_name);
const struct media_v2_entity *mp_device_get_entity(const MPDevice *device, uint32_t id); 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); const struct media_v2_entity *mp_device_get_entities(const MPDevice *device);
size_t mp_device_get_num_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 *
const struct media_v2_interface *mp_device_get_interface(const MPDevice *device, uint32_t id); 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); const struct media_v2_interface *mp_device_get_interfaces(const MPDevice *device);
size_t mp_device_get_num_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_pad(const MPDevice *device, uint32_t id);
const struct media_v2_pad *mp_device_get_pads(const MPDevice *device); const struct media_v2_pad *mp_device_get_pads(const MPDevice *device);
size_t mp_device_get_num_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_entity_link(const MPDevice *device,
const struct media_v2_link *mp_device_find_link_from(const MPDevice *device, uint32_t source); uint32_t entity_id);
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_from(const MPDevice *device,
const struct media_v2_link *mp_device_find_link_between(const MPDevice *device, uint32_t source, uint32_t sink); 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_link(const MPDevice *device, uint32_t id);
const struct media_v2_link *mp_device_get_links(const MPDevice *device); const struct media_v2_link *mp_device_get_links(const MPDevice *device);
size_t mp_device_get_num_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(); MPDeviceList *mp_device_list_new();
void mp_device_list_free(MPDeviceList *device_list); 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_remove(MPDeviceList **device_list);
MPDevice *mp_device_list_get(const MPDeviceList *device_list); MPDevice *mp_device_list_get(const MPDeviceList *device_list);

53
ini.c
View File

@ -25,26 +25,29 @@ https://github.com/benhoyt/inih
#define MAX_NAME 50 #define MAX_NAME 50
/* Strip whitespace chars off end of given string, in place. Return s. */ /* 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); char *p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p))) while (p > s && isspace((unsigned char)(*--p)))
*p = '\0'; *p = '\0';
return s; return s;
} }
/* Return pointer to first non-whitespace char in given string. */ /* 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))) while (*s && isspace((unsigned char)(*s)))
s++; s++;
return (char*)s; return (char *)s;
} }
/* Return pointer to first char (of chars) or inline comment in given string, /* 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 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. */ 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 #if INI_ALLOW_INLINE_COMMENTS
int was_space = 0; int was_space = 0;
@ -58,39 +61,40 @@ static char* find_chars_or_comment(const char* s, const char* chars)
s++; s++;
} }
#endif #endif
return (char*)s; return (char *)s;
} }
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ /* 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); strncpy(dest, src, size - 1);
dest[size - 1] = '\0'; dest[size - 1] = '\0';
return dest; return dest;
} }
/* See documentation in header file. */ /* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, int
void* user) 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 #if INI_USE_STACK
char line[INI_MAX_LINE]; char line[INI_MAX_LINE];
#else #else
char* line; char *line;
#endif #endif
char section[MAX_SECTION] = ""; char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = ""; char prev_name[MAX_NAME] = "";
char* start; char *start;
char* end; char *end;
char* name; char *name;
char* value; char *value;
int lineno = 0; int lineno = 0;
int error = 0; int error = 0;
#if !INI_USE_STACK #if !INI_USE_STACK
line = (char*)malloc(INI_MAX_LINE); line = (char *)malloc(INI_MAX_LINE);
if (!line) { if (!line) {
return -2; return -2;
} }
@ -129,13 +133,11 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
*end = '\0'; *end = '\0';
strncpy0(section, start + 1, sizeof(section)); strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0'; *prev_name = '\0';
} } else if (!error) {
else if (!error) {
/* No ']' found on section line */ /* No ']' found on section line */
error = lineno; error = lineno;
} }
} } else if (*start) {
else if (*start) {
/* Not a comment, must be a name[=:]value pair */ /* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:"); end = find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') { if (*end == '=' || *end == ':') {
@ -154,8 +156,7 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
if (!handler(user, section, name, value) && !error) if (!handler(user, section, name, value) && !error)
error = lineno; error = lineno;
memset(value, 0, strlen(value)); memset(value, 0, strlen(value));
} } else if (!error) {
else if (!error) {
/* No '=' or ':' found on name[=:]value line */ /* No '=' or ':' found on name[=:]value line */
error = lineno; error = lineno;
} }
@ -175,15 +176,17 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
} }
/* See documentation in header file. */ /* 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. */ /* 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; FILE *file;
int error; int error;
file = fopen(filename, "r"); file = fopen(filename, "r");

14
ini.h
View File

@ -18,11 +18,11 @@ extern "C" {
#include <stdio.h> #include <stdio.h>
/* Typedef for prototype of handler function. */ /* Typedef for prototype of handler function. */
typedef int (*ini_handler)(void* user, const char* section, typedef int (*ini_handler)(void *user, const char *section, const char *name,
const char* name, const char* value); const char *value);
/* Typedef for prototype of fgets-style reader function. */ /* 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 /* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section (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 stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero). 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 /* 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. */ 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 /* Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O. */ filename. Used for implementing custom or string-based I/O. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler,
void* user); void *user);
/* Nonzero to allow multi-line value parsing, in the style of Python's /* 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 configparser. If allowed, ini_parse() will call the handler with the same

View File

@ -35,7 +35,6 @@ struct camera_info {
bool has_auto_focus_continuous; bool has_auto_focus_continuous;
bool has_auto_focus_start; bool has_auto_focus_start;
// unsigned int entity_id; // unsigned int entity_id;
// enum v4l2_buf_type type; // enum v4l2_buf_type type;
@ -43,7 +42,6 @@ struct camera_info {
// char video_dev_fname[260]; // char video_dev_fname[260];
// int media_fd; // int media_fd;
// struct mp_media_link media_links[MP_MAX_LINKS]; // struct mp_media_link media_links[MP_MAX_LINKS];
// int num_media_links; // int num_media_links;
@ -93,39 +91,45 @@ static bool want_focus = false;
static MPPipeline *pipeline; static MPPipeline *pipeline;
static GSource *capture_source; 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 // Find device info
size_t device_index = 0; size_t device_index = 0;
for (; device_index < num_devices; ++device_index) { for (; device_index < num_devices; ++device_index) {
if (strcmp(config->media_dev_name, devices[device_index].media_dev_name) == 0) { if (strcmp(config->media_dev_name,
devices[device_index].media_dev_name) == 0) {
break; break;
} }
} }
if (device_index == num_devices) if (device_index == num_devices) {
{
device_index = num_devices; device_index = num_devices;
// Initialize new device // Initialize new device
struct device_info *info = &devices[device_index]; struct device_info *info = &devices[device_index];
info->media_dev_name = config->media_dev_name; info->media_dev_name = config->media_dev_name;
info->device = mp_device_list_find_remove(device_list, info->media_dev_name); info->device = mp_device_list_find_remove(device_list,
info->media_dev_name);
if (!info->device) { if (!info->device) {
g_printerr("Could not find /dev/media* node matching '%s'\n", info->media_dev_name); g_printerr("Could not find /dev/media* node matching '%s'\n",
info->media_dev_name);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
const struct media_v2_entity *entity = mp_device_find_entity_type(info->device, MEDIA_ENT_F_IO_V4L); const struct media_v2_entity *entity =
mp_device_find_entity_type(info->device, MEDIA_ENT_F_IO_V4L);
if (!entity) { if (!entity) {
g_printerr("Could not find device video entity\n"); g_printerr("Could not find device video entity\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
const struct media_v2_pad *pad = mp_device_get_pad_from_entity(info->device, entity->id); const struct media_v2_pad *pad =
mp_device_get_pad_from_entity(info->device, entity->id);
info->interface_pad_id = pad->id; info->interface_pad_id = pad->id;
const struct media_v2_interface *interface = mp_device_find_entity_interface(info->device, entity->id); const struct media_v2_interface *interface =
mp_device_find_entity_interface(info->device, entity->id);
char dev_name[260]; char dev_name[260];
if (!mp_find_device_path(interface->devnode, dev_name, 260)) { if (!mp_find_device_path(interface->devnode, dev_name, 260)) {
g_printerr("Could not find video path\n"); g_printerr("Could not find video path\n");
@ -147,24 +151,26 @@ static void setup_camera(MPDeviceList **device_list, const struct mp_camera_conf
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); const struct media_v2_entity *entity =
mp_device_find_entity(dev_info->device, config->dev_name);
if (!entity) { if (!entity) {
g_printerr("Could not find camera entity matching '%s'\n", config->dev_name); g_printerr("Could not find camera entity matching '%s'\n",
config->dev_name);
exit(EXIT_FAILURE); 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 // Make sure the camera starts out as disabled
mp_device_setup_link( mp_device_setup_link(dev_info->device, info->pad_id,
dev_info->device, dev_info->interface_pad_id, false);
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)) { if (!mp_find_device_path(interface->devnode, info->dev_fname, 260)) {
g_printerr("Could not find camera device path\n"); g_printerr("Could not find camera device path\n");
@ -180,11 +186,14 @@ static void setup_camera(MPDeviceList **device_list, const struct mp_camera_conf
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 // Trigger continuous auto focus if the sensor supports it
if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO, NULL)) { if (mp_camera_query_control(info->camera, V4L2_CID_FOCUS_AUTO,
NULL)) {
info->has_auto_focus_continuous = true; info->has_auto_focus_continuous = true;
mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, 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)) { if (mp_camera_query_control(info->camera, V4L2_CID_AUTO_FOCUS_START,
NULL)) {
info->has_auto_focus_start = true; info->has_auto_focus_start = true;
} }
@ -192,15 +201,16 @@ static void setup_camera(MPDeviceList **device_list, const struct mp_camera_conf
if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) { if (mp_camera_query_control(info->camera, V4L2_CID_GAIN, &control)) {
info->gain_ctrl = V4L2_CID_GAIN; info->gain_ctrl = V4L2_CID_GAIN;
info->gain_max = control.max; info->gain_max = control.max;
} } else if (mp_camera_query_control(
else if (mp_camera_query_control(info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) { info->camera, V4L2_CID_ANALOGUE_GAIN, &control)) {
info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN; info->gain_ctrl = V4L2_CID_ANALOGUE_GAIN;
info->gain_max = control.max; 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();
@ -216,7 +226,8 @@ static void setup(MPPipeline *pipeline, const void *data)
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();
@ -225,7 +236,8 @@ void mp_io_pipeline_start()
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) { if (capture_source) {
g_source_destroy(capture_source); g_source_destroy(capture_source);
@ -243,10 +255,12 @@ update_process_pipeline()
// Grab the latest control values // Grab the latest control values
if (!current_controls.gain_is_manual) { if (!current_controls.gain_is_manual) {
current_controls.gain = mp_camera_control_get_int32(info->camera, info->gain_ctrl); current_controls.gain =
mp_camera_control_get_int32(info->camera, info->gain_ctrl);
} }
if (!current_controls.exposure_is_manual) { if (!current_controls.exposure_is_manual) {
current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); current_controls.exposure =
mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE);
} }
struct mp_process_pipeline_state pipeline_state = { struct mp_process_pipeline_state pipeline_state = {
@ -272,7 +286,8 @@ 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);
} }
@ -286,7 +301,8 @@ capture(MPPipeline *pipeline, const void *data)
// Disable the autogain/exposure while taking the burst // 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_AUTOGAIN, 0);
mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL); mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_MANUAL);
// Change camera mode for capturing // Change camera mode for capturing
mp_camera_stop_capture(info->camera); mp_camera_stop_capture(info->camera);
@ -302,7 +318,8 @@ capture(MPPipeline *pipeline, const void *data)
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);
} }
@ -319,31 +336,39 @@ update_controls()
if (want_focus) { if (want_focus) {
if (info->has_auto_focus_continuous) { if (info->has_auto_focus_continuous) {
mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO, 1); mp_camera_control_set_bool(info->camera, V4L2_CID_FOCUS_AUTO,
1);
} else if (info->has_auto_focus_start) { } else if (info->has_auto_focus_start) {
mp_camera_control_set_bool(info->camera, V4L2_CID_AUTO_FOCUS_START, 1); 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) { 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); 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) { if (desired_controls.gain_is_manual &&
mp_camera_control_set_int32(info->camera, info->gain_ctrl, desired_controls.gain); 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) { if (current_controls.exposure_is_manual !=
mp_camera_control_set_int32( desired_controls.exposure_is_manual) {
info->camera, mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO,
V4L2_CID_EXPOSURE_AUTO, desired_controls.exposure_is_manual ?
desired_controls.exposure_is_manual ? V4L2_EXPOSURE_MANUAL : V4L2_EXPOSURE_AUTO); V4L2_EXPOSURE_MANUAL :
V4L2_EXPOSURE_AUTO);
} }
if (desired_controls.exposure_is_manual && current_controls.exposure != desired_controls.exposure) { if (desired_controls.exposure_is_manual &&
mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE, desired_controls.exposure); 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;
@ -357,11 +382,11 @@ on_frame(MPImage image, void *data)
// When the mode is switched while capturing we get a couple blank frames, // When the mode is switched while capturing we get a couple blank frames,
// presumably from buffers made ready during the switch. Ignore these. // presumably from buffers made ready during the switch. Ignore these.
if (just_switched_mode) if (just_switched_mode) {
{
if (blank_frame_count < 20) { if (blank_frame_count < 20) {
// Only check a 50x50 area // Only check a 50x50 area
size_t test_size = MIN(50, image.width) * MIN(50, image.height); size_t test_size =
MIN(50, image.width) * MIN(50, image.height);
bool image_is_blank = true; bool image_is_blank = true;
for (size_t i = 0; i < test_size; ++i) { for (size_t i = 0; i < test_size; ++i) {
@ -383,7 +408,9 @@ on_frame(MPImage image, void *data)
} }
// Copy from the camera buffer // Copy from the camera buffer
size_t size = mp_pixel_format_width_to_bytes(image.pixel_format, image.width) * image.height; size_t size =
mp_pixel_format_width_to_bytes(image.pixel_format, image.width) *
image.height;
uint8_t *buffer = malloc(size); uint8_t *buffer = malloc(size);
memcpy(buffer, image.data, size); memcpy(buffer, image.data, size);
@ -400,11 +427,14 @@ on_frame(MPImage image, void *data)
// Restore the auto exposure and gain if needed // Restore the auto exposure and gain if needed
if (!current_controls.exposure_is_manual) { if (!current_controls.exposure_is_manual) {
mp_camera_control_set_int32(info->camera, V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_AUTO); mp_camera_control_set_int32(info->camera,
V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_AUTO);
} }
if (!current_controls.gain_is_manual) { if (!current_controls.gain_is_manual) {
mp_camera_control_set_bool(info->camera, V4L2_CID_AUTOGAIN, true); mp_camera_control_set_bool(info->camera,
V4L2_CID_AUTOGAIN, true);
} }
// Go back to preview mode // Go back to preview mode
@ -436,11 +466,8 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
struct device_info *dev_info = &devices[info->device_index]; struct device_info *dev_info = &devices[info->device_index];
mp_camera_stop_capture(info->camera); mp_camera_stop_capture(info->camera);
mp_device_setup_link( mp_device_setup_link(dev_info->device, info->pad_id,
dev_info->device, dev_info->interface_pad_id, false);
info->pad_id,
dev_info->interface_pad_id,
false);
} }
if (capture_source) { if (capture_source) {
@ -454,30 +481,34 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
struct camera_info *info = &cameras[camera->index]; struct camera_info *info = &cameras[camera->index];
struct device_info *dev_info = &devices[info->device_index]; struct device_info *dev_info = &devices[info->device_index];
mp_device_setup_link( mp_device_setup_link(dev_info->device, info->pad_id,
dev_info->device, dev_info->interface_pad_id, true);
info->pad_id,
dev_info->interface_pad_id,
true);
mode = camera->preview_mode; mode = camera->preview_mode;
mp_camera_set_mode(info->camera, &mode); mp_camera_set_mode(info->camera, &mode);
mp_camera_start_capture(info->camera); mp_camera_start_capture(info->camera);
capture_source = mp_pipeline_add_capture_source(pipeline, info->camera, on_frame, NULL); 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_is_manual =
current_controls.gain = mp_camera_control_get_int32(info->camera, info->gain_ctrl); 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_is_manual =
current_controls.exposure = mp_camera_control_get_int32(info->camera, V4L2_CID_EXPOSURE); 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 has_changed = has_changed || burst_length != state->burst_length ||
|| burst_length != state->burst_length preview_width != state->preview_width ||
|| preview_width != state->preview_width preview_height != state->preview_height;
|| preview_height != state->preview_height;
burst_length = state->burst_length; burst_length = state->burst_length;
preview_width = state->preview_width; preview_width = state->preview_width;
@ -491,7 +522,9 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
desired_controls.exposure_is_manual = state->exposure_is_manual; desired_controls.exposure_is_manual = state->exposure_is_manual;
desired_controls.exposure = state->exposure; desired_controls.exposure = state->exposure;
has_changed = has_changed || 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);
@ -499,7 +532,9 @@ update_state(MPPipeline *pipeline, const struct mp_io_pipeline_state *state)
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));
} }

166
main.c
View File

@ -21,10 +21,7 @@
#include "quickpreview.h" #include "quickpreview.h"
#include "io_pipeline.h" #include "io_pipeline.h"
enum user_control { enum user_control { USER_CONTROL_ISO, USER_CONTROL_SHUTTER };
USER_CONTROL_ISO,
USER_CONTROL_SHUTTER
};
static bool camera_is_initialized = false; static bool camera_is_initialized = false;
static const struct mp_camera_config *camera = NULL; static const struct mp_camera_config *camera = NULL;
@ -121,17 +118,14 @@ update_state(const struct mp_main_state *state)
return false; 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)); struct mp_main_state *state_copy = malloc(sizeof(struct mp_main_state));
*state_copy = *state; *state_copy = *state;
g_main_context_invoke_full( g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
g_main_context_default(), (GSourceFunc)update_state, state_copy, free);
G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)update_state,
state_copy,
free);
} }
static bool static bool
@ -145,19 +139,16 @@ set_preview(cairo_surface_t *image)
return false; 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_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
g_main_context_default(), (GSourceFunc)set_preview, image, NULL);
G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)set_preview,
image,
NULL);
} }
static void static void
draw_surface_scaled_centered( draw_surface_scaled_centered(cairo_t *cr, uint32_t dst_width, uint32_t dst_height,
cairo_t *cr, uint32_t dst_width, uint32_t dst_height, cairo_surface_t *surface) cairo_surface_t *surface)
{ {
cairo_save(cr); cairo_save(cr);
@ -165,7 +156,7 @@ draw_surface_scaled_centered(
int width = cairo_image_surface_get_width(surface); int width = cairo_image_surface_get_width(surface);
int height = cairo_image_surface_get_height(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_scale(cr, scale, scale);
cairo_translate(cr, -width / 2, -height / 2); cairo_translate(cr, -width / 2, -height / 2);
@ -181,10 +172,8 @@ capture_completed(const char *fname)
strncpy(last_path, fname, 260); strncpy(last_path, fname, 260);
// Create a thumbnail from the current surface // Create a thumbnail from the current surface
cairo_surface_t *thumb = cairo_image_surface_create( cairo_surface_t *thumb =
CAIRO_FORMAT_ARGB32, cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 24, 24);
24,
24);
cairo_t *cr = cairo_create(thumb); cairo_t *cr = cairo_create(thumb);
draw_surface_scaled_centered(cr, 24, 24, surface); draw_surface_scaled_centered(cr, 24, 24, surface);
@ -196,16 +185,13 @@ capture_completed(const char *fname)
return false; return false;
} }
void mp_main_capture_completed(const char *fname) void
mp_main_capture_completed(const char *fname)
{ {
gchar *name = g_strdup(fname); gchar *name = g_strdup(fname);
g_main_context_invoke_full( g_main_context_invoke_full(g_main_context_default(), G_PRIORITY_DEFAULT_IDLE,
g_main_context_default(), (GSourceFunc)capture_completed, name, g_free);
G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc)capture_completed,
name,
g_free);
} }
static void static void
@ -217,14 +203,16 @@ draw_controls()
char shutterangle[6]; char shutterangle[6];
if (exposure_is_manual) { 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); sprintf(shutterangle, "%d\u00b0", temp);
} else { } else {
sprintf(shutterangle, "auto"); sprintf(shutterangle, "auto");
} }
if (gain_is_manual) { 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); sprintf(iso, "%d", temp);
} else { } else {
sprintf(iso, "auto"); sprintf(iso, "auto");
@ -237,7 +225,8 @@ draw_controls()
if (gtk_widget_get_window(preview) == NULL) { if (gtk_widget_get_window(preview) == NULL) {
return; return;
} }
status_surface = gdk_window_create_similar_surface(gtk_widget_get_window(preview), status_surface =
gdk_window_create_similar_surface(gtk_widget_get_window(preview),
CAIRO_CONTENT_COLOR_ALPHA, CAIRO_CONTENT_COLOR_ALPHA,
preview_width, 32); preview_width, 32);
@ -246,7 +235,8 @@ draw_controls()
cairo_paint(cr); cairo_paint(cr);
// Draw the outlines for the headings // 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_font_size(cr, 9);
cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_source_rgba(cr, 0, 0, 0, 1);
@ -266,7 +256,8 @@ draw_controls()
cairo_show_text(cr, "Shutter"); cairo_show_text(cr, "Shutter");
// Draw the outlines for the values // 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_font_size(cr, 11);
cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_source_rgba(cr, 0, 0, 0, 1);
@ -302,7 +293,8 @@ preview_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
// Draw camera preview // Draw camera preview
if (surface) { 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 // Draw control overlay
@ -311,15 +303,14 @@ preview_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
return FALSE; return FALSE;
} }
static gboolean static gboolean
preview_configure(GtkWidget *widget, GdkEventConfigure *event) preview_configure(GtkWidget *widget, GdkEventConfigure *event)
{ {
int new_preview_width = gtk_widget_get_allocated_width(widget); int new_preview_width = gtk_widget_get_allocated_width(widget);
int new_preview_height = gtk_widget_get_allocated_height(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_width = new_preview_width;
preview_height = new_preview_height; preview_height = new_preview_height;
update_io_pipeline(); update_io_pipeline();
@ -336,11 +327,11 @@ on_open_last_clicked(GtkWidget *widget, gpointer user_data)
char uri[275]; char uri[275];
GError *error = NULL; GError *error = NULL;
if(strlen(last_path) == 0) { if (strlen(last_path) == 0) {
return; return;
} }
sprintf(uri, "file://%s.tiff", last_path); 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); 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]; char uri[270];
GError *error = NULL; GError *error = NULL;
sprintf(uri, "file://%s/Pictures", getenv("HOME")); 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); 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); gtk_widget_show(control_box);
} }
if (event->x < 60 ) { if (event->x < 60) {
// ISO // ISO
current_control = USER_CONTROL_ISO; current_control = USER_CONTROL_ISO;
gtk_label_set_text(GTK_LABEL(control_name), "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_lower(control_slider, 0.0);
gtk_adjustment_set_upper(control_slider, (float)gain_max); gtk_adjustment_set_upper(control_slider, (float)gain_max);
gtk_adjustment_set_value(control_slider, (double)gain); gtk_adjustment_set_value(control_slider, (double)gain);
@ -390,7 +382,8 @@ on_preview_tap(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
// Shutter angle // Shutter angle
current_control = USER_CONTROL_SHUTTER; current_control = USER_CONTROL_SHUTTER;
gtk_label_set_text(GTK_LABEL(control_name), "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_lower(control_slider, 1.0);
gtk_adjustment_set_upper(control_slider, 360.0); gtk_adjustment_set_upper(control_slider, 360.0);
gtk_adjustment_set_value(control_slider, (double)exposure); gtk_adjustment_set_value(control_slider, (double)exposure);
@ -415,7 +408,8 @@ void
on_camera_switch_clicked(GtkWidget *widget, gpointer user_data) on_camera_switch_clicked(GtkWidget *widget, gpointer user_data)
{ {
size_t next_index = camera->index + 1; 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) { if (!next_camera) {
next_index = 0; next_index = 0;
@ -478,10 +472,10 @@ on_control_slider_changed(GtkAdjustment *widget, gpointer user_data)
has_changed = true; has_changed = true;
} }
break; break;
case USER_CONTROL_SHUTTER: case USER_CONTROL_SHUTTER: {
{
// So far all sensors use exposure time in number of sensor rows // So far all sensors use exposure time in number of sensor rows
int new_exposure = (int)(value / 360.0 * camera->capture_mode.height); int new_exposure =
(int)(value / 360.0 * camera->capture_mode.height);
if (new_exposure != exposure) { if (new_exposure != exposure) {
exposure = new_exposure; exposure = new_exposure;
has_changed = true; has_changed = true;
@ -504,19 +498,26 @@ main(int argc, char *argv[])
setenv("LC_NUMERIC", "C", 1); setenv("LC_NUMERIC", "C", 1);
gtk_init(&argc, &argv); gtk_init(&argc, &argv);
g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", TRUE, NULL); g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme",
GtkBuilder *builder = gtk_builder_new_from_resource("/org/postmarketos/Megapixels/camera.glade"); 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 *window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
GtkWidget *shutter = GTK_WIDGET(gtk_builder_get_object(builder, "shutter")); GtkWidget *shutter = GTK_WIDGET(gtk_builder_get_object(builder, "shutter"));
GtkWidget *switch_btn = GTK_WIDGET(gtk_builder_get_object(builder, "switch_camera")); GtkWidget *switch_btn =
GtkWidget *settings_btn = GTK_WIDGET(gtk_builder_get_object(builder, "settings")); GTK_WIDGET(gtk_builder_get_object(builder, "switch_camera"));
GtkWidget *settings_back = GTK_WIDGET(gtk_builder_get_object(builder, "settings_back")); GtkWidget *settings_btn =
GtkWidget *error_close = GTK_WIDGET(gtk_builder_get_object(builder, "error_close")); GTK_WIDGET(gtk_builder_get_object(builder, "settings"));
GtkWidget *open_last = GTK_WIDGET(gtk_builder_get_object(builder, "open_last")); GtkWidget *settings_back =
GtkWidget *open_directory = GTK_WIDGET(gtk_builder_get_object(builder, "open_directory")); 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")); preview = GTK_WIDGET(gtk_builder_get_object(builder, "preview"));
error_box = GTK_WIDGET(gtk_builder_get_object(builder, "error_box")); error_box = GTK_WIDGET(gtk_builder_get_object(builder, "error_box"));
error_message = GTK_WIDGET(gtk_builder_get_object(builder, "error_message")); error_message = GTK_WIDGET(gtk_builder_get_object(builder, "error_message"));
@ -524,37 +525,48 @@ main(int argc, char *argv[])
thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last")); thumb_last = GTK_WIDGET(gtk_builder_get_object(builder, "thumb_last"));
control_box = GTK_WIDGET(gtk_builder_get_object(builder, "control_box")); control_box = GTK_WIDGET(gtk_builder_get_object(builder, "control_box"));
control_name = GTK_WIDGET(gtk_builder_get_object(builder, "control_name")); 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")); 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(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), 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(error_close, "clicked", G_CALLBACK(on_error_close_clicked),
g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked), NULL); NULL);
g_signal_connect(settings_btn, "clicked", G_CALLBACK(on_settings_btn_clicked), NULL); g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked),
g_signal_connect(settings_back, "clicked", G_CALLBACK(on_back_clicked), NULL); NULL);
g_signal_connect(open_last, "clicked", G_CALLBACK(on_open_last_clicked), NULL); g_signal_connect(settings_btn, "clicked",
g_signal_connect(open_directory, "clicked", G_CALLBACK(on_open_directory_clicked), NULL); 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, "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) | gtk_widget_set_events(preview, gtk_widget_get_events(preview) |
GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); GDK_BUTTON_PRESS_MASK |
g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap), NULL); GDK_POINTER_MOTION_MASK);
g_signal_connect(control_auto, "toggled", G_CALLBACK(on_control_auto_toggled), NULL); g_signal_connect(preview, "button-press-event", G_CALLBACK(on_preview_tap),
g_signal_connect(control_slider, "value-changed", G_CALLBACK(on_control_slider_changed), NULL); 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(); GtkCssProvider *provider = gtk_css_provider_new();
if (access("camera.css", F_OK) != -1) { if (access("camera.css", F_OK) != -1) {
gtk_css_provider_load_from_path(provider, "camera.css", NULL); gtk_css_provider_load_from_path(provider, "camera.css", NULL);
} else { } 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); GtkStyleContext *context = gtk_widget_get_style_context(error_box);
gtk_style_context_add_provider(context, gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_USER); GTK_STYLE_PROVIDER_PRIORITY_USER);
context = gtk_widget_get_style_context(control_box); context = gtk_widget_get_style_context(control_box);
gtk_style_context_add_provider(context, gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_USER); GTK_STYLE_PROVIDER_PRIORITY_USER);
mp_io_pipeline_start(); mp_io_pipeline_start();

3
main.h
View File

@ -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_set_preview(cairo_surface_t *image);
void mp_main_capture_completed(const char *fname); void mp_main_capture_completed(const char *fname);
int int remap(int value, int input_min, int input_max, int output_min, int output_max);
remap(int value, int input_min, int input_max, int output_min, int output_max);

View File

@ -1,14 +1,15 @@
void 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 // zero out target matrix
for(int i=0; i<9; i++) { for (int i = 0; i < 9; i++) {
out[i] = 0; out[i] = 0;
} }
for(int i=0; i<3; i++) { for (int i = 0; i < 3; i++) {
for(int j=0; j<3; j++) { for (int j = 0; j < 3; j++) {
for(int k=0; k<3; k++) { for (int k = 0; k < 3; k++) {
out[i*3+j] += a[i*3+k] * b[k*3+j]; out[i * 3 + j] += a[i * 3 + k] * b[k * 3 + j];
} }
} }
} }

View File

@ -10,7 +10,8 @@ struct _MPPipeline {
pthread_t thread; pthread_t thread;
}; };
static void *thread_main_loop(void *arg) static void *
thread_main_loop(void *arg)
{ {
MPPipeline *pipeline = arg; MPPipeline *pipeline = arg;
@ -18,13 +19,14 @@ static void *thread_main_loop(void *arg)
return NULL; return NULL;
} }
MPPipeline *mp_pipeline_new() MPPipeline *
mp_pipeline_new()
{ {
MPPipeline *pipeline = malloc(sizeof(MPPipeline)); MPPipeline *pipeline = malloc(sizeof(MPPipeline));
pipeline->main_context = g_main_context_new(); pipeline->main_context = g_main_context_new();
pipeline->main_loop = g_main_loop_new(pipeline->main_context, false); pipeline->main_loop = g_main_loop_new(pipeline->main_context, false);
int res = pthread_create( int res =
&pipeline->thread, NULL, thread_main_loop, pipeline); pthread_create(&pipeline->thread, NULL, thread_main_loop, pipeline);
assert(res == 0); assert(res == 0);
return pipeline; return pipeline;
@ -35,13 +37,16 @@ struct invoke_args {
MPPipelineCallback callback; MPPipelineCallback callback;
}; };
static bool invoke_impl(struct invoke_args *args) static bool
invoke_impl(struct invoke_args *args)
{ {
args->callback(args->pipeline, args + 1); args->callback(args->pipeline, args + 1);
return false; 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) { if (pthread_self() != pipeline->thread) {
struct invoke_args *args = malloc(sizeof(struct invoke_args) + size); struct invoke_args *args = malloc(sizeof(struct invoke_args) + size);
@ -52,18 +57,16 @@ void mp_pipeline_invoke(MPPipeline *pipeline, MPPipelineCallback callback, const
memcpy(args + 1, data, size); memcpy(args + 1, data, size);
} }
g_main_context_invoke_full( g_main_context_invoke_full(pipeline->main_context,
pipeline->main_context,
G_PRIORITY_DEFAULT, G_PRIORITY_DEFAULT,
(GSourceFunc)invoke_impl, (GSourceFunc)invoke_impl, args, free);
args,
free);
} else { } else {
callback(pipeline, data); 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);
@ -75,34 +78,33 @@ void mp_pipeline_free(MPPipeline *pipeline)
free(pipeline); free(pipeline);
} }
struct capture_source_args struct capture_source_args {
{
MPCamera *camera; MPCamera *camera;
void (*callback)(MPImage, void *); void (*callback)(MPImage, void *);
void *user_data; 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); mp_camera_capture_image(args->camera, args->callback, args->user_data);
return true; return true;
} }
// Not thread safe // 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); int video_fd = mp_camera_get_video_fd(camera);
GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN); GSource *video_source = g_unix_fd_source_new(video_fd, G_IO_IN);
struct capture_source_args *args = malloc(sizeof(struct capture_source_args)); struct capture_source_args *args =
malloc(sizeof(struct capture_source_args));
args->camera = camera; args->camera = camera;
args->callback = callback; args->callback = callback;
args->user_data = user_data; args->user_data = user_data;
g_source_set_callback( g_source_set_callback(video_source, (GSourceFunc)on_capture, args, free);
video_source,
(GSourceFunc)on_capture,
args,
free);
g_source_attach(video_source, pipeline->main_context); g_source_attach(video_source, pipeline->main_context);
return video_source; return video_source;
} }

View File

@ -9,7 +9,10 @@ typedef struct _MPPipeline MPPipeline;
typedef void (*MPPipelineCallback)(MPPipeline *, const void *); typedef void (*MPPipelineCallback)(MPPipeline *, const void *);
MPPipeline *mp_pipeline_new(); 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); 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);

View File

@ -12,11 +12,8 @@
#define TIFFTAG_FORWARDMATRIX1 50964 #define TIFFTAG_FORWARDMATRIX1 50964
static const float colormatrix_srgb[] = { static const float colormatrix_srgb[] = { 3.2409, -1.5373, -0.4986, -0.9692, 1.8759,
3.2409, -1.5373, -0.4986, 0.0415, 0.0556, -0.2039, 1.0569 };
-0.9692, 1.8759, 0.0415,
0.0556, -0.2039, 1.0569
};
static MPPipeline *pipeline; static MPPipeline *pipeline;
@ -50,11 +47,13 @@ static void
register_custom_tiff_tags(TIFF *tif) register_custom_tiff_tags(TIFF *tif)
{ {
static const TIFFFieldInfo custom_fields[] = { static const TIFFFieldInfo custom_fields[] = {
{TIFFTAG_FORWARDMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1, "ForwardMatrix1"}, { TIFFTAG_FORWARDMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, 1, 1,
"ForwardMatrix1" },
}; };
// Add missing dng fields // Add missing dng fields
TIFFMergeFieldInfo(tif, custom_fields, sizeof(custom_fields) / sizeof(custom_fields[0])); TIFFMergeFieldInfo(tif, custom_fields,
sizeof(custom_fields) / sizeof(custom_fields[0]));
} }
static bool static bool
@ -74,7 +73,7 @@ find_processor(char *script)
// Check postprocess.h in the current working directory // Check postprocess.h in the current working directory
sprintf(script, "%s", filename); sprintf(script, "%s", filename);
if(access(script, F_OK) != -1) { if (access(script, F_OK) != -1) {
sprintf(script, "./%s", filename); sprintf(script, "./%s", filename);
printf("Found postprocessor script at %s\n", script); printf("Found postprocessor script at %s\n", script);
return true; return true;
@ -82,21 +81,21 @@ find_processor(char *script)
// Check for a script in XDG_CONFIG_HOME // Check for a script in XDG_CONFIG_HOME
sprintf(script, "%s/megapixels/%s", xdg_config_home, filename); sprintf(script, "%s/megapixels/%s", xdg_config_home, filename);
if(access(script, F_OK) != -1) { if (access(script, F_OK) != -1) {
printf("Found postprocessor script at %s\n", script); printf("Found postprocessor script at %s\n", script);
return true; return true;
} }
// Check user overridden /etc/megapixels/postprocessor.sh // Check user overridden /etc/megapixels/postprocessor.sh
sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename); sprintf(script, "%s/megapixels/%s", SYSCONFDIR, filename);
if(access(script, F_OK) != -1) { if (access(script, F_OK) != -1) {
printf("Found postprocessor script at %s\n", script); printf("Found postprocessor script at %s\n", script);
return true; return true;
} }
// Check packaged /usr/share/megapixels/postprocessor.sh // Check packaged /usr/share/megapixels/postprocessor.sh
sprintf(script, "%s/megapixels/%s", DATADIR, filename); sprintf(script, "%s/megapixels/%s", DATADIR, filename);
if(access(script, F_OK) != -1) { if (access(script, F_OK) != -1) {
printf("Found postprocessor script at %s\n", script); printf("Found postprocessor script at %s\n", script);
return true; return true;
} }
@ -104,7 +103,8 @@ find_processor(char *script)
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);
@ -114,14 +114,16 @@ static void setup(MPPipeline *pipeline, const void *data)
} }
} }
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);
} }
@ -130,37 +132,20 @@ static void
process_image_for_preview(const MPImage *image) process_image_for_preview(const MPImage *image)
{ {
uint32_t surface_width, surface_height, skip; uint32_t surface_width, surface_height, skip;
quick_preview_size( quick_preview_size(&surface_width, &surface_height, &skip, preview_width,
&surface_width, preview_height, image->width, image->height,
&surface_height, image->pixel_format, camera->rotate);
&skip,
preview_width,
preview_height,
image->width,
image->height,
image->pixel_format,
camera->rotate);
cairo_surface_t *surface = cairo_image_surface_create( cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_RGB24, CAIRO_FORMAT_RGB24, surface_width, surface_height);
surface_width,
surface_height);
uint8_t *pixels = cairo_image_surface_get_data(surface); uint8_t *pixels = cairo_image_surface_get_data(surface);
quick_preview( quick_preview((uint32_t *)pixels, surface_width, surface_height, image->data,
(uint32_t *)pixels, image->width, image->height, image->pixel_format,
surface_width, camera->rotate, camera->mirrored,
surface_height,
image->data,
image->width,
image->height,
image->pixel_format,
camera->rotate,
camera->mirrored,
camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix, camera->previewmatrix[0] == 0 ? NULL : camera->previewmatrix,
camera->blacklevel, camera->blacklevel, skip);
skip);
mp_main_set_preview(surface); mp_main_set_preview(surface);
} }
@ -172,14 +157,14 @@ process_image_for_capture(const MPImage *image, int count)
time(&rawtime); time(&rawtime);
struct tm tim = *(localtime(&rawtime)); struct tm tim = *(localtime(&rawtime));
char datetime[20] = {0}; char datetime[20] = { 0 };
strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim); strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tim);
char fname[255]; char fname[255];
sprintf(fname, "%s/%d.dng", burst_dir, count); sprintf(fname, "%s/%d.dng", burst_dir, count);
TIFF *tif = TIFFOpen(fname, "w"); TIFF *tif = TIFFOpen(fname, "w");
if(!tif) { if (!tif) {
printf("Could not open tiff\n"); printf("Could not open tiff\n");
} }
@ -194,13 +179,17 @@ process_image_for_capture(const MPImage *image, int count)
TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model()); TIFFSetField(tif, TIFFTAG_MODEL, mp_get_device_model());
uint16_t orientation; uint16_t orientation;
if (camera->rotate == 0) { if (camera->rotate == 0) {
orientation = camera->mirrored ? ORIENTATION_TOPRIGHT : ORIENTATION_TOPLEFT; orientation = camera->mirrored ? ORIENTATION_TOPRIGHT :
ORIENTATION_TOPLEFT;
} else if (camera->rotate == 90) { } else if (camera->rotate == 90) {
orientation = camera->mirrored ? ORIENTATION_RIGHTBOT : ORIENTATION_LEFTBOT; orientation = camera->mirrored ? ORIENTATION_RIGHTBOT :
ORIENTATION_LEFTBOT;
} else if (camera->rotate == 180) { } else if (camera->rotate == 180) {
orientation = camera->mirrored ? ORIENTATION_BOTLEFT : ORIENTATION_BOTRIGHT; orientation = camera->mirrored ? ORIENTATION_BOTLEFT :
ORIENTATION_BOTRIGHT;
} else { } else {
orientation = camera->mirrored ? ORIENTATION_LEFTTOP : ORIENTATION_RIGHTTOP; orientation = camera->mirrored ? ORIENTATION_LEFTTOP :
ORIENTATION_RIGHTTOP;
} }
TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation); TIFFSetField(tif, TIFFTAG_ORIENTATION, orientation);
TIFFSetField(tif, TIFFTAG_DATETIME, datetime); TIFFSetField(tif, TIFFTAG_DATETIME, datetime);
@ -212,23 +201,25 @@ process_image_for_capture(const MPImage *image, int count)
TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0"); TIFFSetField(tif, TIFFTAG_DNGVERSION, "\001\001\0\0");
TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0"); TIFFSetField(tif, TIFFTAG_DNGBACKWARDVERSION, "\001\0\0\0");
char uniquecameramodel[255]; char uniquecameramodel[255];
sprintf(uniquecameramodel, "%s %s", mp_get_device_make(), mp_get_device_model()); sprintf(uniquecameramodel, "%s %s", mp_get_device_make(),
mp_get_device_model());
TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, uniquecameramodel); TIFFSetField(tif, TIFFTAG_UNIQUECAMERAMODEL, uniquecameramodel);
if(camera->colormatrix[0]) { if (camera->colormatrix[0]) {
TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, camera->colormatrix); TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, camera->colormatrix);
} else { } else {
TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, colormatrix_srgb); TIFFSetField(tif, TIFFTAG_COLORMATRIX1, 9, colormatrix_srgb);
} }
if(camera->forwardmatrix[0]) { if (camera->forwardmatrix[0]) {
TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9, camera->forwardmatrix); TIFFSetField(tif, TIFFTAG_FORWARDMATRIX1, 9, camera->forwardmatrix);
} }
static const float neutral[] = {1.0, 1.0, 1.0}; static const float neutral[] = { 1.0, 1.0, 1.0 };
TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral); TIFFSetField(tif, TIFFTAG_ASSHOTNEUTRAL, 3, neutral);
TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21); TIFFSetField(tif, TIFFTAG_CALIBRATIONILLUMINANT1, 21);
// Write black thumbnail, only windows uses this // Write black thumbnail, only windows uses this
{ {
unsigned char *buf = (unsigned char *)calloc(1, (int)image->width >> 4); unsigned char *buf =
for (int row = 0; row < image->height>>4; row++) { (unsigned char *)calloc(1, (int)image->width >> 4);
for (int row = 0; row < (image->height >> 4); row++) {
TIFFWriteScanline(tif, buf, row, 0); TIFFWriteScanline(tif, buf, row, 0);
} }
free(buf); free(buf);
@ -243,20 +234,20 @@ process_image_for_capture(const MPImage *image, int count)
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CFA);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
static const short cfapatterndim[] = {2, 2}; static const short cfapatterndim[] = { 2, 2 };
TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfapatterndim); TIFFSetField(tif, TIFFTAG_CFAREPEATPATTERNDIM, cfapatterndim);
TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR TIFFSetField(tif, TIFFTAG_CFAPATTERN, "\002\001\001\000"); // BGGR
if(camera->whitelevel) { if (camera->whitelevel) {
TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &camera->whitelevel); TIFFSetField(tif, TIFFTAG_WHITELEVEL, 1, &camera->whitelevel);
} }
if(camera->blacklevel) { if (camera->blacklevel) {
TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &camera->blacklevel); TIFFSetField(tif, TIFFTAG_BLACKLEVEL, 1, &camera->blacklevel);
} }
TIFFCheckpointDirectory(tif); TIFFCheckpointDirectory(tif);
printf("Writing frame to %s\n", fname); printf("Writing frame to %s\n", fname);
unsigned char *pLine = (unsigned char*)malloc(image->width); unsigned char *pLine = (unsigned char *)malloc(image->width);
for(int row = 0; row < image->height; row++){ for (int row = 0; row < image->height; row++) {
TIFFWriteScanline(tif, image->data + (row * image->width), row, 0); TIFFWriteScanline(tif, image->data + (row * image->width), row, 0);
} }
free(pLine); free(pLine);
@ -271,22 +262,27 @@ process_image_for_capture(const MPImage *image, int count)
TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1); TIFFSetField(tif, EXIFTAG_EXPOSUREPROGRAM, 1);
} }
TIFFSetField(tif, EXIFTAG_EXPOSURETIME, (mode.frame_interval.numerator / (float)mode.frame_interval.denominator) / ((float)image->height / (float)exposure)); TIFFSetField(tif, EXIFTAG_EXPOSURETIME,
(mode.frame_interval.numerator /
(float)mode.frame_interval.denominator) /
((float)image->height / (float)exposure));
uint16_t isospeed[1]; uint16_t isospeed[1];
isospeed[0] = (uint16_t)remap(gain - 1, 0, gain_max, camera->iso_min, camera->iso_max); 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_ISOSPEEDRATINGS, 1, isospeed);
TIFFSetField(tif, EXIFTAG_FLASH, 0); TIFFSetField(tif, EXIFTAG_FLASH, 0);
TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime); TIFFSetField(tif, EXIFTAG_DATETIMEORIGINAL, datetime);
TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime); TIFFSetField(tif, EXIFTAG_DATETIMEDIGITIZED, datetime);
if(camera->fnumber) { if (camera->fnumber) {
TIFFSetField(tif, EXIFTAG_FNUMBER, camera->fnumber); TIFFSetField(tif, EXIFTAG_FNUMBER, camera->fnumber);
} }
if(camera->focallength) { if (camera->focallength) {
TIFFSetField(tif, EXIFTAG_FOCALLENGTH, camera->focallength); TIFFSetField(tif, EXIFTAG_FOCALLENGTH, camera->focallength);
} }
if(camera->focallength && camera->cropfactor) { if (camera->focallength && camera->cropfactor) {
TIFFSetField(tif, EXIFTAG_FOCALLENGTHIN35MMFILM, (short)(camera->focallength * camera->cropfactor)); TIFFSetField(tif, EXIFTAG_FOCALLENGTHIN35MMFILM,
(short)(camera->focallength * camera->cropfactor));
} }
uint64_t exif_offset = 0; uint64_t exif_offset = 0;
TIFFWriteCustomDirectory(tif, &exif_offset); TIFFWriteCustomDirectory(tif, &exif_offset);
@ -347,7 +343,8 @@ process_image(MPPipeline *pipeline, const MPImage *image)
} }
} }
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 we haven't processed the previous frame yet, drop this one
if (frames_received != frames_processed && !is_capturing) { if (frames_received != frames_processed && !is_capturing) {
@ -357,10 +354,12 @@ void mp_process_pipeline_process_image(MPImage image)
++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 template[] = "/tmp/megapixels.XXXXXX";
char *tempdir; char *tempdir;
@ -376,7 +375,8 @@ static void capture()
captures_remaining = burst_length; captures_remaining = burst_length;
} }
void mp_process_pipeline_capture() void
mp_process_pipeline_capture()
{ {
is_capturing = true; is_capturing = true;
@ -415,7 +415,9 @@ update_state(MPPipeline *pipeline, const struct mp_process_pipeline_state *state
mp_main_update_state(&main_state); 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));
} }

View File

@ -7,12 +7,14 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
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; 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 r = 1.164f * y + 1.596f * (v - 128);
uint32_t g = 1.164f * y - 0.813f * (v - 128) - 0.391f * (u - 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); 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) { if (!colormatrix) {
return color; return color;
} }
uint32_t r = (color >> 16) * colormatrix[0] + ((color >> 8) & 0xFF) * colormatrix[1] + (color & 0xFF) * colormatrix[2]; uint32_t r = (color >> 16) * colormatrix[0] +
uint32_t g = (color >> 16) * colormatrix[3] + ((color >> 8) & 0xFF) * colormatrix[4] + (color & 0xFF) * colormatrix[5]; ((color >> 8) & 0xFF) * colormatrix[1] +
uint32_t b = (color >> 16) * colormatrix[6] + ((color >> 8) & 0xFF) * colormatrix[7] + (color & 0xFF) * colormatrix[8]; (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 // Clip colors
if (r > 0xFF) 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); 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; uint32_t x_r, y_r;
if (rotation == 0) { 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; return index;
} }
static void quick_preview_rggb8( static void
uint32_t *dst, quick_preview_rggb8(uint32_t *dst, const uint32_t dst_width,
const uint32_t dst_width, const uint32_t dst_height, const uint8_t *src,
const uint32_t dst_height, const uint32_t src_width, const uint32_t src_height,
const uint8_t *src, const MPPixelFormat format, const uint32_t rotation,
const uint32_t src_width, const bool mirrored, const float *colormatrix,
const uint32_t src_height, const uint8_t blacklevel, const uint32_t skip)
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; uint32_t src_y = 0, dst_y = 0;
while (src_y < src_height) { while (src_y < src_height) {
@ -112,7 +117,8 @@ static void quick_preview_rggb8(
color = apply_colormatrix(color, colormatrix); 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; src_x += 2 + 2 * skip;
++dst_x; ++dst_x;
@ -123,19 +129,13 @@ static void quick_preview_rggb8(
} }
} }
static void quick_preview_rggb10( static void
uint32_t *dst, quick_preview_rggb10(uint32_t *dst, const uint32_t dst_width,
const uint32_t dst_width, const uint32_t dst_height, const uint8_t *src,
const uint32_t dst_height, const uint32_t src_width, const uint32_t src_height,
const uint8_t *src, const MPPixelFormat format, const uint32_t rotation,
const uint32_t src_width, const bool mirrored, const float *colormatrix,
const uint32_t src_height, const uint8_t blacklevel, const uint32_t skip)
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); assert(src_width % 2 == 0);
@ -171,7 +171,8 @@ static void quick_preview_rggb10(
color = apply_colormatrix(color, colormatrix); 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; uint32_t advance = 1 + skip;
if (src_x % 5 == 0) { if (src_x % 5 == 0) {
@ -187,18 +188,12 @@ static void quick_preview_rggb10(
} }
} }
static void quick_preview_yuv( static void
uint32_t *dst, quick_preview_yuv(uint32_t *dst, const uint32_t dst_width, const uint32_t dst_height,
const uint32_t dst_width, const uint8_t *src, const uint32_t src_width,
const uint32_t dst_height, const uint32_t src_height, const MPPixelFormat format,
const uint8_t *src, const uint32_t rotation, const bool mirrored,
const uint32_t src_width, const float *colormatrix, const uint32_t skip)
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); assert(src_width % 2 == 0);
@ -237,13 +232,16 @@ static void quick_preview_yuv(
color1 = apply_colormatrix(color1, colormatrix); color1 = apply_colormatrix(color1, colormatrix);
color2 = apply_colormatrix(color2, 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[dst_i1] = color1;
++dst_x; ++dst_x;
// The last pixel needs to be skipped if we have an odd un-rotated width // The last pixel needs to be skipped if we have an odd un-rotated width
if (dst_x < unrot_dst_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[dst_i2] = color2;
++dst_x; ++dst_x;
} }
@ -256,92 +254,52 @@ static void quick_preview_yuv(
} }
} }
void quick_preview( void
uint32_t *dst, quick_preview(uint32_t *dst, const uint32_t dst_width, const uint32_t dst_height,
const uint32_t dst_width, const uint8_t *src, const uint32_t src_width,
const uint32_t dst_height, const uint32_t src_height, const MPPixelFormat format,
const uint8_t *src, const uint32_t rotation, const bool mirrored, const float *colormatrix,
const uint32_t src_width, const uint8_t blacklevel, const uint32_t skip)
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) { switch (format) {
case MP_PIXEL_FMT_BGGR8: case MP_PIXEL_FMT_BGGR8:
case MP_PIXEL_FMT_GBRG8: case MP_PIXEL_FMT_GBRG8:
case MP_PIXEL_FMT_GRBG8: case MP_PIXEL_FMT_GRBG8:
case MP_PIXEL_FMT_RGGB8: case MP_PIXEL_FMT_RGGB8:
quick_preview_rggb8( quick_preview_rggb8(dst, dst_width, dst_height, src, src_width,
dst, src_height, format, rotation, mirrored,
dst_width, colormatrix, blacklevel, skip);
dst_height,
src,
src_width,
src_height,
format,
rotation,
mirrored,
colormatrix,
blacklevel,
skip);
break; break;
case MP_PIXEL_FMT_BGGR10P: case MP_PIXEL_FMT_BGGR10P:
case MP_PIXEL_FMT_GBRG10P: case MP_PIXEL_FMT_GBRG10P:
case MP_PIXEL_FMT_GRBG10P: case MP_PIXEL_FMT_GRBG10P:
case MP_PIXEL_FMT_RGGB10P: case MP_PIXEL_FMT_RGGB10P:
quick_preview_rggb10( quick_preview_rggb10(dst, dst_width, dst_height, src, src_width,
dst, src_height, format, rotation, mirrored,
dst_width, colormatrix, blacklevel, skip);
dst_height,
src,
src_width,
src_height,
format,
rotation,
mirrored,
colormatrix,
blacklevel,
skip);
break; break;
case MP_PIXEL_FMT_UYVY: case MP_PIXEL_FMT_UYVY:
case MP_PIXEL_FMT_YUYV: case MP_PIXEL_FMT_YUYV:
quick_preview_yuv( quick_preview_yuv(dst, dst_width, dst_height, src, src_width,
dst, src_height, format, rotation, mirrored,
dst_width, colormatrix, skip);
dst_height,
src,
src_width,
src_height,
format,
rotation,
mirrored,
colormatrix,
skip);
break; break;
default: default:
assert(false); 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( void
uint32_t *dst_width, quick_preview_size(uint32_t *dst_width, uint32_t *dst_height, uint32_t *skip,
uint32_t *dst_height, const uint32_t preview_width, const uint32_t preview_height,
uint32_t *skip, const uint32_t src_width, const uint32_t src_height,
const uint32_t preview_width, const MPPixelFormat format, const int rotation)
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_x = mp_pixel_format_width_to_colors(format, src_width);
uint32_t colors_y = mp_pixel_format_height_to_colors(format, src_height); uint32_t colors_y = mp_pixel_format_height_to_colors(format, src_height);

View File

@ -1,27 +1,14 @@
#include "camera.h" #include "camera.h"
#include <stdint.h> #include <stdint.h>
void quick_preview( void quick_preview(uint32_t *dst, const uint32_t dst_width,
uint32_t *dst, const uint32_t dst_height, const uint8_t *src,
const uint32_t dst_width, const uint32_t src_width, const uint32_t src_height,
const uint32_t dst_height, const MPPixelFormat format, const uint32_t rotation,
const uint8_t *src, const bool mirrored, const float *colormatrix,
const uint32_t src_width, const uint8_t blacklevel, const uint32_t skip);
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( void quick_preview_size(uint32_t *dst_width, uint32_t *dst_height, uint32_t *skip,
uint32_t *dst_width, const uint32_t preview_width, const uint32_t preview_height,
uint32_t *dst_height, const uint32_t src_width, const uint32_t src_height,
uint32_t *skip, const MPPixelFormat format, const int rotation);
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);